aboutsummaryrefslogtreecommitdiffstats
path: root/test/unit/ready.js
blob: d1a728b47d2ac339ed62351b021ee1396e918187 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
QUnit.module( "ready" );

( function() {
	var notYetReady, noEarlyExecution,
		whenified = jQuery.when && jQuery.when( jQuery.ready ),
		promisified = Promise.resolve( jQuery.ready ),
		start = new Date(),
		order = [],
		args = {};

	notYetReady = !jQuery.isReady;

	QUnit.test( "jQuery.isReady", function( assert ) {
		assert.expect( 2 );

		assert.equal( notYetReady, true, "jQuery.isReady should not be true before DOM ready" );
		assert.equal( jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready" );
	} );

	// Create an event handler.
	function makeHandler( testId ) {

		// When returned function is executed, push testId onto `order` array
		// to ensure execution order. Also, store event handler arg to ensure
		// the correct arg is being passed into the event handler.
		return function( arg ) {
			order.push( testId );
			args[ testId ] = arg;
		};
	}

	function throwError( num ) {

		// Not a global QUnit failure
		var onerror = window.onerror;
		window.onerror = function() {
			window.onerror = onerror;
		};

		throw new Error( "Ready error " + num );
	}

	// Bind to the ready event in every possible way.
	jQuery( makeHandler( "a" ) );
	jQuery( document ).ready( makeHandler( "b" ) );
	jQuery.ready.then( makeHandler( "c" ) );

	// Throw in some errors
	jQuery( function() {
		throwError( 1 );
	} );
	jQuery( function() {
		throwError( 2 );
	} );

	// Bind again to ensure that the errors didn't lock everything up
	jQuery( makeHandler( "d" ) );
	jQuery( document ).ready( makeHandler( "e" ) );
	jQuery.ready.then( makeHandler( "f" ) );

	noEarlyExecution = order.length === 0;

	// This assumes that QUnit tests are run on DOM ready!
	QUnit.test( "jQuery ready", function( assert ) {
		assert.expect( 10 );

		assert.ok( noEarlyExecution,
			"Handlers bound to DOM ready should not execute before DOM ready" );

		// Ensure execution order.
		assert.deepEqual( order, [ "a", "b", "c", "d", "e", "f" ],
			"Bound DOM ready handlers should execute in bind order" );

		// Ensure handler argument is correct.
		assert.equal( args.a, jQuery,
			"Argument passed to fn in jQuery( fn ) should be jQuery" );
		assert.equal( args.b, jQuery,
			"Argument passed to fn in jQuery(document).ready( fn ) should be jQuery" );

		order = [];

		// Now that the ready event has fired, again bind to the ready event.
		// These ready handlers should execute asynchronously.
		var done = assert.async();
		jQuery( makeHandler( "g" ) );
		jQuery( document ).ready( makeHandler( "h" ) );
		jQuery.ready.then( makeHandler( "i" ) );
		window.setTimeout( function() {
			assert.equal( order.shift(), "g",
				"Event handler should execute immediately, but async" );
			assert.equal( args.g, jQuery,
				"Argument passed to fn in jQuery( fn ) should be jQuery" );

			assert.equal( order.shift(), "h",
				"Event handler should execute immediately, but async" );
			assert.equal( args.h, jQuery,
				"Argument passed to fn in jQuery(document).ready( fn ) should be jQuery" );

			assert.equal( order.shift(), "i",
				"Event handler should execute immediately, but async" );
			assert.equal( args.h, jQuery,
				"Argument passed to fn in jQuery.ready.then( fn ) should be jQuery" );

			done();
		} );
	} );

	QUnit[ jQuery.when ? "test" : "skip" ]( "jQuery.when(jQuery.ready)", function( assert ) {
		assert.expect( 2 );
		var done = assert.async( 2 );

		whenified.then( function() {
			assert.ok( jQuery.isReady, "jQuery.when Deferred resolved" );
			done();
		} );

		jQuery.when( jQuery.ready ).then( function() {
			assert.ok( jQuery.isReady, "jQuery.when Deferred resolved" );
			done();
		} );
	} );

	QUnit.test( "Promise.resolve(jQuery.ready)", function( assert ) {
		assert.expect( 2 );
		var done = assert.async( 2 );

		promisified.then( function() {
			assert.ok( jQuery.isReady, "Native promised resolved" );
			done();
		} );

		Promise.resolve( jQuery.ready ).then( function() {
			assert.ok( jQuery.isReady, "Native promised resolved" );
			done();
		} );
	} );

	QUnit.test( "Error in ready callback does not halt all future executions (gh-1823)", function( assert ) {
		assert.expect( 1 );
		var done = assert.async();

		jQuery( function() {
			throwError( 3 );
		} );

		jQuery( function() {
			assert.ok( true, "Subsequent handler called" );
			done();
		} );
	} );

	// jQuery.holdReady is deprecated, skip the test if it was excluded.
	if ( jQuery.holdReady ) {
		testIframe(
			"holdReady test needs to be a standalone test since it deals with DOM ready",
			"readywait.html",
			function( assert, jQuery, window, document, releaseCalled ) {
				assert.expect( 2 );
				var now = new Date();
				assert.ok( now - start >= 300, "Needs to have waited at least half a second" );
				assert.ok( releaseCalled, "The release function was called, which resulted in ready" );
			}
		);
	}

} )();