jquery.byteLimit: Partial rewrite to fix logic errors
[lhc/web/wiklou.git] / tests / qunit / suites / resources / jquery / jquery.byteLimit.test.js
1 ( function ( $ ) {
2 var sample20simple, sample1mb, sample22mixed;
3
4 module( 'jquery.byteLimit', QUnit.newMwEnvironment() );
5
6 // Simple sample (20 chars, 20 bytes)
7 sample20simple = '1234567890abcdefghij';
8
9 // Euro-symbol (1 char, 3 bytes)
10 sample1mb = '\u20AC';
11
12 // Multi-byte sample (22 chars, 26 bytes)
13 sample22mixed = '1234567890' + sample1mb + 'abcdefghij' + sample1mb;
14
15 /**
16 * Basic emulation of character-by-charater insertion
17 * and triggering of keyup event after each character.
18 */
19 function simulateKeyUps( $input, charstr ) {
20 var i, code, event, liveVal,
21 len = charstr.length;
22 for ( i = 0; i < len; i += 1 ) {
23 // Always use the live value as base
24 liveVal = $input.val();
25
26 // Get the key code for the to-be-inserted character
27 code = charstr.charCodeAt( i );
28
29 $input.val( liveVal + charstr.charAt( i ) );
30
31 // Trigger keyup event
32 event = new jQuery.Event( 'keyup', {
33 keyCode: code,
34 charCode: code
35 } );
36 $input.trigger( event );
37 }
38 }
39
40 /**
41 * Test factory for $.fn.byteLimit
42 *
43 * @param Object options
44 */
45 function byteLimitTest( options ) {
46 var opt = $.extend({
47 description: '',
48 $input: null,
49 sample: '',
50 limit: false,
51 expected: ''
52 }, options);
53
54 test( opt.description, function () {
55 var rawVal, fn, useVal;
56
57 opt.$input.appendTo( '#qunit-fixture' );
58
59 simulateKeyUps( opt.$input, opt.sample );
60
61 rawVal = opt.$input.val();
62 fn = opt.$input.data( 'byteLimitCallback' );
63 useVal = $.isFunction( fn ) ? fn( rawVal ) : rawVal;
64
65 if ( opt.limit ) {
66 expect( 3 );
67
68 QUnit.ltOrEq(
69 $.byteLength( useVal ),
70 opt.limit,
71 'Prevent keypresses after byteLimit was reached, length never exceeded the limit'
72 );
73 equal(
74 $.byteLength( rawVal ),
75 $.byteLength( opt.expected ),
76 'Not preventing keypresses too early, length has reached the expected length'
77 );
78 equal( rawVal, opt.expected, 'New value matches the expected string' );
79
80 } else {
81 expect( 2 );
82 equal( useVal, opt.expected, 'New value matches the expected string' );
83 equal(
84 $.byteLength( useVal ),
85 $.byteLength( opt.expected ),
86 'Unlimited scenarios are not affected, expected length reached'
87 );
88 }
89 } );
90 }
91
92 test( '-- Initial check', function () {
93 expect(1);
94 ok( $.fn.byteLimit, 'jQuery.fn.byteLimit defined' );
95 } );
96
97 byteLimitTest({
98 description: 'Plain text input',
99 $input: $( '<input>' )
100 .attr( 'type', 'text' ),
101 sample: sample20simple,
102 expected: sample20simple
103 });
104
105 byteLimitTest({
106 description: 'No .byteLimit() parameters and no maxLength property - should not throw exceptions (bug 36310)',
107 $input: $( '<input>' )
108 .attr( 'type', 'text' )
109 .byteLimit(),
110 sample: sample20simple,
111 expected: sample20simple
112 });
113
114 byteLimitTest({
115 description: 'maxLength property',
116 $input: $( '<input>' )
117 .attr( 'type', 'text' )
118 .prop( 'maxLength', '10' )
119 .byteLimit(),
120 sample: sample20simple,
121 limit: 10,
122 expected: '1234567890'
123 });
124
125 byteLimitTest({
126 description: '.byteLimit( limit )',
127 $input: $( '<input>' )
128 .attr( 'type', 'text' )
129 .byteLimit( 10 ),
130 sample: sample20simple,
131 limit: 10,
132 expected: '1234567890'
133 });
134
135 byteLimitTest({
136 description: 'Limit passed to .byteLimit() takes precedence over maxLength property',
137 $input: $( '<input>' )
138 .attr( 'type', 'text' )
139 .prop( 'maxLength', '10' )
140 .byteLimit( 15 ),
141 sample: sample20simple,
142 limit: 15,
143 expected: '1234567890abcde'
144 });
145
146 byteLimitTest({
147 description: '.byteLimit( limit ) - mixed - cut in simplepart',
148 $input: $( '<input>' )
149 .attr( 'type', 'text' )
150 .byteLimit( 14 ),
151 sample: sample22mixed,
152 limit: 14,
153 expected: '1234567890' + sample1mb + 'a'
154 });
155
156 byteLimitTest({
157 description: '.byteLimit( limit ) - mixed - cut in multibyte',
158 $input: $( '<input>' )
159 .attr( 'type', 'text' )
160 .byteLimit( 12 ),
161 sample: sample22mixed,
162 limit: 12,
163 // The 3-byte symbol after 0 would have exceeded the 12 byte limit.
164 // Later when the simulation resumed typing, the two simple characters
165 // were allowed.
166 expected: '1234567890' + 'ab'
167 });
168
169 byteLimitTest({
170 description: '.byteLimit( limit, fn ) callback can alter the value to be checked against',
171 $input: $( '<input>' )
172 .attr( 'type', 'text' )
173 .byteLimit( 6, function ( val ) {
174 // Only construct mw.Title if the string is non-empty,
175 // since mw.Title throws an exception on invalid titles.
176 if ( val === '' ) {
177 return '';
178 }
179
180 // Example: Use value without namespace prefix.
181 return new mw.Title( String( val ) ).getMain();
182 } ),
183 sample: 'User:John',
184 // Limit is 6, text "User:Sample" would normally be too long,
185 // but in this case we test the callback's ability to only
186 // apply the limit to part of the input. The part "John" in this
187 // case is within the limit.
188 limit: 6,
189 // The callback only affects the comparison, the actual input field
190 // should still contain the full value.
191 expected: 'User:John'
192 });
193
194 byteLimitTest({
195 description: '.byteLimit( fn ) combined with maxLength property',
196 $input: $( '<input>' )
197 .attr( 'type', 'text' )
198 .prop( 'maxLength', '6' )
199 .byteLimit( function ( val ) {
200 // Invalid title
201 if ( val === '' ) {
202 return '';
203 }
204
205 // Return without namespace prefix
206 return new mw.Title( String( val ) ).getMain();
207 } ),
208 sample: 'User:Sample',
209 limit: 6, // 'Sample' length
210 expected: 'User:Sample'
211 });
212
213 }( jQuery ) );