2 var loremIpsum
= 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.';
4 QUnit
.module( 'jquery.makeCollapsible', QUnit
.newMwEnvironment( {
6 this.clock
= this.sandbox
.useFakeTimers();
10 function prepareCollapsible( html
, options
) {
11 return $( $.parseHTML( html
) )
12 .appendTo( '#qunit-fixture' )
13 // options might be undefined here - this is okay
14 .makeCollapsible( options
);
17 // This test is first because if it fails, then almost all of the latter tests are meaningless.
18 QUnit
.test( 'testing hooks/triggers', 4, function ( assert
) {
20 $collapsible
= prepareCollapsible(
21 '<div class="mw-collapsible">' + loremIpsum
+ '</div>'
23 $content
= $collapsible
.find( '.mw-collapsible-content' ),
24 $toggle
= $collapsible
.find( '.mw-collapsible-toggle' );
26 // In one full collapse-expand cycle, each event will be fired once
29 $collapsible
.on( 'beforeCollapse.mw-collapsible', function () {
30 assert
.assertTrue( $content
.is( ':visible' ), 'first beforeCollapseExpand: content is visible' );
32 $collapsible
.on( 'afterCollapse.mw-collapsible', function () {
33 assert
.assertTrue( $content
.is( ':hidden' ), 'first afterCollapseExpand: content is hidden' );
36 $collapsible
.on( 'beforeExpand.mw-collapsible', function () {
37 assert
.assertTrue( $content
.is( ':hidden' ), 'second beforeCollapseExpand: content is hidden' );
39 $collapsible
.on( 'afterExpand.mw-collapsible', function () {
40 assert
.assertTrue( $content
.is( ':visible' ), 'second afterCollapseExpand: content is visible' );
43 // ...expanding happens here
44 $toggle
.trigger( 'click' );
45 test
.clock
.tick( 500 );
48 // ...collapsing happens here
49 $toggle
.trigger( 'click' );
50 test
.clock
.tick( 500 );
53 QUnit
.test( 'basic operation (<div>)', 5, function ( assert
) {
55 $collapsible
= prepareCollapsible(
56 '<div class="mw-collapsible">' + loremIpsum
+ '</div>'
58 $content
= $collapsible
.find( '.mw-collapsible-content' ),
59 $toggle
= $collapsible
.find( '.mw-collapsible-toggle' );
61 assert
.equal( $content
.length
, 1, 'content is present' );
62 assert
.equal( $content
.find( $toggle
).length
, 0, 'toggle is not a descendant of content' );
64 assert
.assertTrue( $content
.is( ':visible' ), 'content is visible' );
66 $collapsible
.on( 'afterCollapse.mw-collapsible', function () {
67 assert
.assertTrue( $content
.is( ':hidden' ), 'after collapsing: content is hidden' );
69 $collapsible
.on( 'afterExpand.mw-collapsible', function () {
70 assert
.assertTrue( $content
.is( ':visible' ), 'after expanding: content is visible' );
73 $toggle
.trigger( 'click' );
74 test
.clock
.tick( 500 );
77 $toggle
.trigger( 'click' );
78 test
.clock
.tick( 500 );
81 QUnit
.test( 'basic operation (<table>)', 7, function ( assert
) {
83 $collapsible
= prepareCollapsible(
84 '<table class="mw-collapsible">' +
85 '<tr><td>' + loremIpsum
+ '</td><td>' + loremIpsum
+ '</td></tr>' +
86 '<tr><td>' + loremIpsum
+ '</td><td>' + loremIpsum
+ '</td></tr>' +
87 '<tr><td>' + loremIpsum
+ '</td><td>' + loremIpsum
+ '</td></tr>' +
90 $headerRow
= $collapsible
.find( 'tr:first' ),
91 $contentRow
= $collapsible
.find( 'tr:last' ),
92 $toggle
= $headerRow
.find( 'td:last .mw-collapsible-toggle' );
94 assert
.equal( $toggle
.length
, 1, 'toggle is added to last cell of first row' );
96 assert
.assertTrue( $headerRow
.is( ':visible' ), 'headerRow is visible' );
97 assert
.assertTrue( $contentRow
.is( ':visible' ), 'contentRow is visible' );
99 $collapsible
.on( 'afterCollapse.mw-collapsible', function () {
100 assert
.assertTrue( $headerRow
.is( ':visible' ), 'after collapsing: headerRow is still visible' );
101 assert
.assertTrue( $contentRow
.is( ':hidden' ), 'after collapsing: contentRow is hidden' );
103 $collapsible
.on( 'afterExpand.mw-collapsible', function () {
104 assert
.assertTrue( $headerRow
.is( ':visible' ), 'after expanding: headerRow is still visible' );
105 assert
.assertTrue( $contentRow
.is( ':visible' ), 'after expanding: contentRow is visible' );
108 $toggle
.trigger( 'click' );
109 test
.clock
.tick( 500 );
112 $toggle
.trigger( 'click' );
113 test
.clock
.tick( 500 );
116 function tableWithCaptionTest( $collapsible
, test
, assert
) {
117 var $caption
= $collapsible
.find( 'caption' ),
118 $headerRow
= $collapsible
.find( 'tr:first' ),
119 $contentRow
= $collapsible
.find( 'tr:last' ),
120 $toggle
= $caption
.find( '.mw-collapsible-toggle' );
122 assert
.equal( $toggle
.length
, 1, 'toggle is added to the end of the caption' );
124 assert
.assertTrue( $caption
.is( ':visible' ), 'caption is visible' );
125 assert
.assertTrue( $headerRow
.is( ':visible' ), 'headerRow is visible' );
126 assert
.assertTrue( $contentRow
.is( ':visible' ), 'contentRow is visible' );
128 $collapsible
.on( 'afterCollapse.mw-collapsible', function () {
129 assert
.assertTrue( $caption
.is( ':visible' ), 'after collapsing: caption is still visible' );
130 assert
.assertTrue( $headerRow
.is( ':hidden' ), 'after collapsing: headerRow is hidden' );
131 assert
.assertTrue( $contentRow
.is( ':hidden' ), 'after collapsing: contentRow is hidden' );
133 $collapsible
.on( 'afterExpand.mw-collapsible', function () {
134 assert
.assertTrue( $caption
.is( ':visible' ), 'after expanding: caption is still visible' );
135 assert
.assertTrue( $headerRow
.is( ':visible' ), 'after expanding: headerRow is visible' );
136 assert
.assertTrue( $contentRow
.is( ':visible' ), 'after expanding: contentRow is visible' );
139 $toggle
.trigger( 'click' );
140 test
.clock
.tick( 500 );
143 $toggle
.trigger( 'click' );
144 test
.clock
.tick( 500 );
147 QUnit
.test( 'basic operation (<table> with caption)', 10, function ( assert
) {
148 tableWithCaptionTest( prepareCollapsible(
149 '<table class="mw-collapsible">' +
150 '<caption>' + loremIpsum
+ '</caption>' +
151 '<tr><th>' + loremIpsum
+ '</th><th>' + loremIpsum
+ '</th></tr>' +
152 '<tr><td>' + loremIpsum
+ '</td><td>' + loremIpsum
+ '</td></tr>' +
153 '<tr><td>' + loremIpsum
+ '</td><td>' + loremIpsum
+ '</td></tr>' +
158 QUnit
.test( 'basic operation (<table> with caption and <thead>)', 10, function ( assert
) {
159 tableWithCaptionTest( prepareCollapsible(
160 '<table class="mw-collapsible">' +
161 '<caption>' + loremIpsum
+ '</caption>' +
162 '<thead><tr><th>' + loremIpsum
+ '</th><th>' + loremIpsum
+ '</th></tr></thead>' +
163 '<tr><td>' + loremIpsum
+ '</td><td>' + loremIpsum
+ '</td></tr>' +
164 '<tr><td>' + loremIpsum
+ '</td><td>' + loremIpsum
+ '</td></tr>' +
169 function listTest( listType
, test
, assert
) {
170 var $collapsible
= prepareCollapsible(
171 '<' + listType
+ ' class="mw-collapsible">' +
172 '<li>' + loremIpsum
+ '</li>' +
173 '<li>' + loremIpsum
+ '</li>' +
174 '</' + listType
+ '>'
176 $toggleItem
= $collapsible
.find( 'li.mw-collapsible-toggle-li:first-child' ),
177 $contentItem
= $collapsible
.find( 'li:last' ),
178 $toggle
= $toggleItem
.find( '.mw-collapsible-toggle' );
180 assert
.equal( $toggle
.length
, 1, 'toggle is present, added inside new zeroth list item' );
182 assert
.assertTrue( $toggleItem
.is( ':visible' ), 'toggleItem is visible' );
183 assert
.assertTrue( $contentItem
.is( ':visible' ), 'contentItem is visible' );
185 $collapsible
.on( 'afterCollapse.mw-collapsible', function () {
186 assert
.assertTrue( $toggleItem
.is( ':visible' ), 'after collapsing: toggleItem is still visible' );
187 assert
.assertTrue( $contentItem
.is( ':hidden' ), 'after collapsing: contentItem is hidden' );
189 $collapsible
.on( 'afterExpand.mw-collapsible', function () {
190 assert
.assertTrue( $toggleItem
.is( ':visible' ), 'after expanding: toggleItem is still visible' );
191 assert
.assertTrue( $contentItem
.is( ':visible' ), 'after expanding: contentItem is visible' );
194 $toggle
.trigger( 'click' );
195 test
.clock
.tick( 500 );
198 $toggle
.trigger( 'click' );
199 test
.clock
.tick( 500 );
202 QUnit
.test( 'basic operation (<ul>)', 7, function ( assert
) {
203 listTest( 'ul', this, assert
);
206 QUnit
.test( 'basic operation (<ol>)', 7, function ( assert
) {
207 listTest( 'ol', this, assert
);
210 QUnit
.test( 'basic operation when synchronous (options.instantHide)', 2, function ( assert
) {
211 var $collapsible
= prepareCollapsible(
212 '<div class="mw-collapsible">' + loremIpsum
+ '</div>',
213 { instantHide
: true }
215 $content
= $collapsible
.find( '.mw-collapsible-content' );
217 assert
.assertTrue( $content
.is( ':visible' ), 'content is visible' );
219 $collapsible
.find( '.mw-collapsible-toggle' ).trigger( 'click' );
221 assert
.assertTrue( $content
.is( ':hidden' ), 'after collapsing: content is hidden' );
224 QUnit
.test( 'mw-made-collapsible data added', 1, function ( assert
) {
225 var $collapsible
= prepareCollapsible(
226 '<div>' + loremIpsum
+ '</div>'
229 assert
.equal( $collapsible
.data( 'mw-made-collapsible' ), true, 'mw-made-collapsible data present' );
232 QUnit
.test( 'mw-collapsible added when missing', 1, function ( assert
) {
233 var $collapsible
= prepareCollapsible(
234 '<div>' + loremIpsum
+ '</div>'
237 assert
.assertTrue( $collapsible
.hasClass( 'mw-collapsible' ), 'mw-collapsible class present' );
240 QUnit
.test( 'mw-collapsed added when missing', 1, function ( assert
) {
241 var $collapsible
= prepareCollapsible(
242 '<div>' + loremIpsum
+ '</div>',
246 assert
.assertTrue( $collapsible
.hasClass( 'mw-collapsed' ), 'mw-collapsed class present' );
249 QUnit
.test( 'initial collapse (mw-collapsed class)', 2, function ( assert
) {
250 var $collapsible
= prepareCollapsible(
251 '<div class="mw-collapsible mw-collapsed">' + loremIpsum
+ '</div>'
253 $content
= $collapsible
.find( '.mw-collapsible-content' );
255 // Synchronous - mw-collapsed should cause instantHide: true to be used on initial collapsing
256 assert
.assertTrue( $content
.is( ':hidden' ), 'content is hidden' );
258 $collapsible
.on( 'afterExpand.mw-collapsible', function () {
259 assert
.assertTrue( $content
.is( ':visible' ), 'after expanding: content is visible' );
262 $collapsible
.find( '.mw-collapsible-toggle' ).trigger( 'click' );
263 this.clock
.tick( 500 );
266 QUnit
.test( 'initial collapse (options.collapsed)', 2, function ( assert
) {
267 var $collapsible
= prepareCollapsible(
268 '<div class="mw-collapsible">' + loremIpsum
+ '</div>',
271 $content
= $collapsible
.find( '.mw-collapsible-content' );
273 // Synchronous - collapsed: true should cause instantHide: true to be used on initial collapsing
274 assert
.assertTrue( $content
.is( ':hidden' ), 'content is hidden' );
276 $collapsible
.on( 'afterExpand.mw-collapsible', function () {
277 assert
.assertTrue( $content
.is( ':visible' ), 'after expanding: content is visible' );
280 $collapsible
.find( '.mw-collapsible-toggle' ).trigger( 'click' );
281 this.clock
.tick( 500 );
284 QUnit
.test( 'clicks on links inside toggler pass through (options.linksPassthru)', 2, function ( assert
) {
285 var $collapsible
= prepareCollapsible(
286 '<div class="mw-collapsible">' +
287 '<div class="mw-collapsible-toggle">' +
288 'Toggle <a href="#top">toggle</a> toggle <b>toggle</b>' +
290 '<div class="mw-collapsible-content">' + loremIpsum
+ '</div>' +
292 // Can't do asynchronous because we're testing that the event *doesn't* happen
293 { instantHide
: true }
295 $content
= $collapsible
.find( '.mw-collapsible-content' );
297 $collapsible
.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
298 assert
.assertTrue( $content
.is( ':visible' ), 'click event on link inside toggle passes through (content not toggled)' );
300 $collapsible
.find( '.mw-collapsible-toggle b' ).trigger( 'click' );
301 assert
.assertTrue( $content
.is( ':hidden' ), 'click event on non-link inside toggle toggles content' );
304 QUnit
.test( 'collapse/expand text (data-collapsetext, data-expandtext)', 2, function ( assert
) {
305 var $collapsible
= prepareCollapsible(
306 '<div class="mw-collapsible" data-collapsetext="Collapse me!" data-expandtext="Expand me!">' +
310 $toggleLink
= $collapsible
.find( '.mw-collapsible-toggle a' );
312 assert
.equal( $toggleLink
.text(), 'Collapse me!', 'data-collapsetext is respected' );
314 $collapsible
.on( 'afterCollapse.mw-collapsible', function () {
315 assert
.equal( $toggleLink
.text(), 'Expand me!', 'data-expandtext is respected' );
318 $collapsible
.find( '.mw-collapsible-toggle' ).trigger( 'click' );
319 this.clock
.tick( 500 );
322 QUnit
.test( 'collapse/expand text (options.collapseText, options.expandText)', 2, function ( assert
) {
323 var $collapsible
= prepareCollapsible(
324 '<div class="mw-collapsible">' + loremIpsum
+ '</div>',
325 { collapseText
: 'Collapse me!', expandText
: 'Expand me!' }
327 $toggleLink
= $collapsible
.find( '.mw-collapsible-toggle a' );
329 assert
.equal( $toggleLink
.text(), 'Collapse me!', 'options.collapseText is respected' );
331 $collapsible
.on( 'afterCollapse.mw-collapsible', function () {
332 assert
.equal( $toggleLink
.text(), 'Expand me!', 'options.expandText is respected' );
335 $collapsible
.find( '.mw-collapsible-toggle' ).trigger( 'click' );
336 this.clock
.tick( 500 );
339 QUnit
.test( 'cloned collapsibles can be made collapsible again', 2, function ( assert
) {
341 $collapsible
= prepareCollapsible(
342 '<div class="mw-collapsible">' + loremIpsum
+ '</div>'
344 $clone
= $collapsible
.clone() // clone without data and events
345 .appendTo( '#qunit-fixture' ).makeCollapsible(),
346 $content
= $clone
.find( '.mw-collapsible-content' );
348 assert
.assertTrue( $content
.is( ':visible' ), 'content is visible' );
350 $clone
.on( 'afterCollapse.mw-collapsible', function () {
351 assert
.assertTrue( $content
.is( ':hidden' ), 'after collapsing: content is hidden' );
354 $clone
.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
355 test
.clock
.tick( 500 );
357 }( mediaWiki
, jQuery
) );