1 |
torben |
2125 |
(function( $ ) { |
2 |
|
|
|
3 |
|
|
var reset, jshintLoaded; |
4 |
|
|
|
5 |
|
|
window.TestHelpers = {}; |
6 |
|
|
|
7 |
|
|
function includeStyle( url ) { |
8 |
|
|
document.write( "<link rel='stylesheet' href='../../../" + url + "'>" ); |
9 |
|
|
} |
10 |
|
|
|
11 |
|
|
function includeScript( url ) { |
12 |
|
|
document.write( "<script src='../../../" + url + "'></script>" ); |
13 |
|
|
} |
14 |
|
|
|
15 |
|
|
function url( value ) { |
16 |
|
|
return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random() * 100000, 10); |
17 |
|
|
} |
18 |
|
|
|
19 |
|
|
reset = QUnit.reset; |
20 |
|
|
QUnit.reset = function() { |
21 |
|
|
// Ensure jQuery events and data on the fixture are properly removed |
22 |
|
|
jQuery("#qunit-fixture").empty(); |
23 |
|
|
// Let QUnit reset the fixture |
24 |
|
|
reset.apply( this, arguments ); |
25 |
|
|
}; |
26 |
|
|
|
27 |
|
|
|
28 |
|
|
QUnit.config.requireExpects = true; |
29 |
|
|
|
30 |
|
|
QUnit.config.urlConfig.push({ |
31 |
|
|
id: "min", |
32 |
|
|
label: "Minified source", |
33 |
|
|
tooltip: "Load minified source files instead of the regular unminified ones." |
34 |
|
|
}); |
35 |
|
|
|
36 |
|
|
TestHelpers.loadResources = QUnit.urlParams.min ? |
37 |
|
|
function() { |
38 |
|
|
includeStyle( "dist/jquery-ui.min.css" ); |
39 |
|
|
includeScript( "dist/jquery-ui.min.js" ); |
40 |
|
|
} : |
41 |
|
|
function( resources ) { |
42 |
|
|
$.each( resources.css || [], function( i, resource ) { |
43 |
|
|
includeStyle( "themes/base/jquery." + resource + ".css" ); |
44 |
|
|
}); |
45 |
|
|
$.each( resources.js || [], function( i, resource ) { |
46 |
|
|
includeScript( resource ); |
47 |
|
|
}); |
48 |
|
|
}; |
49 |
|
|
|
50 |
|
|
QUnit.config.urlConfig.push({ |
51 |
|
|
id: "nojshint", |
52 |
|
|
label: "Skip JSHint", |
53 |
|
|
tooltip: "Skip running JSHint, e.g. within TestSwarm, where Jenkins runs it already" |
54 |
|
|
}); |
55 |
|
|
|
56 |
|
|
jshintLoaded = false; |
57 |
|
|
TestHelpers.testJshint = function( module ) { |
58 |
|
|
if ( QUnit.urlParams.nojshint ) { |
59 |
|
|
return; |
60 |
|
|
} |
61 |
|
|
|
62 |
|
|
if ( !jshintLoaded ) { |
63 |
|
|
includeScript( "external/jshint.js" ); |
64 |
|
|
jshintLoaded = true; |
65 |
|
|
} |
66 |
|
|
|
67 |
|
|
asyncTest( "JSHint", function() { |
68 |
|
|
expect( 1 ); |
69 |
|
|
|
70 |
|
|
$.when( |
71 |
|
|
$.ajax({ |
72 |
|
|
url: url("../../../ui/.jshintrc"), |
73 |
|
|
dataType: "json" |
74 |
|
|
}), |
75 |
|
|
$.ajax({ |
76 |
|
|
url: url("../../../ui/jquery.ui." + module + ".js"), |
77 |
|
|
dataType: "text" |
78 |
|
|
}) |
79 |
|
|
).done(function( hintArgs, srcArgs ) { |
80 |
|
|
var globals, passed, errors, |
81 |
|
|
jshintrc = hintArgs[ 0 ], |
82 |
|
|
source = srcArgs[ 0 ]; |
83 |
|
|
|
84 |
|
|
globals = jshintrc.globals || {}; |
85 |
|
|
delete jshintrc.globals; |
86 |
|
|
passed = JSHINT( source, jshintrc, globals ), |
87 |
|
|
errors = $.map( JSHINT.errors, function( error ) { |
88 |
|
|
// JSHINT may report null if there are too many errors |
89 |
|
|
if ( !error ) { |
90 |
|
|
return; |
91 |
|
|
} |
92 |
|
|
|
93 |
|
|
return "[L" + error.line + ":C" + error.character + "] " + |
94 |
|
|
error.reason + "\n" + error.evidence + "\n"; |
95 |
|
|
}).join( "\n" ); |
96 |
|
|
ok( passed, errors ); |
97 |
|
|
start(); |
98 |
|
|
}) |
99 |
|
|
.fail(function() { |
100 |
|
|
ok( false, "error loading source" ); |
101 |
|
|
start(); |
102 |
|
|
}); |
103 |
|
|
}); |
104 |
|
|
}; |
105 |
|
|
|
106 |
|
|
function testWidgetDefaults( widget, defaults ) { |
107 |
|
|
var pluginDefaults = $.ui[ widget ].prototype.options; |
108 |
|
|
|
109 |
|
|
// ensure that all defaults have the correct value |
110 |
|
|
test( "defined defaults", function() { |
111 |
|
|
var count = 0; |
112 |
|
|
$.each( defaults, function( key, val ) { |
113 |
|
|
expect( ++count ); |
114 |
|
|
if ( $.isFunction( val ) ) { |
115 |
|
|
ok( $.isFunction( pluginDefaults[ key ] ), key ); |
116 |
|
|
return; |
117 |
|
|
} |
118 |
|
|
deepEqual( pluginDefaults[ key ], val, key ); |
119 |
|
|
}); |
120 |
|
|
}); |
121 |
|
|
|
122 |
|
|
// ensure that all defaults were tested |
123 |
|
|
test( "tested defaults", function() { |
124 |
|
|
var count = 0; |
125 |
|
|
$.each( pluginDefaults, function( key ) { |
126 |
|
|
expect( ++count ); |
127 |
|
|
ok( key in defaults, key ); |
128 |
|
|
}); |
129 |
|
|
}); |
130 |
|
|
} |
131 |
|
|
|
132 |
|
|
function testWidgetOverrides( widget ) { |
133 |
|
|
if ( $.uiBackCompat === false ) { |
134 |
|
|
test( "$.widget overrides", function() { |
135 |
|
|
expect( 4 ); |
136 |
|
|
$.each([ |
137 |
|
|
"_createWidget", |
138 |
|
|
"destroy", |
139 |
|
|
"option", |
140 |
|
|
"_trigger" |
141 |
|
|
], function( i, method ) { |
142 |
|
|
strictEqual( $.ui[ widget ].prototype[ method ], |
143 |
|
|
$.Widget.prototype[ method ], "should not override " + method ); |
144 |
|
|
}); |
145 |
|
|
}); |
146 |
|
|
} |
147 |
|
|
} |
148 |
|
|
|
149 |
|
|
function testBasicUsage( widget ) { |
150 |
|
|
test( "basic usage", function() { |
151 |
|
|
expect( 3 ); |
152 |
|
|
|
153 |
|
|
var defaultElement = $.ui[ widget ].prototype.defaultElement; |
154 |
|
|
$( defaultElement ).appendTo( "body" )[ widget ]().remove(); |
155 |
|
|
ok( true, "initialized on element" ); |
156 |
|
|
|
157 |
|
|
$( defaultElement )[ widget ]().remove(); |
158 |
|
|
ok( true, "initialized on disconnected DOMElement - never connected" ); |
159 |
|
|
|
160 |
|
|
$( defaultElement ).appendTo( "body" ).remove()[ widget ]().remove(); |
161 |
|
|
ok( true, "initialized on disconnected DOMElement - removed" ); |
162 |
|
|
}); |
163 |
|
|
} |
164 |
|
|
|
165 |
|
|
TestHelpers.commonWidgetTests = function( widget, settings ) { |
166 |
|
|
module( widget + ": common widget" ); |
167 |
|
|
|
168 |
|
|
TestHelpers.testJshint( widget ); |
169 |
|
|
testWidgetDefaults( widget, settings.defaults ); |
170 |
|
|
testWidgetOverrides( widget ); |
171 |
|
|
testBasicUsage( widget ); |
172 |
|
|
test( "version", function() { |
173 |
|
|
expect( 1 ); |
174 |
|
|
ok( "version" in $.ui[ widget ].prototype, "version property exists" ); |
175 |
|
|
}); |
176 |
|
|
}; |
177 |
|
|
|
178 |
|
|
/* |
179 |
|
|
* Taken from https://github.com/jquery/qunit/tree/master/addons/close-enough |
180 |
|
|
*/ |
181 |
|
|
window.closeEnough = function( actual, expected, maxDifference, message ) { |
182 |
|
|
var passes = (actual === expected) || Math.abs(actual - expected) <= maxDifference; |
183 |
|
|
QUnit.push(passes, actual, expected, message); |
184 |
|
|
}; |
185 |
|
|
|
186 |
|
|
/* |
187 |
|
|
* Experimental assertion for comparing DOM objects. |
188 |
|
|
* |
189 |
|
|
* Serializes an element and some properties and attributes and it's children if any, otherwise the text. |
190 |
|
|
* Then compares the result using deepEqual. |
191 |
|
|
*/ |
192 |
|
|
window.domEqual = function( selector, modifier, message ) { |
193 |
|
|
var expected, actual, |
194 |
|
|
properties = [ |
195 |
|
|
"disabled", |
196 |
|
|
"readOnly" |
197 |
|
|
], |
198 |
|
|
attributes = [ |
199 |
|
|
"autocomplete", |
200 |
|
|
"aria-activedescendant", |
201 |
|
|
"aria-controls", |
202 |
|
|
"aria-describedby", |
203 |
|
|
"aria-disabled", |
204 |
|
|
"aria-expanded", |
205 |
|
|
"aria-haspopup", |
206 |
|
|
"aria-hidden", |
207 |
|
|
"aria-labelledby", |
208 |
|
|
"aria-pressed", |
209 |
|
|
"aria-selected", |
210 |
|
|
"aria-valuemax", |
211 |
|
|
"aria-valuemin", |
212 |
|
|
"aria-valuenow", |
213 |
|
|
"class", |
214 |
|
|
"href", |
215 |
|
|
"id", |
216 |
|
|
"nodeName", |
217 |
|
|
"role", |
218 |
|
|
"tabIndex", |
219 |
|
|
"title" |
220 |
|
|
]; |
221 |
|
|
|
222 |
|
|
function getElementStyles( elem ) { |
223 |
|
|
var key, len, |
224 |
|
|
style = elem.ownerDocument.defaultView ? |
225 |
|
|
elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : |
226 |
|
|
elem.currentStyle, |
227 |
|
|
styles = {}; |
228 |
|
|
|
229 |
|
|
if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { |
230 |
|
|
len = style.length; |
231 |
|
|
while ( len-- ) { |
232 |
|
|
key = style[ len ]; |
233 |
|
|
if ( typeof style[ key ] === "string" ) { |
234 |
|
|
styles[ $.camelCase( key ) ] = style[ key ]; |
235 |
|
|
} |
236 |
|
|
} |
237 |
|
|
// support: Opera, IE <9 |
238 |
|
|
} else { |
239 |
|
|
for ( key in style ) { |
240 |
|
|
if ( typeof style[ key ] === "string" ) { |
241 |
|
|
styles[ key ] = style[ key ]; |
242 |
|
|
} |
243 |
|
|
} |
244 |
|
|
} |
245 |
|
|
|
246 |
|
|
return styles; |
247 |
|
|
} |
248 |
|
|
|
249 |
|
|
function extract( elem ) { |
250 |
|
|
if ( !elem || !elem.length ) { |
251 |
|
|
QUnit.push( false, actual, expected, |
252 |
|
|
"domEqual failed, can't extract " + selector + ", message was: " + message ); |
253 |
|
|
return; |
254 |
|
|
} |
255 |
|
|
|
256 |
|
|
var children, |
257 |
|
|
result = {}; |
258 |
|
|
$.each( properties, function( index, attr ) { |
259 |
|
|
var value = elem.prop( attr ); |
260 |
|
|
result[ attrĀ ] = value !== undefined ? value : ""; |
261 |
|
|
}); |
262 |
|
|
$.each( attributes, function( index, attr ) { |
263 |
|
|
var value = elem.attr( attr ); |
264 |
|
|
result[ attrĀ ] = value !== undefined ? value : ""; |
265 |
|
|
}); |
266 |
|
|
result.style = getElementStyles( elem[ 0 ] ); |
267 |
|
|
result.events = $._data( elem[ 0 ], "events" ); |
268 |
|
|
result.data = $.extend( {}, elem.data() ); |
269 |
|
|
delete result.data[ $.expando ]; |
270 |
|
|
children = elem.children(); |
271 |
|
|
if ( children.length ) { |
272 |
|
|
result.children = elem.children().map(function() { |
273 |
|
|
return extract( $( this ) ); |
274 |
|
|
}).get(); |
275 |
|
|
} else { |
276 |
|
|
result.text = elem.text(); |
277 |
|
|
} |
278 |
|
|
return result; |
279 |
|
|
} |
280 |
|
|
|
281 |
|
|
function done() { |
282 |
|
|
actual = extract( $( selector ) ); |
283 |
|
|
QUnit.push( QUnit.equiv(actual, expected), actual, expected, message ); |
284 |
|
|
} |
285 |
|
|
|
286 |
|
|
// Get current state prior to modifier |
287 |
|
|
expected = extract( $( selector ) ); |
288 |
|
|
|
289 |
|
|
// Run modifier (async or sync), then compare state via done() |
290 |
|
|
if ( modifier.length ) { |
291 |
|
|
modifier( done ); |
292 |
|
|
} else { |
293 |
|
|
modifier(); |
294 |
|
|
done(); |
295 |
|
|
} |
296 |
|
|
}; |
297 |
|
|
|
298 |
|
|
}( jQuery )); |