scratch – Blame information for rev 134

Subversion Repositories:
Rev:
Rev Author Line No. Line
134 office 1 describe('2. Integration tests:', function() {
2  
3 before(function() {
4 require('../node_modules/jquery-simulate-ext/libs/bililiteRange');
5 require('../node_modules/jquery-simulate-ext/libs/jquery.simulate');
6  
7 // https://github.com/j-ulrich/jquery-simulate-ext/issues/9
8 // For us, it just saves a littlebit time
9 global.$.simulate.ext_disableQuirkDetection = true;
10  
11 require('../node_modules/jquery-simulate-ext/src/jquery.simulate.ext');
12 require('../node_modules/jquery-simulate-ext/src/jquery.simulate.key-combo');
13 require('../node_modules/jquery-simulate-ext/src/jquery.simulate.key-sequence');
14 });
15  
16 describe('Using an alternative delimiter', function() {
17 before(function() {
18 TFT.template = '<input type="text" class="tokenize" value="red;green;blue;yellow" />'
19 TFT.options = {
20 delimiter: ';'
21 }
22 });
23  
24 after(function() {
25 delete TFT.template;
26 delete TFT.options;
27 });
28  
29 it('must create tokens by splitting the original value with delimiters', function() {
30 this.$field.data('bs.tokenfield').$wrapper.find('.token').length.must.equal(4);
31 });
32  
33 it('must create a token when the delimiting key is pressed and use the first delimiter for setting original input value', function() {
34 this.$input.focus().simulate("key-sequence", { sequence: "purple;olive;" })
35 this.$field.data('bs.tokenfield').$wrapper.find('.token').length.must.equal(6);
36 this.$field.val().must.equal('red; green; blue; yellow; purple; olive');
37 });
38 })
39  
40 describe('with multiple alternative delimiters', function() {
41 describe("Delimiters: [' ', '.']", function() {
42 before(function() {
43 TFT.template = '<input type="text" class="tokenize" value="red green blue.yellow" />'
44 TFT.options = {
45 delimiter: [' ', '.']
46 }
47 });
48  
49 after(function() {
50 delete TFT.template;
51 delete TFT.options;
52 });
53  
54 it('must create tokens by splitting the original value with delimiters', function() {
55 this.$field.data('bs.tokenfield').$wrapper.find('.token').length.must.equal(4);
56 });
57  
58 it('must create a token when the delimiting key is pressed and use the first delimiter for setting original input value', function() {
59 this.$input.focus().simulate("key-sequence", { sequence: "purple olive." });
60 this.$field.data('bs.tokenfield').$wrapper.find('.token').length.must.equal(6);
61 this.$field.val().must.equal('red green blue yellow purple olive');
62 });
63 });
64  
65 describe("Delimiters: [',', ' ', '-', '_'] (Regression test for #79)", function() {
66 before(function() {
67 TFT.template = '<input type="text" class="tokenize" value="red,green blue-yellow_123" />'
68 TFT.options = {
69 delimiter: [',', ' ', '-', '_']
70 }
71 });
72  
73 after(function() {
74 delete TFT.template;
75 delete TFT.options;
76 });
77  
78 it('must create tokens by splitting the original value with delimiters', function() {
79 this.$field.data('bs.tokenfield').$wrapper.find('.token').length.must.equal(5);
80 });
81 });
82  
83 describe("Using regexp special characters as delimiters", function() {
84 before(function() {
85 TFT.template = '<input type="text" class="tokenize" value="red\\green$blue[yellow{orange^violet.purple|black?white*gray+silver(lime)navy" />'
86 TFT.options = {
87 delimiter: ['\\', '$', '[', '{', '^', '.', '|', '?', '*', '+', '(', ')']
88 }
89 });
90  
91 after(function() {
92 delete TFT.template;
93 delete TFT.options;
94 });
95  
96 it('must create tokens by splitting the original value with delimiters', function() {
97 this.$field.data('bs.tokenfield').$wrapper.find('.token').length.must.equal(13);
98 });
99 });
100 });
101  
102 describe('Keyboard interaction', function() {
103  
104 describe("Pressing Ctrl+A", function() {
105 before(function() {
106 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
107 });
108  
109 after(function() {
110 delete TFT.template;
111 });
112  
113 it("must select all tokens", function() {
114 this.$input.focus().simulate("key-combo", { combo: "ctrl+a" });
115 this.$field.tokenfield('getTokens', true).length.must.equal(3);
116 });
117 });
118  
119 describe("pressing Cmd+A", function() {
120 before(function() {
121 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
122 });
123  
124 after(function() {
125 delete TFT.template;
126 });
127  
128 it("must select all tokens", function() {
129 this.$input.focus().simulate("key-combo", { combo: "meta+a" });
130 this.$field.tokenfield('getTokens', true).length.must.equal(3);
131 });
132 });
133  
134 describe("Pressing delete", function() {
135 describe("when a token is selected", function() {
136 before(function() {
137 TFT.template = '<input type="text" class="tokenize" value="red,green,blue,yellow" />'
138 });
139  
140 after(function() {
141 delete TFT.template;
142 });
143  
144 describe('and there are more tokens to the right of selected token', function() {
145 it("must delete the selected token and move focus to the next token", function() {
146 // Mark green as active
147 this.$wrapper.find('.token')
148 .filter(':has(.token-label:contains(green))').addClass('active');
149  
150 this.$copyHelper.simulate("key-sequence", { sequence: "{del}" });
151 this.$field.tokenfield('getTokens').length.must.equal(3);
152 this.$field.tokenfield('getTokensList', null, null, true).must.equal('blue');
153 });
154 })
155  
156 describe('and there are no more tokens to the right of the selected token', function() {
157 it("must delete the selected token and move focus to input", function() {
158 // Mark green as active
159 this.$wrapper.find('.token')
160 .filter(':has(.token-label:contains(yellow))').addClass('active');
161  
162 this.$copyHelper.simulate("key-sequence", { sequence: "{del}" });
163 this.$field.tokenfield('getTokens').length.must.equal(3);
164 this.$field.tokenfield('getTokensList', null, null, true).must.equal('');
165 this.$input.is(document.activeElement).must.be.true();
166 });
167 })
168 });
169  
170 describe("when multiple tokens are selected", function() {
171 before(function() {
172 TFT.template = '<input type="text" class="tokenize" value="red,green,blue,yellow,purple" />'
173 });
174  
175 after(function() {
176 delete TFT.template;
177 });
178  
179 describe('and there are more tokens to the right of selected tokens', function() {
180 it("must delete the selected tokens and move focus to the next token of the rightmost selected token", function() {
181 // Mark green and yellow as active
182 this.$wrapper.find('.token')
183 .filter(':has(.token-label:contains(green))').addClass('active');
184 this.$wrapper.find('.token')
185 .filter(':has(.token-label:contains(yellow))').addClass('active');
186  
187 this.$copyHelper.simulate("key-sequence", { sequence: "{del}" });
188 this.$field.tokenfield('getTokens').length.must.equal(3);
189 this.$field.tokenfield('getTokensList', null, null, true).must.equal('purple');
190 });
191 });
192  
193 describe('and there are no more tokens to the right of selected tokens', function() {
194 it("must delete the selected tokens and move focus input", function() {
195 // Mark green and yellow as active
196 this.$wrapper.find('.token')
197 .filter(':has(.token-label:contains(green))').addClass('active');
198 this.$wrapper.find('.token')
199 .filter(':has(.token-label:contains(purple))').addClass('active');
200  
201 this.$copyHelper.simulate("key-sequence", { sequence: "{del}" });
202 this.$field.tokenfield('getTokens').length.must.equal(3);
203 this.$field.tokenfield('getTokensList').must.equal('red, blue, yellow');
204 this.$input.is(document.activeElement).must.be.true();
205  
206 });
207 });
208 });
209 });
210  
211 describe("Pressing backspace", function() {
212 describe("when a token is selected", function() {
213 before(function() {
214 TFT.template = '<input type="text" class="tokenize" value="red,green,blue,yellow" />'
215 });
216  
217 after(function() {
218 delete TFT.template;
219 });
220  
221 describe('and there are more tokens to the left of selected token', function() {
222 it("must delete the selected token and move focus to the previous token", function() {
223 // Mark green as active
224 this.$wrapper.find('.token')
225 .filter(':has(.token-label:contains(blue))').addClass('active');
226  
227 this.$copyHelper.simulate("key-sequence", { sequence: "{backspace}" });
228 this.$field.tokenfield('getTokens').length.must.equal(3);
229 this.$field.tokenfield('getTokensList', null, null, true).must.equal('green');
230 });
231 })
232  
233 describe('and there are no more tokens to the left of the selected token', function() {
234 it("must delete the selected token and move focus to input", function() {
235 // Mark green as active
236 this.$wrapper.find('.token')
237 .filter(':has(.token-label:contains(red))').addClass('active');
238  
239 this.$copyHelper.simulate("key-sequence", { sequence: "{backspace}" });
240 this.$field.tokenfield('getTokens').length.must.equal(3);
241 this.$field.tokenfield('getTokensList', null, null, true).must.equal('');
242 this.$input.is(document.activeElement).must.be.true();
243 });
244 })
245 });
246  
247 describe("when multiple tokens are selected", function() {
248 before(function() {
249 TFT.template = '<input type="text" class="tokenize" value="red,green,blue,yellow,purple" />'
250 });
251  
252 after(function() {
253 delete TFT.template;
254 });
255  
256 describe('and there are more tokens to the left of selected tokens', function() {
257 it("must delete the selected tokens and move focus to the previous token of the leftmost selected token", function() {
258 // Mark green and yellow as active
259 this.$wrapper.find('.token')
260 .filter(':has(.token-label:contains(green))').addClass('active');
261 this.$wrapper.find('.token')
262 .filter(':has(.token-label:contains(yellow))').addClass('active');
263  
264 this.$copyHelper.simulate("key-sequence", { sequence: "{backspace}" });
265 this.$field.tokenfield('getTokens').length.must.equal(3);
266 this.$field.tokenfield('getTokensList', null, null, true).must.equal('red');
267 });
268 });
269  
270 describe('and there are no more tokens to the left of selected tokens', function() {
271 it("must delete the selected tokens and move focus input", function() {
272 // Mark green and yellow as active
273 this.$wrapper.find('.token')
274 .filter(':has(.token-label:contains(red))').addClass('active');
275 this.$wrapper.find('.token')
276 .filter(':has(.token-label:contains(purple))').addClass('active');
277  
278 this.$copyHelper.simulate("key-sequence", { sequence: "{backspace}" });
279 this.$field.tokenfield('getTokens').length.must.equal(3);
280 this.$field.tokenfield('getTokensList').must.equal('green, blue, yellow');
281 this.$input.is(document.activeElement).must.be.true();
282 });
283 });
284 });
285  
286 describe("when focus is on input", function() {
287 before(function() {
288 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
289 });
290  
291 after(function() {
292 delete TFT.template;
293 });
294  
295 it("must move focus to the last token", function() {
296 this.$input.simulate("key-sequence", { sequence: "{backspace}" });
297 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('blue');
298 });
299 });
300 });
301  
302 describe("Pressing left arrow key", function() {
303 describe("when no tokens are selected", function() {
304 before(function() {
305 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
306 });
307  
308 after(function() {
309 delete TFT.template;
310 });
311  
312 it("must move focus to the last token", function() {
313 this.$input.simulate("key-sequence", { sequence: "{leftarrow}" });
314 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('blue');
315 });
316 });
317  
318 describe("when a token is selected", function() {
319 before(function() {
320 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
321 });
322  
323 after(function() {
324 delete TFT.template;
325 });
326  
327 it("must move focus to the previous token", function() {
328 this.$wrapper.find('.token')
329 .filter(':has(.token-label:contains(blue))').addClass('active');
330  
331 this.$copyHelper.simulate("key-sequence", { sequence: "{leftarrow}" });
332 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('green');
333 });
334 });
335  
336 describe("when multiple tokens are selected", function() {
337 before(function() {
338 TFT.template = '<input type="text" class="tokenize" value="red,green,blue,yellow" />'
339 });
340  
341 after(function() {
342 delete TFT.template;
343 });
344  
345 it("must move focus to the previous token of the leftmost selected token", function() {
346 this.$wrapper.find('.token')
347 .filter(':has(.token-label:contains(green))').addClass('active');
348 this.$wrapper.find('.token')
349 .filter(':has(.token-label:contains(yellow))').addClass('active');
350  
351 this.$copyHelper.simulate("key-sequence", { sequence: "{leftarrow}" });
352 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('red');
353 });
354 });
355  
356 describe("when the first token is selected", function() {
357 before(function() {
358 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
359 });
360  
361 after(function() {
362 delete TFT.template;
363 });
364  
365 it("must keep the focus on the first token", function() {
366 this.$wrapper.find('.token')
367 .filter(':has(.token-label:contains(red))').addClass('active');
368  
369 this.$copyHelper.simulate("key-sequence", { sequence: "{leftarrow}" });
370 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('red');
371 });
372 });
373  
374 describe("when no tokens are selected and direction is RTL", function() {
375 before(function() {
376 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" style="direction:rtl" />'
377 });
378  
379 after(function() {
380 delete TFT.template;
381 });
382  
383 it("must keep the focus on the input", function() {
384 this.$input.simulate("key-sequence", { sequence: "{leftarrow}" });
385 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('');
386 this.$input.is(document.activeElement).must.be.true();
387 });
388 });
389 });
390  
391 describe("Pressing right arrow key", function() {
392 describe("when no tokens are selected", function() {
393 before(function() {
394 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
395 });
396  
397 after(function() {
398 delete TFT.template;
399 });
400  
401 it("must keep the focus on the input", function() {
402 this.$input.simulate("key-sequence", { sequence: "{rightarrow}" });
403 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('');
404 this.$input.is(document.activeElement).must.be.true();
405 });
406 });
407  
408 describe("when a token is selected", function() {
409 before(function() {
410 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
411 });
412  
413 after(function() {
414 delete TFT.template;
415 });
416  
417 it("must move focus to the next token", function() {
418 this.$wrapper.find('.token')
419 .filter(':has(.token-label:contains(red))').addClass('active');
420  
421 this.$copyHelper.simulate("key-sequence", { sequence: "{rightarrow}" });
422 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('green');
423 });
424 });
425  
426 describe("when multiple tokens are selected", function() {
427 before(function() {
428 TFT.template = '<input type="text" class="tokenize" value="red,green,blue,yellow" />'
429 });
430  
431 after(function() {
432 delete TFT.template;
433 });
434  
435 it("must move focus to the next token of the rightmost selected token", function() {
436 this.$wrapper.find('.token')
437 .filter(':has(.token-label:contains(red))').addClass('active');
438 this.$wrapper.find('.token')
439 .filter(':has(.token-label:contains(blue))').addClass('active');
440  
441 this.$copyHelper.simulate("key-sequence", { sequence: "{rightarrow}" });
442 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('yellow');
443 });
444 });
445  
446 describe("when the last token is selected", function() {
447 before(function() {
448 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
449 });
450  
451 after(function() {
452 delete TFT.template;
453 });
454  
455 it("must move the focus to the input", function() {
456 this.$wrapper.find('.token')
457 .filter(':has(.token-label:contains(blue))').addClass('active');
458  
459 this.$copyHelper.simulate("key-sequence", { sequence: "{rightarrow}" });
460 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('');
461 this.$input.is(document.activeElement).must.be.true();
462 });
463 });
464  
465 describe("when no tokens are selected and direction is RTL", function() {
466 before(function() {
467 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" style="direction:rtl" />'
468 });
469  
470 after(function() {
471 delete TFT.template;
472 });
473  
474 it("must move focus to the last token", function() {
475 this.$input.simulate("key-sequence", { sequence: "{rightarrow}" });
476 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('blue');
477 });
478 });
479 });
480  
481 describe("Pressing Shift + left arrow key", function() {
482 describe("when no tokens are selected", function() {
483 before(function() {
484 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
485 });
486  
487 after(function() {
488 delete TFT.template;
489 });
490  
491 it("must move focus to the last token", function() {
492 this.$input.focus().simulate("keydown", { keyCode: 37, charCode: 37, shiftKey: true });
493 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('blue');
494 });
495 });
496  
497 describe("when a token is selected", function() {
498 before(function() {
499 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
500 });
501  
502 after(function() {
503 delete TFT.template;
504 });
505  
506 it("must activate the previous token in addition to the already active token", function() {
507 this.$wrapper.find('.token')
508 .filter(':has(.token-label:contains(blue))').addClass('active');
509  
510 this.$copyHelper.focus()
511 .simulate("keydown", { keyCode: 37, shiftKey: true })
512 .simulate("keydown", { keyCode: 37, shiftKey: true });
513 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('red, green, blue');
514 });
515 });
516  
517 describe("when multiple, non-adjacent tokens are selected", function() {
518 before(function() {
519 TFT.template = '<input type="text" class="tokenize" value="red,green,blue,yellow,purple" />'
520 });
521  
522 after(function() {
523 delete TFT.template;
524 });
525  
526 it("must move select the previous token of the leftmost selected token in addition to the already selected tokens", function() {
527 this.$wrapper.find('.token')
528 .filter(':has(.token-label:contains(green))').addClass('active');
529 this.$wrapper.find('.token')
530 .filter(':has(.token-label:contains(yellow))').addClass('active');
531  
532 this.$copyHelper.focus().simulate("keydown", { keyCode: 37, shiftKey: true });
533 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('red, green, yellow');
534 });
535 });
536 });
537  
538 describe("Pressing Shift + right arrow key", function() {
539 describe("when a token is selected", function() {
540 before(function() {
541 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
542 });
543  
544 after(function() {
545 delete TFT.template;
546 });
547  
548 it("must activate the next token in addition to the already active token", function() {
549 this.$wrapper.find('.token')
550 .filter(':has(.token-label:contains(red))').addClass('active');
551  
552 this.$copyHelper.focus()
553 .simulate("keydown", { keyCode: 39, shiftKey: true })
554 .simulate("keydown", { keyCode: 39, shiftKey: true });
555 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('red, green, blue');
556 });
557 });
558  
559 describe("when multiple, non-adjacent tokens are selected", function() {
560 before(function() {
561 TFT.template = '<input type="text" class="tokenize" value="red,green,blue,yellow,purple" />'
562 });
563  
564 after(function() {
565 delete TFT.template;
566 });
567  
568 it("must move select the next token of the rightmost selected token in addition to the already selected tokens", function() {
569 this.$wrapper.find('.token')
570 .filter(':has(.token-label:contains(green))').addClass('active');
571 this.$wrapper.find('.token')
572 .filter(':has(.token-label:contains(yellow))').addClass('active');
573  
574 this.$copyHelper.focus().simulate("keydown", { keyCode: 39, shiftKey: true });
575 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('green, yellow, purple');
576 });
577 });
578 });
579  
580 describe("Pressing Enter key", function() {
581 describe("when a token is selected", function() {
582 before(function() {
583 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
584 });
585  
586 after(function() {
587 delete TFT.template;
588 });
589  
590 it("must enter edit mode for the active token", function() {
591 this.$wrapper.find('.token')
592 .filter(':has(.token-label:contains(green))').addClass('active');
593  
594 this.$copyHelper.simulate("key-sequence", { sequence: "{enter}" });
595 this.$input.data('edit').must.be.true();
596 this.$input.prev(':contains(red)').must.have.length(1);
597 this.$input.next(':contains(blue)').must.have.length(1);
598 });
599 });
600  
601 describe("when a token is selected and allowEditing is false", function() {
602 before(function() {
603 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />';
604 TFT.options = { allowEditing: false }
605 });
606  
607 after(function() {
608 delete TFT.template;
609 delete TFT.options;
610 });
611  
612 it("must not enter edit mode for the active token [no data('edit') property]", function() {
613 this.$wrapper.find('.token')
614 .filter(':has(.token-label:contains(green))').addClass('active');
615  
616 this.$copyHelper.simulate("key-sequence", { sequence: "{enter}" });
617 this.$input.data().must.not.have.property('edit');
618 });
619 });
620  
621 describe("when input has text", function() {
622 before(function() {
623 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
624 });
625  
626 after(function() {
627 delete TFT.template;
628 });
629  
630 it("must create a new token from the input", function() {
631  
632 this.$input.simulate("key-sequence", { sequence: "purple{enter}" });
633 this.$field.tokenfield('getTokens').must.have.length(4);
634 });
635 });
636 });
637  
638 describe("Pressing Tab key", function() {
639 describe("when input has text", function() {
640 before(function() {
641 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
642 });
643  
644 after(function() {
645 delete TFT.template;
646 });
647  
648 it("must create a new token from the input", function() {
649  
650 this.$input.focus().simulate("key-sequence", { sequence: "purple" });
651 this.$input.simulate("keydown", { keyCode: 9 });
652 this.$field.tokenfield('getTokens').must.have.length(4);
653 });
654 });
655 });
656 });
657  
658 describe("Mouse interaction", function() {
659  
660 describe("Clicking on a token", function() {
661 before(function() {
662 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
663 });
664  
665 after(function() {
666 delete TFT.template;
667 });
668  
669 it("must select the token and deactivate any other active tokens", function() {
670 this.$wrapper.find('.token')
671 .filter(':has(.token-label:contains(green))').addClass('active');
672  
673 this.$wrapper.find('.token:contains(red)').click();
674 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('red');
675 });
676 });
677  
678 describe("Clicking on a token's remove icon", function() {
679 before(function() {
680 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
681 });
682  
683 after(function() {
684 delete TFT.template;
685 });
686  
687 it("must remove the token", function() {
688 this.$wrapper.find('.token:contains(red)').find('.close').click();
689 this.$field.tokenfield('getTokensList' ).must.equal('green, blue');
690 });
691 });
692  
693 describe("Double-clicking on a token", function() {
694 before(function() {
695 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
696 });
697  
698 after(function() {
699 delete TFT.template;
700 });
701  
702 it("must enter the edit mode of the token", function() {
703 this.$wrapper.find('.token')
704 .filter(':has(.token-label:contains(green))').addClass('active');
705  
706 this.$wrapper.find('.token:contains(red)').dblclick();
707 this.$input.data('edit').must.be.true();
708 this.$input.next(':contains(green)').must.have.length(1);
709 });
710 });
711  
712 describe("must not enter the edit mode of the token when allowEditing false", function() {
713 before(function() {
714 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />';
715 TFT.options = { allowEditing: false }
716 });
717  
718 after(function() {
719 delete TFT.template;
720 delete TFT.options;
721 });
722  
723 it("must not enter the edit mode of the token", function() {
724 this.$wrapper.find('.token:contains(red)').dblclick();
725 this.$input.data().must.not.have.property('edit');
726 });
727 });
728  
729 describe("Ctrl-clicking on a token when another token is selected", function() {
730 before(function() {
731 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
732 });
733  
734 after(function() {
735 delete TFT.template;
736 });
737  
738 it("must activate the token in addition to the already active token", function() {
739 this.$wrapper.find('.token')
740 .filter(':has(.token-label:contains(green))').addClass('active');
741  
742 this.$wrapper.find('.token:contains(red)').simulate('click', { ctrlKey: true });
743 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('red, green');
744 });
745 });
746  
747 describe("Shift-clicking on a token when another token is selected", function() {
748 before(function() {
749 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
750 });
751  
752 after(function() {
753 delete TFT.template;
754 });
755  
756 it("must activate the token and all the tokens between the already active token", function() {
757 this.$wrapper.find('.token:contains(blue)').simulate('click');
758 this.$wrapper.find('.token:contains(red)').simulate('click', { shiftKey: true });
759 this.$field.tokenfield('getTokensList', null, null, true ).must.equal('red, green, blue');
760 });
761 });
762  
763 describe("Pressing enter when there is no input", function() {
764 var submitted = false;
765  
766 before(function() {
767 TFT.template = '<form method="post" action=""><input type="text" class="tokenize" value="red,green,blue" /><input type="submit"></form>';
768 });
769  
770 after(function() {
771 delete TFT.template;
772 });
773  
774 beforeEach(function() {
775 this.$sandbox.find('form').on('submit', function(e) {
776 submitted = true;
777 e.preventDefault();
778 return false;
779 });
780 // key-sequence does not trigger submit event on the form when pressing enter
781 // so we need to trigger it manually. Not really a solid test-case, but oh well
782 // https://github.com/j-ulrich/jquery-simulate-ext/pull/14
783 this.$input.focus().simulate("key-sequence", { sequence: "{enter}" }).trigger('submit');
784 });
785  
786 it("must submit the underlying form", function() {
787 submitted.must.equal(true);
788 });
789 });
790 });
791  
792 describe("Events", function() {
793  
794 describe("tokenfield:initialize", function() {
795 it("must must be triggered when tokenfield is created", function (done) {
796 $('<input type="text" />')
797 .on('tokenfield:initialize', function() {
798 done();
799 })
800 .tokenfield();
801 });
802 });
803  
804 describe("tokenfield:createtoken", function() {
805 it("must allow changing token label and value", function() {
806 this.$field.on('tokenfield:createtoken', function (e) {
807 e.attrs.value = 'one';
808 e.attrs.label = 'two';
809 });
810 this.$field.tokenfield('createToken', 'zero');
811  
812 var results = this.$field.tokenfield('getTokens');
813 results[0].label.must.equal('two');
814 results[0].value.must.equal('one');
815 });
816  
817 it("must allow setting token value to an empty string", function() {
818 this.$field.on('tokenfield:createtoken', function (e) {
819 e.attrs.value = '';
820 });
821 this.$field.tokenfield('createToken', 'zero');
822  
823 var results = this.$field.tokenfield('getTokens');
824 results[0].label.must.equal('zero');
825 results[0].value.must.equal('');
826 });
827  
828 it("must allow canceling createtoken by setting token to a falsy value", function() {
829 this.$field.on('tokenfield:createtoken', function (e) {
830 e.attrs = false;
831 });
832 this.$field.tokenfield('createToken', 'yellow');
833  
834 var results = this.$field.tokenfield('getTokens');
835 results.must.have.length(0);
836 });
837  
838 it("must allow canceling createtoken by calling event.preventDefault()", function() {
839 this.$field.on('tokenfield:createtoken', function (e) {
840 e.preventDefault();
841 });
842 this.$field.tokenfield('createToken', 'yellow');
843  
844 var results = this.$field.tokenfield('getTokens');
845 results.must.have.length(0);
846 });
847  
848 it("must allow canceling createtoken by returning false in the event handler", function() {
849 this.$field.on('tokenfield:createtoken', function (e) {
850 return false;
851 });
852 this.$field.tokenfield('createToken', 'yellow');
853  
854 var results = this.$field.tokenfield('getTokens');
855 results.must.have.length(0);
856 });
857 });
858  
859 describe("tokenfield:createdtoken", function() {
860 it("must be triggered when a token is created and in the DOM", function (done) {
861 var self = this;
862  
863 this.$field.on('tokenfield:createdtoken', function (e) {
864 e.attrs.must.be.an.object();
865 e.attrs.label.must.eql('red');
866 e.attrs.value.must.eql('red');
867 e.relatedTarget.must.be.an.object();
868  
869 self.$wrapper.find(e.relatedTarget).must.have.length(1);
870  
871 done();
872 });
873  
874 this.$field.tokenfield('createToken', 'red');
875 });
876 });
877  
878 describe("tokenfield:edittoken", function() {
879 before(function() {
880 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
881 });
882  
883 after(function() {
884 delete TFT.template;
885 });
886  
887 it("must be triggered when a token is edited", function (done) {
888 this.$field.on('tokenfield:edittoken', function (e) {
889 e.attrs.must.be.an.object();
890 e.attrs.label.must.eql('red');
891 e.attrs.value.must.eql('red');
892 e.relatedTarget.must.be.an.object();
893 done();
894 });
895  
896 this.$wrapper.find('.token')
897 .filter(':has(.token-label:contains(red))').addClass('active');
898  
899 this.$copyHelper.simulate("key-sequence", { sequence: "{enter}" });
900 });
901  
902 it("must allow canceling the default event handler by calling event.preventDefault()", function() {
903 this.$field.on('tokenfield:edittoken', function (e) {
904 e.preventDefault();
905 });
906  
907 this.$wrapper.find('.token')
908 .filter(':has(.token-label:contains(red))').addClass('active');
909  
910 this.$copyHelper.simulate("key-sequence", { sequence: "{enter}" });
911  
912 this.$input.data().must.not.have.property('edit');
913 });
914  
915 it("must allow canceling the default event handler by returning false in the event handler", function() {
916 this.$field.on('tokenfield:edittoken', function (e) {
917 return false;
918 });
919  
920 this.$wrapper.find('.token')
921 .filter(':has(.token-label:contains(red))').addClass('active');
922  
923 this.$copyHelper.simulate("key-sequence", { sequence: "{enter}" });
924  
925 this.$input.data().must.not.have.property('edit');
926 });
927 });
928  
929 describe("tokenfield:editedtoken", function() {
930 before(function() {
931 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
932 });
933  
934 after(function() {
935 delete TFT.template;
936 });
937  
938 it("must be triggered when a token is now being edited (replaced with an input in the DOM)", function (done) {
939 var self = this;
940  
941 this.$field.on('tokenfield:editedtoken', function (e) {
942 e.attrs.must.be.an.object();
943 e.attrs.label.must.eql('red');
944 e.attrs.value.must.eql('red');
945 e.relatedTarget.must.be.an.object();
946  
947 self.$wrapper.find(e.relatedTarget).must.have.length(0);
948  
949 done();
950 });
951  
952 this.$wrapper.find('.token')
953 .filter(':has(.token-label:contains(red))').addClass('active');
954  
955 this.$copyHelper.simulate("key-sequence", { sequence: "{enter}" });
956 });
957 });
958  
959 describe("tokenfield:removetoken", function() {
960 before(function() {
961 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
962 });
963  
964 after(function() {
965 delete TFT.template;
966 });
967  
968 it("must be triggered when a token is about to be removed", function (done) {
969 this.$field.on('tokenfield:removetoken', function (e) {
970 e.attrs.must.be.an.object();
971 e.attrs.label.must.eql('red');
972 e.attrs.value.must.eql('red');
973 done();
974 });
975  
976 this.$wrapper.find('.token:first').find('.close').click();
977 });
978  
979 it("must allow canceling the default event handler by calling event.preventDefault()", function() {
980 this.$field.on('tokenfield:removetoken', function (e) {
981 e.preventDefault();
982 });
983  
984 this.$wrapper.find('.token:first').find('.close').click();
985  
986 this.$field.tokenfield('getTokens').must.have.length(3);
987 });
988  
989 it("must allow canceling the default event handler by returning false in the event handler", function() {
990 this.$field.on('tokenfield:removetoken', function (e) {
991 return false;
992 });
993  
994 this.$wrapper.find('.token:first').find('.close').click();
995  
996 this.$field.tokenfield('getTokens').must.have.length(3);
997 });
998 });
999  
1000 describe("tokenfield:removedtoken", function() {
1001 before(function() {
1002 TFT.template = '<input type="text" class="tokenize" value="red,green,blue" />'
1003 });
1004  
1005 after(function() {
1006 delete TFT.template;
1007 });
1008  
1009 it("must be triggered when a token is removed from the DOM", function (done) {
1010 var self = this;
1011  
1012 this.$field.on('tokenfield:removedtoken', function (e) {
1013 e.attrs.must.be.an.object();
1014 e.attrs.label.must.eql('red');
1015 e.attrs.value.must.eql('red');
1016  
1017 self.$wrapper.find(e.relatedTarget).length.must.equal(0);
1018  
1019 done();
1020 });
1021  
1022 this.$wrapper.find('.token:first').find('.close').click();
1023 });
1024 });
1025  
1026 });
1027  
1028 });