qunit: Update tests to not assume animations use setTimeout
[lhc/web/wiklou.git] / tests / qunit / suites / resources / jquery / jquery.makeCollapsible.test.js
1 ( function ( mw, $ ) {
2 var loremIpsum = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.';
3
4 QUnit.module( 'jquery.makeCollapsible', QUnit.newMwEnvironment() );
5
6 function prepareCollapsible( html, options ) {
7 return $( $.parseHTML( html ) )
8 .appendTo( '#qunit-fixture' )
9 // options might be undefined here - this is okay
10 .makeCollapsible( options );
11 }
12
13 // This test is first because if it fails, then almost all of the latter tests are meaningless.
14 QUnit.test( 'testing hooks/triggers', 4, function ( assert ) {
15 var test = this,
16 $collapsible = prepareCollapsible(
17 '<div class="mw-collapsible">' + loremIpsum + '</div>'
18 ),
19 $content = $collapsible.find( '.mw-collapsible-content' ),
20 $toggle = $collapsible.find( '.mw-collapsible-toggle' );
21
22 // In one full collapse-expand cycle, each event will be fired once
23
24 // On collapse...
25 $collapsible.on( 'beforeCollapse.mw-collapsible', function () {
26 assert.assertTrue( $content.is( ':visible' ), 'first beforeCollapseExpand: content is visible' );
27 } );
28 $collapsible.on( 'afterCollapse.mw-collapsible', function () {
29 assert.assertTrue( $content.is( ':hidden' ), 'first afterCollapseExpand: content is hidden' );
30
31 // On expand...
32 $collapsible.on( 'beforeExpand.mw-collapsible', function () {
33 assert.assertTrue( $content.is( ':hidden' ), 'second beforeCollapseExpand: content is hidden' );
34 } );
35 $collapsible.on( 'afterExpand.mw-collapsible', function () {
36 assert.assertTrue( $content.is( ':visible' ), 'second afterCollapseExpand: content is visible' );
37 } );
38
39 // ...expanding happens here
40 $toggle.trigger( 'click' );
41 } );
42
43 // ...collapsing happens here
44 $toggle.trigger( 'click' );
45 } );
46
47 QUnit.test( 'basic operation (<div>)', 5, function ( assert ) {
48 var test = this,
49 $collapsible = prepareCollapsible(
50 '<div class="mw-collapsible">' + loremIpsum + '</div>'
51 ),
52 $content = $collapsible.find( '.mw-collapsible-content' ),
53 $toggle = $collapsible.find( '.mw-collapsible-toggle' );
54
55 assert.equal( $content.length, 1, 'content is present' );
56 assert.equal( $content.find( $toggle ).length, 0, 'toggle is not a descendant of content' );
57
58 assert.assertTrue( $content.is( ':visible' ), 'content is visible' );
59
60 $collapsible.on( 'afterCollapse.mw-collapsible', function () {
61 assert.assertTrue( $content.is( ':hidden' ), 'after collapsing: content is hidden' );
62
63 $collapsible.on( 'afterExpand.mw-collapsible', function () {
64 assert.assertTrue( $content.is( ':visible' ), 'after expanding: content is visible' );
65 } );
66
67 $toggle.trigger( 'click' );
68 } );
69
70 $toggle.trigger( 'click' );
71 } );
72
73 QUnit.test( 'basic operation (<table>)', 7, function ( assert ) {
74 var test = this,
75 $collapsible = prepareCollapsible(
76 '<table class="mw-collapsible">' +
77 '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
78 '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
79 '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
80 '</table>'
81 ),
82 $headerRow = $collapsible.find( 'tr:first' ),
83 $contentRow = $collapsible.find( 'tr:last' ),
84 $toggle = $headerRow.find( 'td:last .mw-collapsible-toggle' );
85
86 assert.equal( $toggle.length, 1, 'toggle is added to last cell of first row' );
87
88 assert.assertTrue( $headerRow.is( ':visible' ), 'headerRow is visible' );
89 assert.assertTrue( $contentRow.is( ':visible' ), 'contentRow is visible' );
90
91 $collapsible.on( 'afterCollapse.mw-collapsible', function () {
92 assert.assertTrue( $headerRow.is( ':visible' ), 'after collapsing: headerRow is still visible' );
93 assert.assertTrue( $contentRow.is( ':hidden' ), 'after collapsing: contentRow is hidden' );
94
95 $collapsible.on( 'afterExpand.mw-collapsible', function () {
96 assert.assertTrue( $headerRow.is( ':visible' ), 'after expanding: headerRow is still visible' );
97 assert.assertTrue( $contentRow.is( ':visible' ), 'after expanding: contentRow is visible' );
98 } );
99
100 $toggle.trigger( 'click' );
101 } );
102
103 $toggle.trigger( 'click' );
104 } );
105
106 function tableWithCaptionTest( $collapsible, test, assert ) {
107 var $caption = $collapsible.find( 'caption' ),
108 $headerRow = $collapsible.find( 'tr:first' ),
109 $contentRow = $collapsible.find( 'tr:last' ),
110 $toggle = $caption.find( '.mw-collapsible-toggle' );
111
112 assert.equal( $toggle.length, 1, 'toggle is added to the end of the caption' );
113
114 assert.assertTrue( $caption.is( ':visible' ), 'caption is visible' );
115 assert.assertTrue( $headerRow.is( ':visible' ), 'headerRow is visible' );
116 assert.assertTrue( $contentRow.is( ':visible' ), 'contentRow is visible' );
117
118 $collapsible.on( 'afterCollapse.mw-collapsible', function () {
119 assert.assertTrue( $caption.is( ':visible' ), 'after collapsing: caption is still visible' );
120 assert.assertTrue( $headerRow.is( ':hidden' ), 'after collapsing: headerRow is hidden' );
121 assert.assertTrue( $contentRow.is( ':hidden' ), 'after collapsing: contentRow is hidden' );
122
123 $collapsible.on( 'afterExpand.mw-collapsible', function () {
124 assert.assertTrue( $caption.is( ':visible' ), 'after expanding: caption is still visible' );
125 assert.assertTrue( $headerRow.is( ':visible' ), 'after expanding: headerRow is visible' );
126 assert.assertTrue( $contentRow.is( ':visible' ), 'after expanding: contentRow is visible' );
127 } );
128
129 $toggle.trigger( 'click' );
130 } );
131
132 $toggle.trigger( 'click' );
133 }
134
135 QUnit.test( 'basic operation (<table> with caption)', 10, function ( assert ) {
136 tableWithCaptionTest( prepareCollapsible(
137 '<table class="mw-collapsible">' +
138 '<caption>' + loremIpsum + '</caption>' +
139 '<tr><th>' + loremIpsum + '</th><th>' + loremIpsum + '</th></tr>' +
140 '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
141 '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
142 '</table>'
143 ), this, assert );
144 } );
145
146 QUnit.test( 'basic operation (<table> with caption and <thead>)', 10, function ( assert ) {
147 tableWithCaptionTest( prepareCollapsible(
148 '<table class="mw-collapsible">' +
149 '<caption>' + loremIpsum + '</caption>' +
150 '<thead><tr><th>' + loremIpsum + '</th><th>' + loremIpsum + '</th></tr></thead>' +
151 '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
152 '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
153 '</table>'
154 ), this, assert );
155 } );
156
157 function listTest( listType, test, assert ) {
158 var $collapsible = prepareCollapsible(
159 '<' + listType + ' class="mw-collapsible">' +
160 '<li>' + loremIpsum + '</li>' +
161 '<li>' + loremIpsum + '</li>' +
162 '</' + listType + '>'
163 ),
164 $toggleItem = $collapsible.find( 'li.mw-collapsible-toggle-li:first-child' ),
165 $contentItem = $collapsible.find( 'li:last' ),
166 $toggle = $toggleItem.find( '.mw-collapsible-toggle' );
167
168 assert.equal( $toggle.length, 1, 'toggle is present, added inside new zeroth list item' );
169
170 assert.assertTrue( $toggleItem.is( ':visible' ), 'toggleItem is visible' );
171 assert.assertTrue( $contentItem.is( ':visible' ), 'contentItem is visible' );
172
173 $collapsible.on( 'afterCollapse.mw-collapsible', function () {
174 assert.assertTrue( $toggleItem.is( ':visible' ), 'after collapsing: toggleItem is still visible' );
175 assert.assertTrue( $contentItem.is( ':hidden' ), 'after collapsing: contentItem is hidden' );
176
177 $collapsible.on( 'afterExpand.mw-collapsible', function () {
178 assert.assertTrue( $toggleItem.is( ':visible' ), 'after expanding: toggleItem is still visible' );
179 assert.assertTrue( $contentItem.is( ':visible' ), 'after expanding: contentItem is visible' );
180 } );
181
182 $toggle.trigger( 'click' );
183 } );
184
185 $toggle.trigger( 'click' );
186 }
187
188 QUnit.test( 'basic operation (<ul>)', 7, function ( assert ) {
189 listTest( 'ul', this, assert );
190 } );
191
192 QUnit.test( 'basic operation (<ol>)', 7, function ( assert ) {
193 listTest( 'ol', this, assert );
194 } );
195
196 QUnit.test( 'basic operation when synchronous (options.instantHide)', 2, function ( assert ) {
197 var $collapsible = prepareCollapsible(
198 '<div class="mw-collapsible">' + loremIpsum + '</div>',
199 { instantHide: true }
200 ),
201 $content = $collapsible.find( '.mw-collapsible-content' );
202
203 assert.assertTrue( $content.is( ':visible' ), 'content is visible' );
204
205 $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
206
207 assert.assertTrue( $content.is( ':hidden' ), 'after collapsing: content is hidden' );
208 } );
209
210 QUnit.test( 'mw-made-collapsible data added', 1, function ( assert ) {
211 var $collapsible = prepareCollapsible(
212 '<div>' + loremIpsum + '</div>'
213 );
214
215 assert.equal( $collapsible.data( 'mw-made-collapsible' ), true, 'mw-made-collapsible data present' );
216 } );
217
218 QUnit.test( 'mw-collapsible added when missing', 1, function ( assert ) {
219 var $collapsible = prepareCollapsible(
220 '<div>' + loremIpsum + '</div>'
221 );
222
223 assert.assertTrue( $collapsible.hasClass( 'mw-collapsible' ), 'mw-collapsible class present' );
224 } );
225
226 QUnit.test( 'mw-collapsed added when missing', 1, function ( assert ) {
227 var $collapsible = prepareCollapsible(
228 '<div>' + loremIpsum + '</div>',
229 { collapsed: true }
230 );
231
232 assert.assertTrue( $collapsible.hasClass( 'mw-collapsed' ), 'mw-collapsed class present' );
233 } );
234
235 QUnit.test( 'initial collapse (mw-collapsed class)', 2, function ( assert ) {
236 var $collapsible = prepareCollapsible(
237 '<div class="mw-collapsible mw-collapsed">' + loremIpsum + '</div>'
238 ),
239 $content = $collapsible.find( '.mw-collapsible-content' );
240
241 // Synchronous - mw-collapsed should cause instantHide: true to be used on initial collapsing
242 assert.assertTrue( $content.is( ':hidden' ), 'content is hidden' );
243
244 $collapsible.on( 'afterExpand.mw-collapsible', function () {
245 assert.assertTrue( $content.is( ':visible' ), 'after expanding: content is visible' );
246 } );
247
248 $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
249 } );
250
251 QUnit.test( 'initial collapse (options.collapsed)', 2, function ( assert ) {
252 var $collapsible = prepareCollapsible(
253 '<div class="mw-collapsible">' + loremIpsum + '</div>',
254 { collapsed: true }
255 ),
256 $content = $collapsible.find( '.mw-collapsible-content' );
257
258 // Synchronous - collapsed: true should cause instantHide: true to be used on initial collapsing
259 assert.assertTrue( $content.is( ':hidden' ), 'content is hidden' );
260
261 $collapsible.on( 'afterExpand.mw-collapsible', function () {
262 assert.assertTrue( $content.is( ':visible' ), 'after expanding: content is visible' );
263 } );
264
265 $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
266 } );
267
268 QUnit.test( 'clicks on links inside toggler pass through (options.linksPassthru)', 2, function ( assert ) {
269 var $collapsible = prepareCollapsible(
270 '<div class="mw-collapsible">' +
271 '<div class="mw-collapsible-toggle">' +
272 'Toggle <a href="#top">toggle</a> toggle <b>toggle</b>' +
273 '</div>' +
274 '<div class="mw-collapsible-content">' + loremIpsum + '</div>' +
275 '</div>',
276 // Can't do asynchronous because we're testing that the event *doesn't* happen
277 { instantHide: true }
278 ),
279 $content = $collapsible.find( '.mw-collapsible-content' );
280
281 $collapsible.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
282 assert.assertTrue( $content.is( ':visible' ), 'click event on link inside toggle passes through (content not toggled)' );
283
284 $collapsible.find( '.mw-collapsible-toggle b' ).trigger( 'click' );
285 assert.assertTrue( $content.is( ':hidden' ), 'click event on non-link inside toggle toggles content' );
286 } );
287
288 QUnit.test( 'collapse/expand text (data-collapsetext, data-expandtext)', 2, function ( assert ) {
289 var $collapsible = prepareCollapsible(
290 '<div class="mw-collapsible" data-collapsetext="Collapse me!" data-expandtext="Expand me!">' +
291 loremIpsum +
292 '</div>'
293 ),
294 $toggleLink = $collapsible.find( '.mw-collapsible-toggle a' );
295
296 assert.equal( $toggleLink.text(), 'Collapse me!', 'data-collapsetext is respected' );
297
298 $collapsible.on( 'afterCollapse.mw-collapsible', function () {
299 assert.equal( $toggleLink.text(), 'Expand me!', 'data-expandtext is respected' );
300 } );
301
302 $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
303 } );
304
305 QUnit.test( 'collapse/expand text (options.collapseText, options.expandText)', 2, function ( assert ) {
306 var $collapsible = prepareCollapsible(
307 '<div class="mw-collapsible">' + loremIpsum + '</div>',
308 { collapseText: 'Collapse me!', expandText: 'Expand me!' }
309 ),
310 $toggleLink = $collapsible.find( '.mw-collapsible-toggle a' );
311
312 assert.equal( $toggleLink.text(), 'Collapse me!', 'options.collapseText is respected' );
313
314 $collapsible.on( 'afterCollapse.mw-collapsible', function () {
315 assert.equal( $toggleLink.text(), 'Expand me!', 'options.expandText is respected' );
316 } );
317
318 $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
319 } );
320
321 QUnit.test( 'cloned collapsibles can be made collapsible again', 2, function ( assert ) {
322 var test = this,
323 $collapsible = prepareCollapsible(
324 '<div class="mw-collapsible">' + loremIpsum + '</div>'
325 ),
326 $clone = $collapsible.clone() // clone without data and events
327 .appendTo( '#qunit-fixture' ).makeCollapsible(),
328 $content = $clone.find( '.mw-collapsible-content' );
329
330 assert.assertTrue( $content.is( ':visible' ), 'content is visible' );
331
332 $clone.on( 'afterCollapse.mw-collapsible', function () {
333 assert.assertTrue( $content.is( ':hidden' ), 'after collapsing: content is hidden' );
334 } );
335
336 $clone.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
337 } );
338 }( mediaWiki, jQuery ) );