Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bootstrap
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
bootstrap
Commits
d869a5fb
Commit
d869a5fb
authored
Aug 27, 2014
by
XhmikosR
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update QUnit to v1.15.0.
parent
783e0017
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1141 additions
and
934 deletions
+1141
-934
js/tests/vendor/qunit.css
js/tests/vendor/qunit.css
+7
-7
js/tests/vendor/qunit.js
js/tests/vendor/qunit.js
+1134
-927
No files found.
js/tests/vendor/qunit.css
View file @
d869a5fb
/*!
* QUnit 1.1
4
.0
* QUnit 1.1
5
.0
* http://qunitjs.com/
*
* Copyright 201
3
jQuery Foundation and other contributors
* Copyright 201
4
jQuery Foundation and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2014-0
1-31T16:4
0Z
* Date: 2014-0
8-08T16:0
0Z
*/
/** Font Family and Sizes */
...
...
@@ -62,14 +62,14 @@
}
#qunit-testrunner-toolbar
{
padding
:
0.5em
0
0.5em
2
em
;
padding
:
0.5em
1em
0.5em
1
em
;
color
:
#5E740B
;
background-color
:
#EEE
;
overflow
:
hidden
;
}
#qunit-userAgent
{
padding
:
0.5em
0
0.5em
2.5
em
;
padding
:
0.5em
1em
0.5em
1
em
;
background-color
:
#2B81AF
;
color
:
#FFF
;
text-shadow
:
rgba
(
0
,
0
,
0
,
0.5
)
2px
2px
1px
;
...
...
@@ -86,7 +86,7 @@
}
#qunit-tests
li
{
padding
:
0.4em
0.5em
0.4em
2.5
em
;
padding
:
0.4em
1em
0.4em
1
em
;
border-bottom
:
1px
solid
#FFF
;
list-style-position
:
inside
;
}
...
...
@@ -215,7 +215,7 @@
/** Result */
#qunit-testresult
{
padding
:
0.5em
0.5em
0.5em
2.5
em
;
padding
:
0.5em
1em
0.5em
1
em
;
color
:
#2B81AF
;
background-color
:
#D2E0E6
;
...
...
js/tests/vendor/qunit.js
View file @
d869a5fb
/*!
* QUnit 1.1
4
.0
* QUnit 1.1
5
.0
* http://qunitjs.com/
*
* Copyright 201
3
jQuery Foundation and other contributors
* Copyright 201
4
jQuery Foundation and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2014-0
1-31T16:4
0Z
* Date: 2014-0
8-08T16:0
0Z
*/
(
function
(
window
)
{
var
QUnit
,
assert
,
config
,
onErrorFnPrev
,
testId
=
0
,
fileName
=
(
sourceFromStacktrace
(
0
)
||
""
).
replace
(
/
(
:
\d
+
)
+
\)?
/
,
""
).
replace
(
/.+
\/
/
,
""
),
fileName
=
(
sourceFromStacktrace
(
0
)
||
""
).
replace
(
/
(
:
\d
+
)
+
\)?
/
,
""
).
replace
(
/.+
\/
/
,
""
),
toString
=
Object
.
prototype
.
toString
,
hasOwn
=
Object
.
prototype
.
hasOwnProperty
,
// Keep a local reference to Date (GH-283)
Date
=
window
.
Date
,
now
=
Date
.
now
||
function
()
{
return
new
Date
().
getTime
();
},
setTimeout
=
window
.
setTimeout
,
clearTimeout
=
window
.
clearTimeout
,
defined
=
{
...
...
@@ -32,7 +33,7 @@ var QUnit,
sessionStorage
.
setItem
(
x
,
x
);
sessionStorage
.
removeItem
(
x
);
return
true
;
}
catch
(
e
)
{
}
catch
(
e
)
{
return
false
;
}
}())
...
...
@@ -74,20 +75,17 @@ var QUnit,
* @return {Object} New object with only the own properties (recursively).
*/
objectValues
=
function
(
obj
)
{
// Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
/*jshint newcap: false */
var
key
,
val
,
vals
=
QUnit
.
is
(
"
array
"
,
obj
)
?
[]
:
{};
for
(
key
in
obj
)
{
if
(
hasOwn
.
call
(
obj
,
key
)
)
{
val
=
obj
[
key
];
vals
[
key
]
=
val
===
Object
(
val
)
?
objectValues
(
val
)
:
val
;
val
=
obj
[
key
];
vals
[
key
]
=
val
===
Object
(
val
)
?
objectValues
(
val
)
:
val
;
}
}
return
vals
;
};
// Root QUnit object.
// `QUnit` initialized at top of scope
QUnit
=
{
...
...
@@ -96,7 +94,7 @@ QUnit = {
module
:
function
(
name
,
testEnvironment
)
{
config
.
currentModule
=
name
;
config
.
currentModuleTestEnvironment
=
testEnvironment
;
config
.
modules
[
name
]
=
true
;
config
.
modules
[
name
]
=
true
;
},
asyncTest
:
function
(
testName
,
expected
,
callback
)
{
...
...
@@ -109,20 +107,14 @@ QUnit = {
},
test
:
function
(
testName
,
expected
,
callback
,
async
)
{
var
test
,
nameHtml
=
"
<span class='test-name'>
"
+
escapeText
(
testName
)
+
"
</span>
"
;
var
test
;
if
(
arguments
.
length
===
2
)
{
callback
=
expected
;
expected
=
null
;
}
if
(
config
.
currentModule
)
{
nameHtml
=
"
<span class='module-name'>
"
+
escapeText
(
config
.
currentModule
)
+
"
</span>:
"
+
nameHtml
;
}
test
=
new
Test
({
nameHtml
:
nameHtml
,
testName
:
testName
,
expected
:
expected
,
async
:
async
,
...
...
@@ -139,16 +131,9 @@ QUnit = {
test
.
queue
();
},
// Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through.
expect
:
function
(
asserts
)
{
if
(
arguments
.
length
===
1
)
{
config
.
current
.
expected
=
asserts
;
}
else
{
return
config
.
current
.
expected
;
}
},
start
:
function
(
count
)
{
var
message
;
// QUnit hasn't been initialized yet.
// Note: RequireJS (et al) may delay onLoad
if
(
config
.
semaphore
===
undefined
)
{
...
...
@@ -166,10 +151,21 @@ QUnit = {
if
(
config
.
semaphore
>
0
)
{
return
;
}
// Set the starting time when the first test is run
QUnit
.
config
.
started
=
QUnit
.
config
.
started
||
now
();
// ignore if start is called more often then stop
if
(
config
.
semaphore
<
0
)
{
config
.
semaphore
=
0
;
QUnit
.
pushFailure
(
"
Called start() while already started (QUnit.config.semaphore was 0 already)
"
,
null
,
sourceFromStacktrace
(
2
)
);
message
=
"
Called start() while already started (QUnit.config.semaphore was 0 already)
"
;
if
(
config
.
current
)
{
QUnit
.
pushFailure
(
message
,
sourceFromStacktrace
(
2
)
);
}
else
{
throw
new
Error
(
message
);
}
return
;
}
// A slight delay, to avoid any current callbacks
...
...
@@ -184,7 +180,7 @@ QUnit = {
config
.
blocking
=
false
;
process
(
true
);
},
13
);
},
13
);
}
else
{
config
.
blocking
=
false
;
process
(
true
);
...
...
@@ -212,6 +208,7 @@ QUnit = {
function
F
()
{}
F
.
prototype
=
QUnit
;
QUnit
=
new
F
();
// Make F QUnit's constructor so that we can add to the prototype later
QUnit
.
constructor
=
F
;
}());
...
...
@@ -263,14 +260,7 @@ config = {
// Set of all modules.
modules
:
{},
// logging callback queues
begin
:
[],
done
:
[],
log
:
[],
testStart
:
[],
testDone
:
[],
moduleStart
:
[],
moduleDone
:
[]
callbacks
:
{}
};
// Initialize more QUnit.config and QUnit.urlParams
...
...
@@ -323,71 +313,6 @@ extend( QUnit, {
config
:
config
,
// Initialize the configuration options
init
:
function
()
{
extend
(
config
,
{
stats
:
{
all
:
0
,
bad
:
0
},
moduleStats
:
{
all
:
0
,
bad
:
0
},
started
:
+
new
Date
(),
updateRate
:
1000
,
blocking
:
false
,
autostart
:
true
,
autorun
:
false
,
filter
:
""
,
queue
:
[],
semaphore
:
1
});
var
tests
,
banner
,
result
,
qunit
=
id
(
"
qunit
"
);
if
(
qunit
)
{
qunit
.
innerHTML
=
"
<h1 id='qunit-header'>
"
+
escapeText
(
document
.
title
)
+
"
</h1>
"
+
"
<h2 id='qunit-banner'></h2>
"
+
"
<div id='qunit-testrunner-toolbar'></div>
"
+
"
<h2 id='qunit-userAgent'></h2>
"
+
"
<ol id='qunit-tests'></ol>
"
;
}
tests
=
id
(
"
qunit-tests
"
);
banner
=
id
(
"
qunit-banner
"
);
result
=
id
(
"
qunit-testresult
"
);
if
(
tests
)
{
tests
.
innerHTML
=
""
;
}
if
(
banner
)
{
banner
.
className
=
""
;
}
if
(
result
)
{
result
.
parentNode
.
removeChild
(
result
);
}
if
(
tests
)
{
result
=
document
.
createElement
(
"
p
"
);
result
.
id
=
"
qunit-testresult
"
;
result
.
className
=
"
result
"
;
tests
.
parentNode
.
insertBefore
(
result
,
tests
);
result
.
innerHTML
=
"
Running...<br/>
"
;
}
},
// Resets the test setup. Useful for tests that modify the DOM.
/*
DEPRECATED: Use multiple tests instead of resetting inside a test.
Use testStart or testDone for custom cleanup.
This method will throw an error in 2.0, and will be removed in 2.1
*/
reset
:
function
()
{
var
fixture
=
id
(
"
qunit-fixture
"
);
if
(
fixture
)
{
fixture
.
innerHTML
=
config
.
fixture
;
}
},
// Safe object type checking
is
:
function
(
type
,
obj
)
{
return
QUnit
.
objectType
(
obj
)
===
type
;
...
...
@@ -403,12 +328,12 @@ extend( QUnit, {
return
"
null
"
;
}
var
match
=
toString
.
call
(
obj
).
match
(
/^
\[
object
\s(
.*
)\]
$/
),
type
=
match
&&
match
[
1
]
||
""
;
var
match
=
toString
.
call
(
obj
).
match
(
/^
\[
object
\s(
.*
)\]
$/
),
type
=
match
&&
match
[
1
]
||
""
;
switch
(
type
)
{
case
"
Number
"
:
if
(
isNaN
(
obj
)
)
{
if
(
isNaN
(
obj
)
)
{
return
"
nan
"
;
}
return
"
number
"
;
...
...
@@ -426,91 +351,6 @@ extend( QUnit, {
return
undefined
;
},
push
:
function
(
result
,
actual
,
expected
,
message
)
{
if
(
!
config
.
current
)
{
throw
new
Error
(
"
assertion outside test context, was
"
+
sourceFromStacktrace
()
);
}
var
output
,
source
,
details
=
{
module
:
config
.
current
.
module
,
name
:
config
.
current
.
testName
,
result
:
result
,
message
:
message
,
actual
:
actual
,
expected
:
expected
};
message
=
escapeText
(
message
)
||
(
result
?
"
okay
"
:
"
failed
"
);
message
=
"
<span class='test-message'>
"
+
message
+
"
</span>
"
;
output
=
message
;
if
(
!
result
)
{
expected
=
escapeText
(
QUnit
.
jsDump
.
parse
(
expected
)
);
actual
=
escapeText
(
QUnit
.
jsDump
.
parse
(
actual
)
);
output
+=
"
<table><tr class='test-expected'><th>Expected: </th><td><pre>
"
+
expected
+
"
</pre></td></tr>
"
;
if
(
actual
!==
expected
)
{
output
+=
"
<tr class='test-actual'><th>Result: </th><td><pre>
"
+
actual
+
"
</pre></td></tr>
"
;
output
+=
"
<tr class='test-diff'><th>Diff: </th><td><pre>
"
+
QUnit
.
diff
(
expected
,
actual
)
+
"
</pre></td></tr>
"
;
}
source
=
sourceFromStacktrace
();
if
(
source
)
{
details
.
source
=
source
;
output
+=
"
<tr class='test-source'><th>Source: </th><td><pre>
"
+
escapeText
(
source
)
+
"
</pre></td></tr>
"
;
}
output
+=
"
</table>
"
;
}
runLoggingCallbacks
(
"
log
"
,
QUnit
,
details
);
config
.
current
.
assertions
.
push
({
result
:
!!
result
,
message
:
output
});
},
pushFailure
:
function
(
message
,
source
,
actual
)
{
if
(
!
config
.
current
)
{
throw
new
Error
(
"
pushFailure() assertion outside test context, was
"
+
sourceFromStacktrace
(
2
)
);
}
var
output
,
details
=
{
module
:
config
.
current
.
module
,
name
:
config
.
current
.
testName
,
result
:
false
,
message
:
message
};
message
=
escapeText
(
message
)
||
"
error
"
;
message
=
"
<span class='test-message'>
"
+
message
+
"
</span>
"
;
output
=
message
;
output
+=
"
<table>
"
;
if
(
actual
)
{
output
+=
"
<tr class='test-actual'><th>Result: </th><td><pre>
"
+
escapeText
(
actual
)
+
"
</pre></td></tr>
"
;
}
if
(
source
)
{
details
.
source
=
source
;
output
+=
"
<tr class='test-source'><th>Source: </th><td><pre>
"
+
escapeText
(
source
)
+
"
</pre></td></tr>
"
;
}
output
+=
"
</table>
"
;
runLoggingCallbacks
(
"
log
"
,
QUnit
,
details
);
config
.
current
.
assertions
.
push
({
result
:
false
,
message
:
output
});
},
url
:
function
(
params
)
{
params
=
extend
(
extend
(
{},
QUnit
.
urlParams
),
params
);
var
key
,
...
...
@@ -526,13 +366,7 @@ extend( QUnit, {
window
.
location
.
pathname
+
querystring
.
slice
(
0
,
-
1
);
},
extend
:
extend
,
id
:
id
,
addEvent
:
addEvent
,
addClass
:
addClass
,
hasClass
:
hasClass
,
removeClass
:
removeClass
// load, equiv, jsDump, diff: Attached later
extend
:
extend
});
/**
...
...
@@ -567,215 +401,29 @@ extend( QUnit.constructor.prototype, {
moduleDone
:
registerLoggingCallback
(
"
moduleDone
"
)
});
if
(
!
defined
.
document
||
document
.
readyState
===
"
complete
"
)
{
config
.
autorun
=
true
;
}
QUnit
.
load
=
function
()
{
runLoggingCallbacks
(
"
begin
"
,
QUnit
,
{}
);
// Initialize the config, saving the execution queue
var
banner
,
filter
,
i
,
j
,
label
,
len
,
main
,
ol
,
toolbar
,
val
,
selection
,
urlConfigContainer
,
moduleFilter
,
userAgent
,
numModules
=
0
,
moduleNames
=
[],
moduleFilterHtml
=
""
,
urlConfigHtml
=
""
,
oldconfig
=
extend
(
{},
config
);
QUnit
.
init
();
extend
(
config
,
oldconfig
);
config
.
blocking
=
false
;
len
=
config
.
urlConfig
.
length
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
val
=
config
.
urlConfig
[
i
];
if
(
typeof
val
===
"
string
"
)
{
val
=
{
id
:
val
,
label
:
val
};
}
config
[
val
.
id
]
=
QUnit
.
urlParams
[
val
.
id
];
if
(
!
val
.
value
||
typeof
val
.
value
===
"
string
"
)
{
urlConfigHtml
+=
"
<input id='qunit-urlconfig-
"
+
escapeText
(
val
.
id
)
+
"
' name='
"
+
escapeText
(
val
.
id
)
+
"
' type='checkbox'
"
+
(
val
.
value
?
"
value='
"
+
escapeText
(
val
.
value
)
+
"
'
"
:
""
)
+
(
config
[
val
.
id
]
?
"
checked='checked'
"
:
""
)
+
"
title='
"
+
escapeText
(
val
.
tooltip
)
+
"
'><label for='qunit-urlconfig-
"
+
escapeText
(
val
.
id
)
+
"
' title='
"
+
escapeText
(
val
.
tooltip
)
+
"
'>
"
+
val
.
label
+
"
</label>
"
;
}
else
{
urlConfigHtml
+=
"
<label for='qunit-urlconfig-
"
+
escapeText
(
val
.
id
)
+
"
' title='
"
+
escapeText
(
val
.
tooltip
)
+
"
'>
"
+
val
.
label
+
"
: </label><select id='qunit-urlconfig-
"
+
escapeText
(
val
.
id
)
+
"
' name='
"
+
escapeText
(
val
.
id
)
+
"
' title='
"
+
escapeText
(
val
.
tooltip
)
+
"
'><option></option>
"
;
selection
=
false
;
if
(
QUnit
.
is
(
"
array
"
,
val
.
value
)
)
{
for
(
j
=
0
;
j
<
val
.
value
.
length
;
j
++
)
{
urlConfigHtml
+=
"
<option value='
"
+
escapeText
(
val
.
value
[
j
]
)
+
"
'
"
+
(
config
[
val
.
id
]
===
val
.
value
[
j
]
?
(
selection
=
true
)
&&
"
selected='selected'
"
:
""
)
+
"
>
"
+
escapeText
(
val
.
value
[
j
]
)
+
"
</option>
"
;
}
}
else
{
for
(
j
in
val
.
value
)
{
if
(
hasOwn
.
call
(
val
.
value
,
j
)
)
{
urlConfigHtml
+=
"
<option value='
"
+
escapeText
(
j
)
+
"
'
"
+
(
config
[
val
.
id
]
===
j
?
(
selection
=
true
)
&&
"
selected='selected'
"
:
""
)
+
"
>
"
+
escapeText
(
val
.
value
[
j
]
)
+
"
</option>
"
;
}
}
}
if
(
config
[
val
.
id
]
&&
!
selection
)
{
urlConfigHtml
+=
"
<option value='
"
+
escapeText
(
config
[
val
.
id
]
)
+
"
' selected='selected' disabled='disabled'>
"
+
escapeText
(
config
[
val
.
id
]
)
+
"
</option>
"
;
}
urlConfigHtml
+=
"
</select>
"
;
}
}
for
(
i
in
config
.
modules
)
{
if
(
config
.
modules
.
hasOwnProperty
(
i
)
)
{
moduleNames
.
push
(
i
);
}
}
numModules
=
moduleNames
.
length
;
moduleNames
.
sort
(
function
(
a
,
b
)
{
return
a
.
localeCompare
(
b
);
runLoggingCallbacks
(
"
begin
"
,
{
totalTests
:
Test
.
count
});
moduleFilterHtml
+=
"
<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value=''
"
+
(
config
.
module
===
undefined
?
"
selected='selected'
"
:
""
)
+
"
>< All Modules ></option>
"
;
for
(
i
=
0
;
i
<
numModules
;
i
++
)
{
moduleFilterHtml
+=
"
<option value='
"
+
escapeText
(
encodeURIComponent
(
moduleNames
[
i
])
)
+
"
'
"
+
(
config
.
module
===
moduleNames
[
i
]
?
"
selected='selected'
"
:
""
)
+
"
>
"
+
escapeText
(
moduleNames
[
i
])
+
"
</option>
"
;
}
moduleFilterHtml
+=
"
</select>
"
;
// `userAgent` initialized at top of scope
userAgent
=
id
(
"
qunit-userAgent
"
);
if
(
userAgent
)
{
userAgent
.
innerHTML
=
navigator
.
userAgent
;
}
// `banner` initialized at top of scope
banner
=
id
(
"
qunit-header
"
);
if
(
banner
)
{
banner
.
innerHTML
=
"
<a href='
"
+
QUnit
.
url
({
filter
:
undefined
,
module
:
undefined
,
testNumber
:
undefined
})
+
"
'>
"
+
banner
.
innerHTML
+
"
</a>
"
;
}
// `toolbar` initialized at top of scope
toolbar
=
id
(
"
qunit-testrunner-toolbar
"
);
if
(
toolbar
)
{
// `filter` initialized at top of scope
filter
=
document
.
createElement
(
"
input
"
);
filter
.
type
=
"
checkbox
"
;
filter
.
id
=
"
qunit-filter-pass
"
;
addEvent
(
filter
,
"
click
"
,
function
()
{
var
tmp
,
ol
=
id
(
"
qunit-tests
"
);
if
(
filter
.
checked
)
{
ol
.
className
=
ol
.
className
+
"
hidepass
"
;
}
else
{
tmp
=
"
"
+
ol
.
className
.
replace
(
/
[\n\t\r]
/g
,
"
"
)
+
"
"
;
ol
.
className
=
tmp
.
replace
(
/ hidepass /
,
"
"
);
}
if
(
defined
.
sessionStorage
)
{
if
(
filter
.
checked
)
{
sessionStorage
.
setItem
(
"
qunit-filter-passed-tests
"
,
"
true
"
);
}
else
{
sessionStorage
.
removeItem
(
"
qunit-filter-passed-tests
"
);
}
}
});
if
(
config
.
hidepassed
||
defined
.
sessionStorage
&&
sessionStorage
.
getItem
(
"
qunit-filter-passed-tests
"
)
)
{
filter
.
checked
=
true
;
// `ol` initialized at top of scope
ol
=
id
(
"
qunit-tests
"
);
ol
.
className
=
ol
.
className
+
"
hidepass
"
;
}
toolbar
.
appendChild
(
filter
);
// `label` initialized at top of scope
label
=
document
.
createElement
(
"
label
"
);
label
.
setAttribute
(
"
for
"
,
"
qunit-filter-pass
"
);
label
.
setAttribute
(
"
title
"
,
"
Only show tests and assertions that fail. Stored in sessionStorage.
"
);
label
.
innerHTML
=
"
Hide passed tests
"
;
toolbar
.
appendChild
(
label
);
urlConfigContainer
=
document
.
createElement
(
"
span
"
);
urlConfigContainer
.
innerHTML
=
urlConfigHtml
;
// For oldIE support:
// * Add handlers to the individual elements instead of the container
// * Use "click" instead of "change" for checkboxes
// * Fallback from event.target to event.srcElement
addEvents
(
urlConfigContainer
.
getElementsByTagName
(
"
input
"
),
"
click
"
,
function
(
event
)
{
var
params
=
{},
target
=
event
.
target
||
event
.
srcElement
;
params
[
target
.
name
]
=
target
.
checked
?
target
.
defaultValue
||
true
:
undefined
;
window
.
location
=
QUnit
.
url
(
params
);
});
addEvents
(
urlConfigContainer
.
getElementsByTagName
(
"
select
"
),
"
change
"
,
function
(
event
)
{
var
params
=
{},
target
=
event
.
target
||
event
.
srcElement
;
params
[
target
.
name
]
=
target
.
options
[
target
.
selectedIndex
].
value
||
undefined
;
window
.
location
=
QUnit
.
url
(
params
);
});
toolbar
.
appendChild
(
urlConfigContainer
);
if
(
numModules
>
1
)
{
moduleFilter
=
document
.
createElement
(
"
span
"
);
moduleFilter
.
setAttribute
(
"
id
"
,
"
qunit-modulefilter-container
"
);
moduleFilter
.
innerHTML
=
moduleFilterHtml
;
addEvent
(
moduleFilter
.
lastChild
,
"
change
"
,
function
()
{
var
selectBox
=
moduleFilter
.
getElementsByTagName
(
"
select
"
)[
0
],
selectedModule
=
decodeURIComponent
(
selectBox
.
options
[
selectBox
.
selectedIndex
].
value
);
window
.
location
=
QUnit
.
url
({
module
:
(
selectedModule
===
""
)
?
undefined
:
selectedModule
,
// Remove any existing filters
filter
:
undefined
,
testNumber
:
undefined
});
});
toolbar
.
appendChild
(
moduleFilter
);
}
}
// Initialize the configuration options
extend
(
config
,
{
stats
:
{
all
:
0
,
bad
:
0
},
moduleStats
:
{
all
:
0
,
bad
:
0
},
started
:
0
,
updateRate
:
1000
,
autostart
:
true
,
filter
:
""
,
semaphore
:
1
},
true
);
// `main` initialized at top of scope
main
=
id
(
"
qunit-fixture
"
);
if
(
main
)
{
config
.
fixture
=
main
.
innerHTML
;
}
config
.
blocking
=
false
;
if
(
config
.
autostart
)
{
QUnit
.
start
();
}
};
if
(
defined
.
document
)
{
addEvent
(
window
,
"
load
"
,
QUnit
.
load
);
}
// `onErrorFnPrev` initialized at top of scope
// Preserve other handlers
onErrorFnPrev
=
window
.
onerror
;
...
...
@@ -783,7 +431,7 @@ onErrorFnPrev = window.onerror;
// Cover uncaught exceptions
// Returning true will suppress the default browser handler,
// returning false will let it run.
window
.
onerror
=
function
(
error
,
filePath
,
linerNr
)
{
window
.
onerror
=
function
(
error
,
filePath
,
linerNr
)
{
var
ret
=
false
;
if
(
onErrorFnPrev
)
{
ret
=
onErrorFnPrev
(
error
,
filePath
,
linerNr
);
...
...
@@ -798,7 +446,7 @@ window.onerror = function ( error, filePath, linerNr ) {
}
QUnit
.
pushFailure
(
error
,
filePath
+
"
:
"
+
linerNr
);
}
else
{
QUnit
.
test
(
"
global failure
"
,
extend
(
function
()
{
QUnit
.
test
(
"
global failure
"
,
extend
(
function
()
{
QUnit
.
pushFailure
(
error
,
filePath
+
"
:
"
+
linerNr
);
},
{
validTest
:
validTest
}
)
);
}
...
...
@@ -813,7 +461,7 @@ function done() {
// Log the last module results
if
(
config
.
previousModule
)
{
runLoggingCallbacks
(
"
moduleDone
"
,
QUnit
,
{
runLoggingCallbacks
(
"
moduleDone
"
,
{
name
:
config
.
previousModule
,
failed
:
config
.
moduleStats
.
bad
,
passed
:
config
.
moduleStats
.
all
-
config
.
moduleStats
.
bad
,
...
...
@@ -822,58 +470,10 @@ function done() {
}
delete
config
.
previousModule
;
var
i
,
key
,
banner
=
id
(
"
qunit-banner
"
),
tests
=
id
(
"
qunit-tests
"
),
runtime
=
+
new
Date
()
-
config
.
started
,
passed
=
config
.
stats
.
all
-
config
.
stats
.
bad
,
html
=
[
"
Tests completed in
"
,
runtime
,
"
milliseconds.<br/>
"
,
"
<span class='passed'>
"
,
passed
,
"
</span> assertions of <span class='total'>
"
,
config
.
stats
.
all
,
"
</span> passed, <span class='failed'>
"
,
config
.
stats
.
bad
,
"
</span> failed.
"
].
join
(
""
);
if
(
banner
)
{
banner
.
className
=
(
config
.
stats
.
bad
?
"
qunit-fail
"
:
"
qunit-pass
"
);
}
if
(
tests
)
{
id
(
"
qunit-testresult
"
).
innerHTML
=
html
;
}
if
(
config
.
altertitle
&&
defined
.
document
&&
document
.
title
)
{
// show ✖ for good, ✔ for bad suite result in title
// use escape sequences in case file gets loaded with non-utf-8-charset
document
.
title
=
[
(
config
.
stats
.
bad
?
"
\
u2716
"
:
"
\
u2714
"
),
document
.
title
.
replace
(
/^
[\u
2714
\u
2716
]
/i
,
""
)
].
join
(
"
"
);
}
// clear own sessionStorage items if all tests passed
if
(
config
.
reorder
&&
defined
.
sessionStorage
&&
config
.
stats
.
bad
===
0
)
{
// `key` & `i` initialized at top of scope
for
(
i
=
0
;
i
<
sessionStorage
.
length
;
i
++
)
{
key
=
sessionStorage
.
key
(
i
++
);
if
(
key
.
indexOf
(
"
qunit-test-
"
)
===
0
)
{
sessionStorage
.
removeItem
(
key
);
}
}
}
// scroll back to top to show results
if
(
config
.
scrolltop
&&
window
.
scrollTo
)
{
window
.
scrollTo
(
0
,
0
);
}
var
runtime
=
now
()
-
config
.
started
,
passed
=
config
.
stats
.
all
-
config
.
stats
.
bad
;
runLoggingCallbacks
(
"
done
"
,
QUnit
,
{
runLoggingCallbacks
(
"
done
"
,
{
failed
:
config
.
stats
.
bad
,
passed
:
passed
,
total
:
config
.
stats
.
all
,
...
...
@@ -922,21 +522,22 @@ function validTest( test ) {
return
!
include
;
}
// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
// Later Safari and IE10 are supposed to support error.stack as well
// Doesn't support IE6 to IE9
// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
function
extractStacktrace
(
e
,
offset
)
{
offset
=
offset
===
undefined
?
3
:
offset
;
offset
=
offset
===
undefined
?
4
:
offset
;
var
stack
,
include
,
i
;
if
(
e
.
stacktrace
)
{
// Opera
// Opera 12.x
return
e
.
stacktrace
.
split
(
"
\n
"
)[
offset
+
3
];
}
else
if
(
e
.
stack
)
{
// Firefox, Chrome
// Firefox, Chrome, Safari 6+, IE10+, PhantomJS and Node
stack
=
e
.
stack
.
split
(
"
\n
"
);
if
(
/^error$/i
.
test
(
stack
[
0
]
)
)
{
if
(
/^error$/i
.
test
(
stack
[
0
]
)
)
{
stack
.
shift
();
}
if
(
fileName
)
{
...
...
@@ -953,12 +554,13 @@ function extractStacktrace( e, offset ) {
}
return
stack
[
offset
];
}
else
if
(
e
.
sourceURL
)
{
// Safari, PhantomJS
//
hopefully one day Safari provides actual stacktraces
//
Safari < 6
// exclude useless self-reference for generated Error objects
if
(
/qunit.js$/
.
test
(
e
.
sourceURL
)
)
{
return
;
}
// for actual exceptions, this is useful
return
e
.
sourceURL
+
"
:
"
+
e
.
line
;
}
...
...
@@ -971,31 +573,6 @@ function sourceFromStacktrace( offset ) {
}
}
/**
* Escape text for attribute or text content.
*/
function
escapeText
(
s
)
{
if
(
!
s
)
{
return
""
;
}
s
=
s
+
""
;
// Both single quotes and double quotes (for attributes)
return
s
.
replace
(
/
[
'"<>&
]
/g
,
function
(
s
)
{
switch
(
s
)
{
case
"
'
"
:
return
"
'
"
;
case
"
\"
"
:
return
"
"
"
;
case
"
<
"
:
return
"
<
"
;
case
"
>
"
:
return
"
>
"
;
case
"
&
"
:
return
"
&
"
;
}
});
}
function
synchronize
(
callback
,
last
)
{
config
.
queue
.
push
(
callback
);
...
...
@@ -1008,11 +585,11 @@ function process( last ) {
function
next
()
{
process
(
last
);
}
var
start
=
n
ew
Date
().
getTime
();
var
start
=
n
ow
();
config
.
depth
=
config
.
depth
?
config
.
depth
+
1
:
1
;
while
(
config
.
queue
.
length
&&
!
config
.
blocking
)
{
if
(
!
defined
.
setTimeout
||
config
.
updateRate
<=
0
||
(
(
n
ew
Date
().
getTime
()
-
start
)
<
config
.
updateRate
)
)
{
if
(
!
defined
.
setTimeout
||
config
.
updateRate
<=
0
||
(
(
n
ow
()
-
start
)
<
config
.
updateRate
)
)
{
config
.
queue
.
shift
()();
}
else
{
setTimeout
(
next
,
13
);
...
...
@@ -1050,12 +627,12 @@ function checkPollution() {
newGlobals
=
diff
(
config
.
pollution
,
old
);
if
(
newGlobals
.
length
>
0
)
{
QUnit
.
pushFailure
(
"
Introduced global variable(s):
"
+
newGlobals
.
join
(
"
,
"
)
);
QUnit
.
pushFailure
(
"
Introduced global variable(s):
"
+
newGlobals
.
join
(
"
,
"
)
);
}
deletedGlobals
=
diff
(
old
,
config
.
pollution
);
if
(
deletedGlobals
.
length
>
0
)
{
QUnit
.
pushFailure
(
"
Deleted global variable(s):
"
+
deletedGlobals
.
join
(
"
,
"
)
);
QUnit
.
pushFailure
(
"
Deleted global variable(s):
"
+
deletedGlobals
.
join
(
"
,
"
)
);
}
}
...
...
@@ -1066,7 +643,7 @@ function diff( a, b ) {
for
(
i
=
0
;
i
<
result
.
length
;
i
++
)
{
for
(
j
=
0
;
j
<
b
.
length
;
j
++
)
{
if
(
result
[
i
]
===
b
[
j
]
)
{
if
(
result
[
i
]
===
b
[
j
]
)
{
result
.
splice
(
i
,
1
);
i
--
;
break
;
...
...
@@ -1076,14 +653,15 @@ function diff( a, b ) {
return
result
;
}
function
extend
(
a
,
b
)
{
function
extend
(
a
,
b
,
undefOnly
)
{
for
(
var
prop
in
b
)
{
if
(
hasOwn
.
call
(
b
,
prop
)
)
{
// Avoid "Member not found" error in IE8 caused by messing with window.constructor
if
(
!
(
prop
===
"
constructor
"
&&
a
===
window
)
)
{
if
(
b
[
prop
]
===
undefined
)
{
delete
a
[
prop
];
}
else
{
}
else
if
(
!
(
undefOnly
&&
typeof
a
[
prop
]
!==
"
undefined
"
)
)
{
a
[
prop
]
=
b
[
prop
];
}
}
...
...
@@ -1093,79 +671,24 @@ function extend( a, b ) {
return
a
;
}
/**
* @param {HTMLElement} elem
* @param {string} type
* @param {Function} fn
*/
function
addEvent
(
elem
,
type
,
fn
)
{
if
(
elem
.
addEventListener
)
{
// Standards-based browsers
elem
.
addEventListener
(
type
,
fn
,
false
);
}
else
if
(
elem
.
attachEvent
)
{
// support: IE <9
elem
.
attachEvent
(
"
on
"
+
type
,
fn
);
}
else
{
function
registerLoggingCallback
(
key
)
{
// Caller must ensure support for event listeners is present
throw
new
Error
(
"
addEvent() was called in a context without event listener support
"
);
// Initialize key collection of logging callback
if
(
QUnit
.
objectType
(
config
.
callbacks
[
key
]
)
===
"
undefined
"
)
{
config
.
callbacks
[
key
]
=
[];
}
return
function
(
callback
)
{
config
.
callbacks
[
key
].
push
(
callback
);
};
}
/**
* @param {Array|NodeList} elems
* @param {string} type
* @param {Function} fn
*/
function
addEvents
(
elems
,
type
,
fn
)
{
var
i
=
elems
.
length
;
while
(
i
--
)
{
addEvent
(
elems
[
i
],
type
,
fn
);
}
}
function
hasClass
(
elem
,
name
)
{
return
(
"
"
+
elem
.
className
+
"
"
).
indexOf
(
"
"
+
name
+
"
"
)
>
-
1
;
}
function
addClass
(
elem
,
name
)
{
if
(
!
hasClass
(
elem
,
name
)
)
{
elem
.
className
+=
(
elem
.
className
?
"
"
:
""
)
+
name
;
}
}
function
removeClass
(
elem
,
name
)
{
var
set
=
"
"
+
elem
.
className
+
"
"
;
// Class name may appear multiple times
while
(
set
.
indexOf
(
"
"
+
name
+
"
"
)
>
-
1
)
{
set
=
set
.
replace
(
"
"
+
name
+
"
"
,
"
"
);
}
// If possible, trim it for prettiness, but not necessarily
elem
.
className
=
typeof
set
.
trim
===
"
function
"
?
set
.
trim
()
:
set
.
replace
(
/^
\s
+|
\s
+$/g
,
""
);
}
function
id
(
name
)
{
return
defined
.
document
&&
document
.
getElementById
&&
document
.
getElementById
(
name
);
}
function
registerLoggingCallback
(
key
)
{
return
function
(
callback
)
{
config
[
key
].
push
(
callback
);
};
}
// Supports deprecated method of completely overwriting logging callbacks
function
runLoggingCallbacks
(
key
,
scope
,
args
)
{
var
i
,
callbacks
;
if
(
QUnit
.
hasOwnProperty
(
key
)
)
{
QUnit
[
key
].
call
(
scope
,
args
);
}
else
{
callbacks
=
config
[
key
];
for
(
i
=
0
;
i
<
callbacks
.
length
;
i
++
)
{
callbacks
[
i
].
call
(
scope
,
args
);
}
function
runLoggingCallbacks
(
key
,
args
)
{
var
i
,
l
,
callbacks
;
callbacks
=
config
.
callbacks
[
key
];
for
(
i
=
0
,
l
=
callbacks
.
length
;
i
<
l
;
i
++
)
{
callbacks
[
i
](
args
);
}
}
...
...
@@ -1186,6 +709,7 @@ function inArray( elem, array ) {
function
Test
(
settings
)
{
extend
(
this
,
settings
);
this
.
assert
=
new
Assert
(
this
);
this
.
assertions
=
[];
this
.
testNumber
=
++
Test
.
count
;
}
...
...
@@ -1193,32 +717,12 @@ function Test( settings ) {
Test
.
count
=
0
;
Test
.
prototype
=
{
init
:
function
()
{
var
a
,
b
,
li
,
tests
=
id
(
"
qunit-tests
"
);
if
(
tests
)
{
b
=
document
.
createElement
(
"
strong
"
);
b
.
innerHTML
=
this
.
nameHtml
;
// `a` initialized at top of scope
a
=
document
.
createElement
(
"
a
"
);
a
.
innerHTML
=
"
Rerun
"
;
a
.
href
=
QUnit
.
url
({
testNumber
:
this
.
testNumber
});
li
=
document
.
createElement
(
"
li
"
);
li
.
appendChild
(
b
);
li
.
appendChild
(
a
);
li
.
className
=
"
running
"
;
li
.
id
=
this
.
id
=
"
qunit-test-output
"
+
testId
++
;
tests
.
appendChild
(
li
);
}
},
setup
:
function
()
{
if
(
// Emit moduleStart when we're switching from one module to another
this
.
module
!==
config
.
previousModule
||
// They could be equal (both undefined) but if the previousModule property doesn't
// yet exist it means this is the first test in a suite that isn't wrapped in a
// module, in which case we'll just emit a moduleStart event for 'undefined'.
...
...
@@ -1226,7 +730,7 @@ Test.prototype = {
!
hasOwn
.
call
(
config
,
"
previousModule
"
)
)
{
if
(
hasOwn
.
call
(
config
,
"
previousModule
"
)
)
{
runLoggingCallbacks
(
"
moduleDone
"
,
QUnit
,
{
runLoggingCallbacks
(
"
moduleDone
"
,
{
name
:
config
.
previousModule
,
failed
:
config
.
moduleStats
.
bad
,
passed
:
config
.
moduleStats
.
all
-
config
.
moduleStats
.
bad
,
...
...
@@ -1235,7 +739,7 @@ Test.prototype = {
}
config
.
previousModule
=
this
.
module
;
config
.
moduleStats
=
{
all
:
0
,
bad
:
0
};
runLoggingCallbacks
(
"
moduleStart
"
,
QUnit
,
{
runLoggingCallbacks
(
"
moduleStart
"
,
{
name
:
this
.
module
});
}
...
...
@@ -1247,65 +751,49 @@ Test.prototype = {
teardown
:
function
()
{}
},
this
.
moduleTestEnvironment
);
this
.
started
=
+
new
Date
();
runLoggingCallbacks
(
"
testStart
"
,
QUnit
,
{
this
.
started
=
now
();
runLoggingCallbacks
(
"
testStart
"
,
{
name
:
this
.
testName
,
module
:
this
.
module
module
:
this
.
module
,
testNumber
:
this
.
testNumber
});
/*jshint camelcase:false */
/**
* Expose the current test environment.
*
* @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead.
*/
QUnit
.
current_testEnvironment
=
this
.
testEnvironment
;
/*jshint camelcase:true */
if
(
!
config
.
pollution
)
{
saveGlobal
();
}
if
(
config
.
notrycatch
)
{
this
.
testEnvironment
.
setup
.
call
(
this
.
testEnvironment
,
QUnit
.
assert
);
this
.
testEnvironment
.
setup
.
call
(
this
.
testEnvironment
,
this
.
assert
);
return
;
}
try
{
this
.
testEnvironment
.
setup
.
call
(
this
.
testEnvironment
,
QUnit
.
assert
);
}
catch
(
e
)
{
QUnit
.
pushFailure
(
"
Setup failed on
"
+
this
.
testName
+
"
:
"
+
(
e
.
message
||
e
),
extractStacktrace
(
e
,
1
)
);
this
.
testEnvironment
.
setup
.
call
(
this
.
testEnvironment
,
this
.
assert
);
}
catch
(
e
)
{
this
.
pushFailure
(
"
Setup failed on
"
+
this
.
testName
+
"
:
"
+
(
e
.
message
||
e
),
extractStacktrace
(
e
,
0
)
);
}
},
run
:
function
()
{
config
.
current
=
this
;
var
running
=
id
(
"
qunit-testresult
"
);
if
(
running
)
{
running
.
innerHTML
=
"
Running: <br/>
"
+
this
.
nameHtml
;
}
if
(
this
.
async
)
{
QUnit
.
stop
();
}
this
.
callbackStarted
=
+
new
Date
();
this
.
callbackStarted
=
now
();
if
(
config
.
notrycatch
)
{
this
.
callback
.
call
(
this
.
testEnvironment
,
QUnit
.
assert
);
this
.
callbackRuntime
=
+
new
Date
()
-
this
.
callbackStarted
;
this
.
callback
.
call
(
this
.
testEnvironment
,
this
.
assert
);
this
.
callbackRuntime
=
now
()
-
this
.
callbackStarted
;
return
;
}
try
{
this
.
callback
.
call
(
this
.
testEnvironment
,
QUnit
.
assert
);
this
.
callbackRuntime
=
+
new
Date
()
-
this
.
callbackStarted
;
}
catch
(
e
)
{
this
.
callbackRuntime
=
+
new
Date
()
-
this
.
callbackStarted
;
this
.
callback
.
call
(
this
.
testEnvironment
,
this
.
assert
);
this
.
callbackRuntime
=
now
()
-
this
.
callbackStarted
;
}
catch
(
e
)
{
this
.
callbackRuntime
=
now
()
-
this
.
callbackStarted
;
this
.
pushFailure
(
"
Died on test #
"
+
(
this
.
assertions
.
length
+
1
)
+
"
"
+
this
.
stack
+
"
:
"
+
(
e
.
message
||
e
),
extractStacktrace
(
e
,
0
)
);
QUnit
.
pushFailure
(
"
Died on test #
"
+
(
this
.
assertions
.
length
+
1
)
+
"
"
+
this
.
stack
+
"
:
"
+
(
e
.
message
||
e
),
extractStacktrace
(
e
,
0
)
);
// else next test will carry the responsibility
saveGlobal
();
...
...
@@ -1319,15 +807,15 @@ Test.prototype = {
config
.
current
=
this
;
if
(
config
.
notrycatch
)
{
if
(
typeof
this
.
callbackRuntime
===
"
undefined
"
)
{
this
.
callbackRuntime
=
+
new
Date
()
-
this
.
callbackStarted
;
this
.
callbackRuntime
=
now
()
-
this
.
callbackStarted
;
}
this
.
testEnvironment
.
teardown
.
call
(
this
.
testEnvironment
,
QUnit
.
assert
);
this
.
testEnvironment
.
teardown
.
call
(
this
.
testEnvironment
,
this
.
assert
);
return
;
}
else
{
try
{
this
.
testEnvironment
.
teardown
.
call
(
this
.
testEnvironment
,
QUnit
.
assert
);
}
catch
(
e
)
{
QUnit
.
pushFailure
(
"
Teardown failed on
"
+
this
.
testName
+
"
:
"
+
(
e
.
message
||
e
),
extractStacktrace
(
e
,
1
)
);
this
.
testEnvironment
.
teardown
.
call
(
this
.
testEnvironment
,
this
.
assert
);
}
catch
(
e
)
{
this
.
pushFailure
(
"
Teardown failed on
"
+
this
.
testName
+
"
:
"
+
(
e
.
message
||
e
),
extractStacktrace
(
e
,
0
)
);
}
}
checkPollution
();
...
...
@@ -1335,115 +823,44 @@ Test.prototype = {
finish
:
function
()
{
config
.
current
=
this
;
if
(
config
.
requireExpects
&&
this
.
expected
===
null
)
{
QUnit
.
pushFailure
(
"
Expected number of assertions to be defined, but expect() was not called.
"
,
this
.
stack
);
this
.
pushFailure
(
"
Expected number of assertions to be defined, but expect() was not called.
"
,
this
.
stack
);
}
else
if
(
this
.
expected
!==
null
&&
this
.
expected
!==
this
.
assertions
.
length
)
{
QUnit
.
pushFailure
(
"
Expected
"
+
this
.
expected
+
"
assertions, but
"
+
this
.
assertions
.
length
+
"
were run
"
,
this
.
stack
);
this
.
pushFailure
(
"
Expected
"
+
this
.
expected
+
"
assertions, but
"
+
this
.
assertions
.
length
+
"
were run
"
,
this
.
stack
);
}
else
if
(
this
.
expected
===
null
&&
!
this
.
assertions
.
length
)
{
QUnit
.
pushFailure
(
"
Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.
"
,
this
.
stack
);
this
.
pushFailure
(
"
Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.
"
,
this
.
stack
);
}
var
i
,
assertion
,
a
,
b
,
time
,
li
,
ol
,
test
=
this
,
good
=
0
,
bad
=
0
,
tests
=
id
(
"
qunit-tests
"
);
var
i
,
bad
=
0
;
this
.
runtime
=
+
new
Date
()
-
this
.
started
;
this
.
runtime
=
now
()
-
this
.
started
;
config
.
stats
.
all
+=
this
.
assertions
.
length
;
config
.
moduleStats
.
all
+=
this
.
assertions
.
length
;
if
(
tests
)
{
ol
=
document
.
createElement
(
"
ol
"
);
ol
.
className
=
"
qunit-assert-list
"
;
for
(
i
=
0
;
i
<
this
.
assertions
.
length
;
i
++
)
{
assertion
=
this
.
assertions
[
i
];
li
=
document
.
createElement
(
"
li
"
);
li
.
className
=
assertion
.
result
?
"
pass
"
:
"
fail
"
;
li
.
innerHTML
=
assertion
.
message
||
(
assertion
.
result
?
"
okay
"
:
"
failed
"
);
ol
.
appendChild
(
li
);
if
(
assertion
.
result
)
{
good
++
;
}
else
{
bad
++
;
config
.
stats
.
bad
++
;
config
.
moduleStats
.
bad
++
;
}
}
// store result when possible
if
(
QUnit
.
config
.
reorder
&&
defined
.
sessionStorage
)
{
if
(
bad
)
{
sessionStorage
.
setItem
(
"
qunit-test-
"
+
this
.
module
+
"
-
"
+
this
.
testName
,
bad
);
}
else
{
sessionStorage
.
removeItem
(
"
qunit-test-
"
+
this
.
module
+
"
-
"
+
this
.
testName
);
}
}
if
(
bad
===
0
)
{
addClass
(
ol
,
"
qunit-collapsed
"
);
}
// `b` initialized at top of scope
b
=
document
.
createElement
(
"
strong
"
);
b
.
innerHTML
=
this
.
nameHtml
+
"
<b class='counts'>(<b class='failed'>
"
+
bad
+
"
</b>, <b class='passed'>
"
+
good
+
"
</b>,
"
+
this
.
assertions
.
length
+
"
)</b>
"
;
addEvent
(
b
,
"
click
"
,
function
()
{
var
next
=
b
.
parentNode
.
lastChild
,
collapsed
=
hasClass
(
next
,
"
qunit-collapsed
"
);
(
collapsed
?
removeClass
:
addClass
)(
next
,
"
qunit-collapsed
"
);
});
addEvent
(
b
,
"
dblclick
"
,
function
(
e
)
{
var
target
=
e
&&
e
.
target
?
e
.
target
:
window
.
event
.
srcElement
;
if
(
target
.
nodeName
.
toLowerCase
()
===
"
span
"
||
target
.
nodeName
.
toLowerCase
()
===
"
b
"
)
{
target
=
target
.
parentNode
;
}
if
(
window
.
location
&&
target
.
nodeName
.
toLowerCase
()
===
"
strong
"
)
{
window
.
location
=
QUnit
.
url
({
testNumber
:
test
.
testNumber
});
}
});
// `time` initialized at top of scope
time
=
document
.
createElement
(
"
span
"
);
time
.
className
=
"
runtime
"
;
time
.
innerHTML
=
this
.
runtime
+
"
ms
"
;
// `li` initialized at top of scope
li
=
id
(
this
.
id
);
li
.
className
=
bad
?
"
fail
"
:
"
pass
"
;
li
.
removeChild
(
li
.
firstChild
);
a
=
li
.
firstChild
;
li
.
appendChild
(
b
);
li
.
appendChild
(
a
);
li
.
appendChild
(
time
);
li
.
appendChild
(
ol
);
}
else
{
for
(
i
=
0
;
i
<
this
.
assertions
.
length
;
i
++
)
{
if
(
!
this
.
assertions
[
i
].
result
)
{
bad
++
;
config
.
stats
.
bad
++
;
config
.
moduleStats
.
bad
++
;
}
for
(
i
=
0
;
i
<
this
.
assertions
.
length
;
i
++
)
{
if
(
!
this
.
assertions
[
i
].
result
)
{
bad
++
;
config
.
stats
.
bad
++
;
config
.
moduleStats
.
bad
++
;
}
}
runLoggingCallbacks
(
"
testDone
"
,
QUnit
,
{
runLoggingCallbacks
(
"
testDone
"
,
{
name
:
this
.
testName
,
module
:
this
.
module
,
failed
:
bad
,
passed
:
this
.
assertions
.
length
-
bad
,
total
:
this
.
assertions
.
length
,
runtime
:
this
.
runtime
,
// HTML Reporter use
assertions
:
this
.
assertions
,
testNumber
:
this
.
testNumber
,
// DEPRECATED: this property will be removed in 2.0.0, use runtime instead
duration
:
this
.
runtime
});
QUnit
.
reset
();
config
.
current
=
undefined
;
},
...
...
@@ -1451,9 +868,6 @@ Test.prototype = {
var
bad
,
test
=
this
;
synchronize
(
function
()
{
test
.
init
();
});
function
run
()
{
// each of these can by async
synchronize
(
function
()
{
...
...
@@ -1473,59 +887,129 @@ Test.prototype = {
// `bad` initialized at top of scope
// defer when previous test run passed, if storage is available
bad
=
QUnit
.
config
.
reorder
&&
defined
.
sessionStorage
&&
+
sessionStorage
.
getItem
(
"
qunit-test-
"
+
this
.
module
+
"
-
"
+
this
.
testName
);
+
sessionStorage
.
getItem
(
"
qunit-test-
"
+
this
.
module
+
"
-
"
+
this
.
testName
);
if
(
bad
)
{
run
();
}
else
{
synchronize
(
run
,
true
);
}
}
};
// `assert` initialized at top of scope
// Assert helpers
// All of these must either call QUnit.push() or manually do:
// - runLoggingCallbacks( "log", .. );
// - config.current.assertions.push({ .. });
assert
=
QUnit
.
assert
=
{
/**
* Asserts rough true-ish result.
* @name ok
* @function
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
*/
ok
:
function
(
result
,
msg
)
{
if
(
!
config
.
current
)
{
throw
new
Error
(
"
ok() assertion outside test context, was
"
+
sourceFromStacktrace
(
2
)
);
}
result
=
!!
result
;
msg
=
msg
||
(
result
?
"
okay
"
:
"
failed
"
);
},
push
:
function
(
result
,
actual
,
expected
,
message
)
{
var
source
,
details
=
{
module
:
config
.
current
.
module
,
name
:
config
.
current
.
testName
,
module
:
this
.
module
,
name
:
this
.
testName
,
result
:
result
,
message
:
msg
message
:
message
,
actual
:
actual
,
expected
:
expected
,
testNumber
:
this
.
testNumber
};
msg
=
"
<span class='test-message'>
"
+
escapeText
(
msg
)
+
"
</span>
"
;
if
(
!
result
)
{
source
=
sourceFromStacktrace
(
2
);
source
=
sourceFromStacktrace
();
if
(
source
)
{
details
.
source
=
source
;
msg
+=
"
<table><tr class='test-source'><th>Source: </th><td><pre>
"
+
escapeText
(
source
)
+
"
</pre></td></tr></table>
"
;
}
}
runLoggingCallbacks
(
"
log
"
,
QUnit
,
details
);
config
.
current
.
assertions
.
push
({
result
:
result
,
message
:
msg
runLoggingCallbacks
(
"
log
"
,
details
);
this
.
assertions
.
push
({
result
:
!!
result
,
message
:
message
});
},
pushFailure
:
function
(
message
,
source
,
actual
)
{
if
(
!
this
instanceof
Test
)
{
throw
new
Error
(
"
pushFailure() assertion outside test context, was
"
+
sourceFromStacktrace
(
2
)
);
}
var
details
=
{
module
:
this
.
module
,
name
:
this
.
testName
,
result
:
false
,
message
:
message
||
"
error
"
,
actual
:
actual
||
null
,
testNumber
:
this
.
testNumber
};
if
(
source
)
{
details
.
source
=
source
;
}
runLoggingCallbacks
(
"
log
"
,
details
);
this
.
assertions
.
push
({
result
:
false
,
message
:
message
});
}
};
QUnit
.
pushFailure
=
function
()
{
if
(
!
QUnit
.
config
.
current
)
{
throw
new
Error
(
"
pushFailure() assertion outside test context, in
"
+
sourceFromStacktrace
(
2
)
);
}
// Gets current test obj
var
currentTest
=
QUnit
.
config
.
current
.
assert
.
test
;
return
currentTest
.
pushFailure
.
apply
(
currentTest
,
arguments
);
};
function
Assert
(
testContext
)
{
this
.
test
=
testContext
;
}
// Assert helpers
QUnit
.
assert
=
Assert
.
prototype
=
{
// Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through.
expect
:
function
(
asserts
)
{
if
(
arguments
.
length
===
1
)
{
this
.
test
.
expected
=
asserts
;
}
else
{
return
this
.
test
.
expected
;
}
},
// Exports test.push() to the user API
push
:
function
()
{
var
assert
=
this
;
// Backwards compatibility fix.
// Allows the direct use of global exported assertions and QUnit.assert.*
// Although, it's use is not recommended as it can leak assertions
// to other tests from async tests, because we only get a reference to the current test,
// not exactly the test where assertion were intended to be called.
if
(
!
QUnit
.
config
.
current
)
{
throw
new
Error
(
"
assertion outside test context, in
"
+
sourceFromStacktrace
(
2
)
);
}
if
(
!
(
assert
instanceof
Assert
)
)
{
assert
=
QUnit
.
config
.
current
.
assert
;
}
return
assert
.
test
.
push
.
apply
(
assert
.
test
,
arguments
);
},
/**
* Asserts rough true-ish result.
* @name ok
* @function
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
*/
ok
:
function
(
result
,
message
)
{
message
=
message
||
(
result
?
"
okay
"
:
"
failed, expected argument to be truthy, was:
"
+
QUnit
.
dump
.
parse
(
result
)
);
if
(
!!
result
)
{
this
.
push
(
true
,
result
,
true
,
message
);
}
else
{
this
.
test
.
pushFailure
(
message
,
null
,
result
);
}
},
/**
...
...
@@ -1537,7 +1021,7 @@ assert = QUnit.assert = {
*/
equal
:
function
(
actual
,
expected
,
message
)
{
/*jshint eqeqeq:false */
QUnit
.
push
(
expected
==
actual
,
actual
,
expected
,
message
);
this
.
push
(
expected
==
actual
,
actual
,
expected
,
message
);
},
/**
...
...
@@ -1546,7 +1030,7 @@ assert = QUnit.assert = {
*/
notEqual
:
function
(
actual
,
expected
,
message
)
{
/*jshint eqeqeq:false */
QUnit
.
push
(
expected
!=
actual
,
actual
,
expected
,
message
);
this
.
push
(
expected
!=
actual
,
actual
,
expected
,
message
);
},
/**
...
...
@@ -1554,9 +1038,9 @@ assert = QUnit.assert = {
* @function
*/
propEqual
:
function
(
actual
,
expected
,
message
)
{
actual
=
objectValues
(
actual
);
expected
=
objectValues
(
expected
);
QUnit
.
push
(
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
actual
=
objectValues
(
actual
);
expected
=
objectValues
(
expected
);
this
.
push
(
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
},
/**
...
...
@@ -1564,9 +1048,9 @@ assert = QUnit.assert = {
* @function
*/
notPropEqual
:
function
(
actual
,
expected
,
message
)
{
actual
=
objectValues
(
actual
);
expected
=
objectValues
(
expected
);
QUnit
.
push
(
!
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
actual
=
objectValues
(
actual
);
expected
=
objectValues
(
expected
);
this
.
push
(
!
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
},
/**
...
...
@@ -1574,7 +1058,7 @@ assert = QUnit.assert = {
* @function
*/
deepEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
this
.
push
(
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
},
/**
...
...
@@ -1582,7 +1066,7 @@ assert = QUnit.assert = {
* @function
*/
notDeepEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
!
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
this
.
push
(
!
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
},
/**
...
...
@@ -1590,7 +1074,7 @@ assert = QUnit.assert = {
* @function
*/
strictEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
expected
===
actual
,
actual
,
expected
,
message
);
this
.
push
(
expected
===
actual
,
actual
,
expected
,
message
);
},
/**
...
...
@@ -1598,91 +1082,67 @@ assert = QUnit.assert = {
* @function
*/
notStrictEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
expected
!==
actual
,
actual
,
expected
,
message
);
this
.
push
(
expected
!==
actual
,
actual
,
expected
,
message
);
},
"
throws
"
:
function
(
block
,
expected
,
message
)
{
var
actual
,
var
actual
,
expectedType
,
expectedOutput
=
expected
,
ok
=
false
;
// 'expected' is optional
if
(
!
message
&&
typeof
expected
===
"
string
"
)
{
// 'expected' is optional
unless doing string comparison
if
(
message
==
null
&&
typeof
expected
===
"
string
"
)
{
message
=
expected
;
expected
=
null
;
}
config
.
curren
t
.
ignoreGlobalErrors
=
true
;
this
.
tes
t
.
ignoreGlobalErrors
=
true
;
try
{
block
.
call
(
config
.
curren
t
.
testEnvironment
);
block
.
call
(
this
.
tes
t
.
testEnvironment
);
}
catch
(
e
)
{
actual
=
e
;
}
config
.
curren
t
.
ignoreGlobalErrors
=
false
;
this
.
tes
t
.
ignoreGlobalErrors
=
false
;
if
(
actual
)
{
expectedType
=
QUnit
.
objectType
(
expected
);
// we don't want to validate thrown error
if
(
!
expected
)
{
ok
=
true
;
expectedOutput
=
null
;
// expected is an Error object
}
else
if
(
expected
instanceof
Error
)
{
ok
=
actual
instanceof
Error
&&
actual
.
name
===
expected
.
name
&&
actual
.
message
===
expected
.
message
;
// expected is a regexp
}
else
if
(
QUnit
.
objectType
(
expected
)
===
"
regexp
"
)
{
}
else
if
(
expectedType
===
"
regexp
"
)
{
ok
=
expected
.
test
(
errorString
(
actual
)
);
// expected is a string
}
else
if
(
QUnit
.
objectType
(
expected
)
===
"
string
"
)
{
}
else
if
(
expectedType
===
"
string
"
)
{
ok
=
expected
===
errorString
(
actual
);
// expected is a constructor
}
else
if
(
actual
instanceof
expected
)
{
// expected is a constructor
, maybe an Error constructor
}
else
if
(
expectedType
===
"
function
"
&&
actual
instanceof
expected
)
{
ok
=
true
;
// expected is a validation function which returns true is validation passed
}
else
if
(
expected
.
call
(
{},
actual
)
===
true
)
{
// expected is an Error object
}
else
if
(
expectedType
===
"
object
"
)
{
ok
=
actual
instanceof
expected
.
constructor
&&
actual
.
name
===
expected
.
name
&&
actual
.
message
===
expected
.
message
;
// expected is a validation function which returns true if validation passed
}
else
if
(
expectedType
===
"
function
"
&&
expected
.
call
(
{},
actual
)
===
true
)
{
expectedOutput
=
null
;
ok
=
true
;
}
QUnit
.
push
(
ok
,
actual
,
expectedOutput
,
message
);
this
.
push
(
ok
,
actual
,
expectedOutput
,
message
);
}
else
{
QUni
t
.
pushFailure
(
message
,
null
,
"
No exception was thrown.
"
);
this
.
tes
t
.
pushFailure
(
message
,
null
,
"
No exception was thrown.
"
);
}
}
};
/**
* @deprecated since 1.8.0
* Kept assertion helpers in root for backwards compatibility.
*/
extend
(
QUnit
.
constructor
.
prototype
,
assert
);
/**
* @deprecated since 1.9.0
* Kept to avoid TypeErrors for undefined methods.
*/
QUnit
.
constructor
.
prototype
.
raises
=
function
()
{
QUnit
.
push
(
false
,
false
,
false
,
"
QUnit.raises has been deprecated since 2012 (fad3c1ea), use QUnit.throws instead
"
);
};
/**
* @deprecated since 1.0.0, replaced with error pushes since 1.3.0
* Kept to avoid TypeErrors for undefined methods.
*/
QUnit
.
constructor
.
prototype
.
equals
=
function
()
{
QUnit
.
push
(
false
,
false
,
false
,
"
QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead
"
);
};
QUnit
.
constructor
.
prototype
.
same
=
function
()
{
QUnit
.
push
(
false
,
false
,
false
,
"
QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead
"
);
};
// Test for equality any JavaScript type.
// Author: Philippe Rathé <prathe@gmail.com>
QUnit
.
equiv
=
(
function
()
{
...
...
@@ -1701,22 +1161,26 @@ QUnit.equiv = (function() {
// the real equiv function
var
innerEquiv
,
// stack to decide between skip/abort functions
callers
=
[],
// stack to avoiding loops from circular referencing
parents
=
[],
parentsB
=
[],
getProto
=
Object
.
getPrototypeOf
||
function
(
obj
)
{
/*
jshint camelcase:fals
e */
getProto
=
Object
.
getPrototypeOf
||
function
(
obj
)
{
/*
jshint camelcase: false, proto: tru
e */
return
obj
.
__proto__
;
},
callbacks
=
(
function
()
{
callbacks
=
(
function
()
{
// for string, boolean, number and null
function
useStrictEquality
(
b
,
a
)
{
/*jshint eqeqeq:false */
if
(
b
instanceof
a
.
constructor
||
a
instanceof
b
.
constructor
)
{
// to catch short annotation VS 'new' annotation of a
// declaration
// e.g. var i = 1;
...
...
@@ -1744,10 +1208,13 @@ QUnit.equiv = (function() {
"
regexp
"
:
function
(
b
,
a
)
{
return
QUnit
.
objectType
(
b
)
===
"
regexp
"
&&
// the regex itself
a
.
source
===
b
.
source
&&
// and its modifiers
a
.
global
===
b
.
global
&&
// (gmi) ...
a
.
ignoreCase
===
b
.
ignoreCase
&&
a
.
multiline
===
b
.
multiline
&&
...
...
@@ -1758,7 +1225,7 @@ QUnit.equiv = (function() {
// - abort otherwise,
// initial === would have catch identical references anyway
"
function
"
:
function
()
{
var
caller
=
callers
[
callers
.
length
-
1
];
var
caller
=
callers
[
callers
.
length
-
1
];
return
caller
!==
Object
&&
typeof
caller
!==
"
undefined
"
;
},
...
...
@@ -1782,10 +1249,10 @@ QUnit.equiv = (function() {
for
(
i
=
0
;
i
<
len
;
i
++
)
{
loop
=
false
;
for
(
j
=
0
;
j
<
parents
.
length
;
j
++
)
{
aCircular
=
parents
[
j
]
===
a
[
i
];
bCircular
=
parentsB
[
j
]
===
b
[
i
];
aCircular
=
parents
[
j
]
===
a
[
i
];
bCircular
=
parentsB
[
j
]
===
b
[
i
];
if
(
aCircular
||
bCircular
)
{
if
(
a
[
i
]
===
b
[
i
]
||
aCircular
&&
bCircular
)
{
if
(
a
[
i
]
===
b
[
i
]
||
aCircular
&&
bCircular
)
{
loop
=
true
;
}
else
{
parents
.
pop
();
...
...
@@ -1794,7 +1261,7 @@ QUnit.equiv = (function() {
}
}
}
if
(
!
loop
&&
!
innerEquiv
(
a
[
i
],
b
[
i
]
)
)
{
if
(
!
loop
&&
!
innerEquiv
(
a
[
i
],
b
[
i
]
)
)
{
parents
.
pop
();
parentsB
.
pop
();
return
false
;
...
...
@@ -1806,6 +1273,7 @@ QUnit.equiv = (function() {
},
"
object
"
:
function
(
b
,
a
)
{
/*jshint forin:false */
var
i
,
j
,
loop
,
aCircular
,
bCircular
,
// Default to true
...
...
@@ -1816,11 +1284,12 @@ QUnit.equiv = (function() {
// comparing constructors is more strict than using
// instanceof
if
(
a
.
constructor
!==
b
.
constructor
)
{
// Allow objects with no prototype to be equivalent to
// objects with Object as their constructor.
if
(
!
(
(
getProto
(
a
)
===
null
&&
getProto
(
b
)
===
Object
.
prototype
)
||
(
getProto
(
b
)
===
null
&&
getProto
(
a
)
===
Object
.
prototype
)
)
)
{
return
false
;
if
(
!
(
(
getProto
(
a
)
===
null
&&
getProto
(
b
)
===
Object
.
prototype
)
||
(
getProto
(
b
)
===
null
&&
getProto
(
a
)
===
Object
.
prototype
)
)
)
{
return
false
;
}
}
...
...
@@ -1835,10 +1304,10 @@ QUnit.equiv = (function() {
for
(
i
in
a
)
{
loop
=
false
;
for
(
j
=
0
;
j
<
parents
.
length
;
j
++
)
{
aCircular
=
parents
[
j
]
===
a
[
i
];
bCircular
=
parentsB
[
j
]
===
b
[
i
];
aCircular
=
parents
[
j
]
===
a
[
i
];
bCircular
=
parentsB
[
j
]
===
b
[
i
];
if
(
aCircular
||
bCircular
)
{
if
(
a
[
i
]
===
b
[
i
]
||
aCircular
&&
bCircular
)
{
if
(
a
[
i
]
===
b
[
i
]
||
aCircular
&&
bCircular
)
{
loop
=
true
;
}
else
{
eq
=
false
;
...
...
@@ -1846,8 +1315,8 @@ QUnit.equiv = (function() {
}
}
}
aProperties
.
push
(
i
);
if
(
!
loop
&&
!
innerEquiv
(
a
[
i
],
b
[
i
]
)
)
{
aProperties
.
push
(
i
);
if
(
!
loop
&&
!
innerEquiv
(
a
[
i
],
b
[
i
]
)
)
{
eq
=
false
;
break
;
}
...
...
@@ -1873,35 +1342,29 @@ QUnit.equiv = (function() {
return
true
;
// end transition
}
return
(
function
(
a
,
b
)
{
return
(
(
function
(
a
,
b
)
{
if
(
a
===
b
)
{
return
true
;
// catch the most you can
}
else
if
(
a
===
null
||
b
===
null
||
typeof
a
===
"
undefined
"
||
typeof
b
===
"
undefined
"
||
QUnit
.
objectType
(
a
)
!==
QUnit
.
objectType
(
b
)
)
{
return
false
;
// don't lose time with error prone cases
QUnit
.
objectType
(
a
)
!==
QUnit
.
objectType
(
b
)
)
{
// don't lose time with error prone cases
return
false
;
}
else
{
return
bindCallbacks
(
a
,
callbacks
,
[
b
,
a
]
);
return
bindCallbacks
(
a
,
callbacks
,
[
b
,
a
]
);
}
// apply transition with (1..n) arguments
}(
args
[
0
],
args
[
1
]
)
&&
innerEquiv
.
apply
(
this
,
args
.
splice
(
1
,
args
.
length
-
1
)
)
);
}(
args
[
0
],
args
[
1
]
)
)
&&
innerEquiv
.
apply
(
this
,
args
.
splice
(
1
,
args
.
length
-
1
)
)
);
};
return
innerEquiv
;
}());
/**
* jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
* http://flesler.blogspot.com Licensed under BSD
* (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
*
* @projectDescription Advanced and extensible data dumping for Javascript.
* @version 1.0.0
* @author Ariel Flesler
* @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
*/
QUnit
.
jsDump
=
(
function
()
{
// Based on jsDump by Ariel Flesler
// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
QUnit
.
dump
=
(
function
()
{
function
quote
(
str
)
{
return
"
\"
"
+
str
.
toString
().
replace
(
/"/g
,
"
\\\"
"
)
+
"
\"
"
;
}
...
...
@@ -1909,42 +1372,43 @@ QUnit.jsDump = (function() {
return
o
+
""
;
}
function
join
(
pre
,
arr
,
post
)
{
var
s
=
jsD
ump
.
separator
(),
base
=
jsD
ump
.
indent
(),
inner
=
jsDump
.
indent
(
1
);
var
s
=
d
ump
.
separator
(),
base
=
d
ump
.
indent
(),
inner
=
dump
.
indent
(
1
);
if
(
arr
.
join
)
{
arr
=
arr
.
join
(
"
,
"
+
s
+
inner
);
}
if
(
!
arr
)
{
return
pre
+
post
;
}
return
[
pre
,
inner
+
arr
,
base
+
post
].
join
(
s
);
return
[
pre
,
inner
+
arr
,
base
+
post
].
join
(
s
);
}
function
array
(
arr
,
stack
)
{
var
i
=
arr
.
length
,
ret
=
new
Array
(
i
);
var
i
=
arr
.
length
,
ret
=
new
Array
(
i
);
this
.
up
();
while
(
i
--
)
{
ret
[
i
]
=
this
.
parse
(
arr
[
i
]
,
undefined
,
stack
);
ret
[
i
]
=
this
.
parse
(
arr
[
i
],
undefined
,
stack
);
}
this
.
down
();
return
join
(
"
[
"
,
ret
,
"
]
"
);
}
var
reName
=
/^function
(\w
+
)
/
,
jsD
ump
=
{
d
ump
=
{
// type is used mostly internally, you can fix a (custom)type in advance
parse
:
function
(
obj
,
type
,
stack
)
{
stack
=
stack
||
[
];
stack
=
stack
||
[];
var
inStack
,
res
,
parser
=
this
.
parsers
[
type
||
this
.
typeOf
(
obj
)
];
parser
=
this
.
parsers
[
type
||
this
.
typeOf
(
obj
)
];
type
=
typeof
parser
;
inStack
=
inArray
(
obj
,
stack
);
if
(
inStack
!==
-
1
)
{
return
"
recursion(
"
+
(
inStack
-
stack
.
length
)
+
"
)
"
;
return
"
recursion(
"
+
(
inStack
-
stack
.
length
)
+
"
)
"
;
}
if
(
type
===
"
function
"
)
{
if
(
type
===
"
function
"
)
{
stack
.
push
(
obj
);
res
=
parser
.
call
(
this
,
obj
,
stack
);
stack
.
pop
();
...
...
@@ -1958,11 +1422,11 @@ QUnit.jsDump = (function() {
type
=
"
null
"
;
}
else
if
(
typeof
obj
===
"
undefined
"
)
{
type
=
"
undefined
"
;
}
else
if
(
QUnit
.
is
(
"
regexp
"
,
obj
)
)
{
}
else
if
(
QUnit
.
is
(
"
regexp
"
,
obj
)
)
{
type
=
"
regexp
"
;
}
else
if
(
QUnit
.
is
(
"
date
"
,
obj
)
)
{
}
else
if
(
QUnit
.
is
(
"
date
"
,
obj
)
)
{
type
=
"
date
"
;
}
else
if
(
QUnit
.
is
(
"
function
"
,
obj
)
)
{
}
else
if
(
QUnit
.
is
(
"
function
"
,
obj
)
)
{
type
=
"
function
"
;
}
else
if
(
typeof
obj
.
setInterval
!==
undefined
&&
typeof
obj
.
document
!==
"
undefined
"
&&
typeof
obj
.
nodeType
===
"
undefined
"
)
{
type
=
"
window
"
;
...
...
@@ -1971,10 +1435,12 @@ QUnit.jsDump = (function() {
}
else
if
(
obj
.
nodeType
)
{
type
=
"
node
"
;
}
else
if
(
// native arrays
toString
.
call
(
obj
)
===
"
[object Array]
"
||
// NodeList objects
(
typeof
obj
.
length
===
"
number
"
&&
typeof
obj
.
item
!==
"
undefined
"
&&
(
obj
.
length
?
obj
.
item
(
0
)
===
obj
[
0
]
:
(
obj
.
item
(
0
)
===
null
&&
typeof
obj
[
0
]
===
"
undefined
"
)
)
)
(
typeof
obj
.
length
===
"
number
"
&&
typeof
obj
.
item
!==
"
undefined
"
&&
(
obj
.
length
?
obj
.
item
(
0
)
===
obj
[
0
]
:
(
obj
.
item
(
0
)
===
null
&&
typeof
obj
[
0
]
===
"
undefined
"
)
)
)
)
{
type
=
"
array
"
;
}
else
if
(
obj
.
constructor
===
Error
.
prototype
.
constructor
)
{
...
...
@@ -1985,7 +1451,7 @@ QUnit.jsDump = (function() {
return
type
;
},
separator
:
function
()
{
return
this
.
multiline
?
this
.
HTML
?
"
<br />
"
:
"
\n
"
:
this
.
HTML
?
"
"
:
"
"
;
return
this
.
multiline
?
this
.
HTML
?
"
<br />
"
:
"
\n
"
:
this
.
HTML
?
"
"
:
"
"
;
},
// extra can be a number, shortcut for increasing-calling-decreasing
indent
:
function
(
extra
)
{
...
...
@@ -1996,7 +1462,7 @@ QUnit.jsDump = (function() {
if
(
this
.
HTML
)
{
chr
=
chr
.
replace
(
/
\t
/g
,
"
"
).
replace
(
/ /g
,
"
"
);
}
return
new
Array
(
this
.
depth
+
(
extra
||
0
)
).
join
(
chr
);
return
new
Array
(
this
.
depth
+
(
extra
||
0
)
).
join
(
chr
);
},
up
:
function
(
a
)
{
this
.
depth
+=
a
||
1
;
...
...
@@ -2005,7 +1471,7 @@ QUnit.jsDump = (function() {
this
.
depth
-=
a
||
1
;
},
setParser
:
function
(
name
,
parser
)
{
this
.
parsers
[
name
]
=
parser
;
this
.
parsers
[
name
]
=
parser
;
},
// The next 3 are exposed so you can use them
quote
:
quote
,
...
...
@@ -2013,11 +1479,11 @@ QUnit.jsDump = (function() {
join
:
join
,
//
depth
:
1
,
// This is the list of parsers, to modify them, use
jsD
ump.setParser
// This is the list of parsers, to modify them, use
d
ump.setParser
parsers
:
{
window
:
"
[Window]
"
,
document
:
"
[Document]
"
,
error
:
function
(
error
)
{
error
:
function
(
error
)
{
return
"
Error(
\"
"
+
error
.
message
+
"
\"
)
"
;
},
unknown
:
"
[Unknown]
"
,
...
...
@@ -2026,51 +1492,61 @@ QUnit.jsDump = (function() {
"
function
"
:
function
(
fn
)
{
var
ret
=
"
function
"
,
// functions never have name in IE
name
=
"
name
"
in
fn
?
fn
.
name
:
(
reName
.
exec
(
fn
)
||
[])[
1
];
name
=
"
name
"
in
fn
?
fn
.
name
:
(
reName
.
exec
(
fn
)
||
[]
)[
1
];
if
(
name
)
{
ret
+=
"
"
+
name
;
}
ret
+=
"
(
"
;
ret
=
[
ret
,
QUnit
.
jsD
ump
.
parse
(
fn
,
"
functionArgs
"
),
"
){
"
].
join
(
""
);
return
join
(
ret
,
QUnit
.
jsDump
.
parse
(
fn
,
"
functionCode
"
),
"
}
"
);
ret
=
[
ret
,
d
ump
.
parse
(
fn
,
"
functionArgs
"
),
"
){
"
].
join
(
""
);
return
join
(
ret
,
dump
.
parse
(
fn
,
"
functionCode
"
),
"
}
"
);
},
array
:
array
,
nodelist
:
array
,
"
arguments
"
:
array
,
object
:
function
(
map
,
stack
)
{
/*jshint forin:false */
var
ret
=
[
],
keys
,
key
,
val
,
i
;
QUnit
.
jsD
ump
.
up
();
var
ret
=
[
],
keys
,
key
,
val
,
i
,
nonEnumerableProperties
;
d
ump
.
up
();
keys
=
[];
for
(
key
in
map
)
{
keys
.
push
(
key
);
}
// Some properties are not always enumerable on Error objects.
nonEnumerableProperties
=
[
"
message
"
,
"
name
"
];
for
(
i
in
nonEnumerableProperties
)
{
key
=
nonEnumerableProperties
[
i
];
if
(
key
in
map
&&
!
(
key
in
keys
)
)
{
keys
.
push
(
key
);
}
}
keys
.
sort
();
for
(
i
=
0
;
i
<
keys
.
length
;
i
++
)
{
key
=
keys
[
i
];
val
=
map
[
key
];
ret
.
push
(
QUnit
.
jsDump
.
parse
(
key
,
"
key
"
)
+
"
:
"
+
QUnit
.
jsD
ump
.
parse
(
val
,
undefined
,
stack
)
);
ret
.
push
(
dump
.
parse
(
key
,
"
key
"
)
+
"
:
"
+
d
ump
.
parse
(
val
,
undefined
,
stack
)
);
}
QUnit
.
jsD
ump
.
down
();
d
ump
.
down
();
return
join
(
"
{
"
,
ret
,
"
}
"
);
},
node
:
function
(
node
)
{
var
len
,
i
,
val
,
open
=
QUnit
.
jsD
ump
.
HTML
?
"
<
"
:
"
<
"
,
close
=
QUnit
.
jsD
ump
.
HTML
?
"
>
"
:
"
>
"
,
open
=
d
ump
.
HTML
?
"
<
"
:
"
<
"
,
close
=
d
ump
.
HTML
?
"
>
"
:
"
>
"
,
tag
=
node
.
nodeName
.
toLowerCase
(),
ret
=
open
+
tag
,
attrs
=
node
.
attributes
;
if
(
attrs
)
{
for
(
i
=
0
,
len
=
attrs
.
length
;
i
<
len
;
i
++
)
{
val
=
attrs
[
i
].
nodeValue
;
val
=
attrs
[
i
].
nodeValue
;
// IE6 includes all attributes in .attributes, even ones not explicitly set.
// Those have values like undefined, null, 0, false, "" or "inherit".
if
(
val
&&
val
!==
"
inherit
"
)
{
ret
+=
"
"
+
attrs
[
i
].
nodeName
+
"
=
"
+
QUnit
.
jsD
ump
.
parse
(
val
,
"
attribute
"
);
ret
+=
"
"
+
attrs
[
i
].
nodeName
+
"
=
"
+
d
ump
.
parse
(
val
,
"
attribute
"
);
}
}
}
...
...
@@ -2083,6 +1559,7 @@ QUnit.jsDump = (function() {
return
ret
+
open
+
"
/
"
+
tag
+
close
;
},
// function calls it internally, it's the arguments part of the function
functionArgs
:
function
(
fn
)
{
var
args
,
...
...
@@ -2092,10 +1569,11 @@ QUnit.jsDump = (function() {
return
""
;
}
args
=
new
Array
(
l
);
args
=
new
Array
(
l
);
while
(
l
--
)
{
// 97 is 'a'
args
[
l
]
=
String
.
fromCharCode
(
97
+
l
);
args
[
l
]
=
String
.
fromCharCode
(
97
+
l
);
}
return
"
"
+
args
.
join
(
"
,
"
)
+
"
"
;
},
...
...
@@ -2119,9 +1597,73 @@ QUnit.jsDump = (function() {
multiline
:
true
};
return
jsD
ump
;
return
d
ump
;
}());
// back compat
QUnit
.
jsDump
=
QUnit
.
dump
;
// For browser, export only select globals
if
(
typeof
window
!==
"
undefined
"
)
{
// Deprecated
// Extend assert methods to QUnit and Global scope through Backwards compatibility
(
function
()
{
var
i
,
assertions
=
Assert
.
prototype
;
function
applyCurrent
(
current
)
{
return
function
()
{
var
assert
=
new
Assert
(
QUnit
.
config
.
current
);
current
.
apply
(
assert
,
arguments
);
};
}
for
(
i
in
assertions
)
{
QUnit
[
i
]
=
applyCurrent
(
assertions
[
i
]
);
}
})();
(
function
()
{
var
i
,
l
,
keys
=
[
"
test
"
,
"
module
"
,
"
expect
"
,
"
asyncTest
"
,
"
start
"
,
"
stop
"
,
"
ok
"
,
"
equal
"
,
"
notEqual
"
,
"
propEqual
"
,
"
notPropEqual
"
,
"
deepEqual
"
,
"
notDeepEqual
"
,
"
strictEqual
"
,
"
notStrictEqual
"
,
"
throws
"
];
for
(
i
=
0
,
l
=
keys
.
length
;
i
<
l
;
i
++
)
{
window
[
keys
[
i
]
]
=
QUnit
[
keys
[
i
]
];
}
})();
window
.
QUnit
=
QUnit
;
}
// For CommonJS environments, export everything
if
(
typeof
module
!==
"
undefined
"
&&
module
.
exports
)
{
module
.
exports
=
QUnit
;
}
// Get a reference to the global object, like window in browsers
}(
(
function
()
{
return
this
;
})()
));
/*istanbul ignore next */
/*
* Javascript Diff Algorithm
* By John Resig (http://ejohn.org/)
...
...
@@ -2137,6 +1679,8 @@ QUnit.jsDump = (function() {
* QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
*/
QUnit
.
diff
=
(
function
()
{
var
hasOwn
=
Object
.
prototype
.
hasOwnProperty
;
/*jshint eqeqeq:false, eqnull:true */
function
diff
(
o
,
n
)
{
var
i
,
...
...
@@ -2144,65 +1688,65 @@ QUnit.diff = (function() {
os
=
{};
for
(
i
=
0
;
i
<
n
.
length
;
i
++
)
{
if
(
!
hasOwn
.
call
(
ns
,
n
[
i
]
)
)
{
ns
[
n
[
i
]
]
=
{
if
(
!
hasOwn
.
call
(
ns
,
n
[
i
]
)
)
{
ns
[
n
[
i
]
]
=
{
rows
:
[],
o
:
null
};
}
ns
[
n
[
i
]
].
rows
.
push
(
i
);
ns
[
n
[
i
]
].
rows
.
push
(
i
);
}
for
(
i
=
0
;
i
<
o
.
length
;
i
++
)
{
if
(
!
hasOwn
.
call
(
os
,
o
[
i
]
)
)
{
os
[
o
[
i
]
]
=
{
if
(
!
hasOwn
.
call
(
os
,
o
[
i
]
)
)
{
os
[
o
[
i
]
]
=
{
rows
:
[],
n
:
null
};
}
os
[
o
[
i
]
].
rows
.
push
(
i
);
os
[
o
[
i
]
].
rows
.
push
(
i
);
}
for
(
i
in
ns
)
{
if
(
hasOwn
.
call
(
ns
,
i
)
)
{
if
(
ns
[
i
].
rows
.
length
===
1
&&
hasOwn
.
call
(
os
,
i
)
&&
os
[
i
].
rows
.
length
===
1
)
{
n
[
ns
[
i
].
rows
[
0
]
]
=
{
text
:
n
[
ns
[
i
].
rows
[
0
]
],
row
:
os
[
i
].
rows
[
0
]
if
(
ns
[
i
].
rows
.
length
===
1
&&
hasOwn
.
call
(
os
,
i
)
&&
os
[
i
].
rows
.
length
===
1
)
{
n
[
ns
[
i
].
rows
[
0
]
]
=
{
text
:
n
[
ns
[
i
].
rows
[
0
]
],
row
:
os
[
i
].
rows
[
0
]
};
o
[
os
[
i
].
rows
[
0
]
]
=
{
text
:
o
[
os
[
i
].
rows
[
0
]
],
row
:
ns
[
i
].
rows
[
0
]
o
[
os
[
i
].
rows
[
0
]
]
=
{
text
:
o
[
os
[
i
].
rows
[
0
]
],
row
:
ns
[
i
].
rows
[
0
]
};
}
}
}
for
(
i
=
0
;
i
<
n
.
length
-
1
;
i
++
)
{
if
(
n
[
i
].
text
!=
null
&&
n
[
i
+
1
].
text
==
null
&&
n
[
i
].
row
+
1
<
o
.
length
&&
o
[
n
[
i
].
row
+
1
].
text
==
null
&&
n
[
i
+
1
]
==
o
[
n
[
i
].
row
+
1
]
)
{
if
(
n
[
i
].
text
!=
null
&&
n
[
i
+
1
].
text
==
null
&&
n
[
i
].
row
+
1
<
o
.
length
&&
o
[
n
[
i
].
row
+
1
].
text
==
null
&&
n
[
i
+
1
]
==
o
[
n
[
i
].
row
+
1
]
)
{
n
[
i
+
1
]
=
{
text
:
n
[
i
+
1
],
row
:
n
[
i
].
row
+
1
row
:
n
[
i
].
row
+
1
};
o
[
n
[
i
].
row
+
1
]
=
{
text
:
o
[
n
[
i
].
row
+
1
],
o
[
n
[
i
].
row
+
1
]
=
{
text
:
o
[
n
[
i
].
row
+
1
],
row
:
i
+
1
};
}
}
for
(
i
=
n
.
length
-
1
;
i
>
0
;
i
--
)
{
if
(
n
[
i
].
text
!=
null
&&
n
[
i
-
1
].
text
==
null
&&
n
[
i
].
row
>
0
&&
o
[
n
[
i
].
row
-
1
].
text
==
null
&&
n
[
i
-
1
]
==
o
[
n
[
i
].
row
-
1
]
)
{
if
(
n
[
i
].
text
!=
null
&&
n
[
i
-
1
].
text
==
null
&&
n
[
i
].
row
>
0
&&
o
[
n
[
i
].
row
-
1
].
text
==
null
&&
n
[
i
-
1
]
==
o
[
n
[
i
].
row
-
1
]
)
{
n
[
i
-
1
]
=
{
text
:
n
[
i
-
1
],
row
:
n
[
i
].
row
-
1
row
:
n
[
i
].
row
-
1
};
o
[
n
[
i
].
row
-
1
]
=
{
text
:
o
[
n
[
i
].
row
-
1
],
o
[
n
[
i
].
row
-
1
]
=
{
text
:
o
[
n
[
i
].
row
-
1
],
row
:
i
-
1
};
}
...
...
@@ -2220,48 +1764,45 @@ QUnit.diff = (function() {
var
i
,
pre
,
str
=
""
,
out
=
diff
(
o
===
""
?
[]
:
o
.
split
(
/
\s
+/
),
n
===
""
?
[]
:
n
.
split
(
/
\s
+/
)
),
oSpace
=
o
.
match
(
/
\s
+/g
),
nSpace
=
n
.
match
(
/
\s
+/g
);
out
=
diff
(
o
===
""
?
[]
:
o
.
split
(
/
\s
+/
),
n
===
""
?
[]
:
n
.
split
(
/
\s
+/
)
),
oSpace
=
o
.
match
(
/
\s
+/g
),
nSpace
=
n
.
match
(
/
\s
+/g
);
if
(
oSpace
==
null
)
{
oSpace
=
[
"
"
];
}
else
{
}
else
{
oSpace
.
push
(
"
"
);
}
if
(
nSpace
==
null
)
{
nSpace
=
[
"
"
];
}
else
{
}
else
{
nSpace
.
push
(
"
"
);
}
if
(
out
.
n
.
length
===
0
)
{
for
(
i
=
0
;
i
<
out
.
o
.
length
;
i
++
)
{
str
+=
"
<del>
"
+
out
.
o
[
i
]
+
oSpace
[
i
]
+
"
</del>
"
;
str
+=
"
<del>
"
+
out
.
o
[
i
]
+
oSpace
[
i
]
+
"
</del>
"
;
}
}
else
{
if
(
out
.
n
[
0
].
text
==
null
)
{
for
(
n
=
0
;
n
<
out
.
o
.
length
&&
out
.
o
[
n
].
text
==
null
;
n
++
)
{
str
+=
"
<del>
"
+
out
.
o
[
n
]
+
oSpace
[
n
]
+
"
</del>
"
;
}
else
{
if
(
out
.
n
[
0
].
text
==
null
)
{
for
(
n
=
0
;
n
<
out
.
o
.
length
&&
out
.
o
[
n
].
text
==
null
;
n
++
)
{
str
+=
"
<del>
"
+
out
.
o
[
n
]
+
oSpace
[
n
]
+
"
</del>
"
;
}
}
for
(
i
=
0
;
i
<
out
.
n
.
length
;
i
++
)
{
if
(
out
.
n
[
i
].
text
==
null
)
{
str
+=
"
<ins>
"
+
out
.
n
[
i
]
+
nSpace
[
i
]
+
"
</ins>
"
;
}
else
{
if
(
out
.
n
[
i
].
text
==
null
)
{
str
+=
"
<ins>
"
+
out
.
n
[
i
]
+
nSpace
[
i
]
+
"
</ins>
"
;
}
else
{
// `pre` initialized at top of scope
pre
=
""
;
for
(
n
=
out
.
n
[
i
].
row
+
1
;
n
<
out
.
o
.
length
&&
out
.
o
[
n
].
text
==
null
;
n
++
)
{
pre
+=
"
<del>
"
+
out
.
o
[
n
]
+
oSpace
[
n
]
+
"
</del>
"
;
for
(
n
=
out
.
n
[
i
].
row
+
1
;
n
<
out
.
o
.
length
&&
out
.
o
[
n
].
text
==
null
;
n
++
)
{
pre
+=
"
<del>
"
+
out
.
o
[
n
]
+
oSpace
[
n
]
+
"
</del>
"
;
}
str
+=
"
"
+
out
.
n
[
i
].
text
+
nSpace
[
i
]
+
pre
;
str
+=
"
"
+
out
.
n
[
i
].
text
+
nSpace
[
i
]
+
pre
;
}
}
}
...
...
@@ -2270,19 +1811,685 @@ QUnit.diff = (function() {
};
}());
// For browser, export only select globals
if
(
typeof
window
!==
"
undefined
"
)
{
extend
(
window
,
QUnit
.
constructor
.
prototype
);
window
.
QUnit
=
QUnit
;
}
(
function
()
{
// For CommonJS environments, export everything
if
(
typeof
module
!==
"
undefined
"
&&
module
.
exports
)
{
module
.
exports
=
QUnit
;
// Deprecated QUnit.init - Ref #530
// Re-initialize the configuration options
QUnit
.
init
=
function
()
{
var
tests
,
banner
,
result
,
qunit
,
config
=
QUnit
.
config
;
config
.
stats
=
{
all
:
0
,
bad
:
0
};
config
.
moduleStats
=
{
all
:
0
,
bad
:
0
};
config
.
started
=
0
;
config
.
updateRate
=
1000
;
config
.
blocking
=
false
;
config
.
autostart
=
true
;
config
.
autorun
=
false
;
config
.
filter
=
""
;
config
.
queue
=
[];
config
.
semaphore
=
1
;
// Return on non-browser environments
// This is necessary to not break on node tests
if
(
typeof
window
===
"
undefined
"
)
{
return
;
}
qunit
=
id
(
"
qunit
"
);
if
(
qunit
)
{
qunit
.
innerHTML
=
"
<h1 id='qunit-header'>
"
+
escapeText
(
document
.
title
)
+
"
</h1>
"
+
"
<h2 id='qunit-banner'></h2>
"
+
"
<div id='qunit-testrunner-toolbar'></div>
"
+
"
<h2 id='qunit-userAgent'></h2>
"
+
"
<ol id='qunit-tests'></ol>
"
;
}
tests
=
id
(
"
qunit-tests
"
);
banner
=
id
(
"
qunit-banner
"
);
result
=
id
(
"
qunit-testresult
"
);
if
(
tests
)
{
tests
.
innerHTML
=
""
;
}
if
(
banner
)
{
banner
.
className
=
""
;
}
if
(
result
)
{
result
.
parentNode
.
removeChild
(
result
);
}
if
(
tests
)
{
result
=
document
.
createElement
(
"
p
"
);
result
.
id
=
"
qunit-testresult
"
;
result
.
className
=
"
result
"
;
tests
.
parentNode
.
insertBefore
(
result
,
tests
);
result
.
innerHTML
=
"
Running...<br/>
"
;
}
};
// Resets the test setup. Useful for tests that modify the DOM.
/*
DEPRECATED: Use multiple tests instead of resetting inside a test.
Use testStart or testDone for custom cleanup.
This method will throw an error in 2.0, and will be removed in 2.1
*/
QUnit
.
reset
=
function
()
{
// Return on non-browser environments
// This is necessary to not break on node tests
if
(
typeof
window
===
"
undefined
"
)
{
return
;
}
var
fixture
=
id
(
"
qunit-fixture
"
);
if
(
fixture
)
{
fixture
.
innerHTML
=
config
.
fixture
;
}
};
// Don't load the HTML Reporter on non-Browser environments
if
(
typeof
window
===
"
undefined
"
)
{
return
;
}
var
config
=
QUnit
.
config
,
hasOwn
=
Object
.
prototype
.
hasOwnProperty
,
defined
=
{
document
:
typeof
window
.
document
!==
"
undefined
"
,
sessionStorage
:
(
function
()
{
var
x
=
"
qunit-test-string
"
;
try
{
sessionStorage
.
setItem
(
x
,
x
);
sessionStorage
.
removeItem
(
x
);
return
true
;
}
catch
(
e
)
{
return
false
;
}
}())
};
// Get a reference to the global object, like window in browsers
}(
(
function
()
{
return
this
;
})()
));
/**
* Escape text for attribute or text content.
*/
function
escapeText
(
s
)
{
if
(
!
s
)
{
return
""
;
}
s
=
s
+
""
;
// Both single quotes and double quotes (for attributes)
return
s
.
replace
(
/
[
'"<>&
]
/g
,
function
(
s
)
{
switch
(
s
)
{
case
"
'
"
:
return
"
'
"
;
case
"
\"
"
:
return
"
"
"
;
case
"
<
"
:
return
"
<
"
;
case
"
>
"
:
return
"
>
"
;
case
"
&
"
:
return
"
&
"
;
}
});
}
/**
* @param {HTMLElement} elem
* @param {string} type
* @param {Function} fn
*/
function
addEvent
(
elem
,
type
,
fn
)
{
if
(
elem
.
addEventListener
)
{
// Standards-based browsers
elem
.
addEventListener
(
type
,
fn
,
false
);
}
else
if
(
elem
.
attachEvent
)
{
// support: IE <9
elem
.
attachEvent
(
"
on
"
+
type
,
fn
);
}
}
/**
* @param {Array|NodeList} elems
* @param {string} type
* @param {Function} fn
*/
function
addEvents
(
elems
,
type
,
fn
)
{
var
i
=
elems
.
length
;
while
(
i
--
)
{
addEvent
(
elems
[
i
],
type
,
fn
);
}
}
function
hasClass
(
elem
,
name
)
{
return
(
"
"
+
elem
.
className
+
"
"
).
indexOf
(
"
"
+
name
+
"
"
)
>=
0
;
}
function
addClass
(
elem
,
name
)
{
if
(
!
hasClass
(
elem
,
name
)
)
{
elem
.
className
+=
(
elem
.
className
?
"
"
:
""
)
+
name
;
}
}
function
toggleClass
(
elem
,
name
)
{
if
(
hasClass
(
elem
,
name
)
)
{
removeClass
(
elem
,
name
);
}
else
{
addClass
(
elem
,
name
);
}
}
function
removeClass
(
elem
,
name
)
{
var
set
=
"
"
+
elem
.
className
+
"
"
;
// Class name may appear multiple times
while
(
set
.
indexOf
(
"
"
+
name
+
"
"
)
>=
0
)
{
set
=
set
.
replace
(
"
"
+
name
+
"
"
,
"
"
);
}
// trim for prettiness
elem
.
className
=
typeof
set
.
trim
===
"
function
"
?
set
.
trim
()
:
set
.
replace
(
/^
\s
+|
\s
+$/g
,
""
);
}
function
id
(
name
)
{
return
defined
.
document
&&
document
.
getElementById
&&
document
.
getElementById
(
name
);
}
function
getUrlConfigHtml
()
{
var
i
,
j
,
val
,
escaped
,
escapedTooltip
,
selection
=
false
,
len
=
config
.
urlConfig
.
length
,
urlConfigHtml
=
""
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
val
=
config
.
urlConfig
[
i
];
if
(
typeof
val
===
"
string
"
)
{
val
=
{
id
:
val
,
label
:
val
};
}
escaped
=
escapeText
(
val
.
id
);
escapedTooltip
=
escapeText
(
val
.
tooltip
);
config
[
val
.
id
]
=
QUnit
.
urlParams
[
val
.
id
];
if
(
!
val
.
value
||
typeof
val
.
value
===
"
string
"
)
{
urlConfigHtml
+=
"
<input id='qunit-urlconfig-
"
+
escaped
+
"
' name='
"
+
escaped
+
"
' type='checkbox'
"
+
(
val
.
value
?
"
value='
"
+
escapeText
(
val
.
value
)
+
"
'
"
:
""
)
+
(
config
[
val
.
id
]
?
"
checked='checked'
"
:
""
)
+
"
title='
"
+
escapedTooltip
+
"
'><label for='qunit-urlconfig-
"
+
escaped
+
"
' title='
"
+
escapedTooltip
+
"
'>
"
+
val
.
label
+
"
</label>
"
;
}
else
{
urlConfigHtml
+=
"
<label for='qunit-urlconfig-
"
+
escaped
+
"
' title='
"
+
escapedTooltip
+
"
'>
"
+
val
.
label
+
"
: </label><select id='qunit-urlconfig-
"
+
escaped
+
"
' name='
"
+
escaped
+
"
' title='
"
+
escapedTooltip
+
"
'><option></option>
"
;
if
(
QUnit
.
is
(
"
array
"
,
val
.
value
)
)
{
for
(
j
=
0
;
j
<
val
.
value
.
length
;
j
++
)
{
escaped
=
escapeText
(
val
.
value
[
j
]
);
urlConfigHtml
+=
"
<option value='
"
+
escaped
+
"
'
"
+
(
config
[
val
.
id
]
===
val
.
value
[
j
]
?
(
selection
=
true
)
&&
"
selected='selected'
"
:
""
)
+
"
>
"
+
escaped
+
"
</option>
"
;
}
}
else
{
for
(
j
in
val
.
value
)
{
if
(
hasOwn
.
call
(
val
.
value
,
j
)
)
{
urlConfigHtml
+=
"
<option value='
"
+
escapeText
(
j
)
+
"
'
"
+
(
config
[
val
.
id
]
===
j
?
(
selection
=
true
)
&&
"
selected='selected'
"
:
""
)
+
"
>
"
+
escapeText
(
val
.
value
[
j
]
)
+
"
</option>
"
;
}
}
}
if
(
config
[
val
.
id
]
&&
!
selection
)
{
escaped
=
escapeText
(
config
[
val
.
id
]
);
urlConfigHtml
+=
"
<option value='
"
+
escaped
+
"
' selected='selected' disabled='disabled'>
"
+
escaped
+
"
</option>
"
;
}
urlConfigHtml
+=
"
</select>
"
;
}
}
return
urlConfigHtml
;
}
function
toolbarUrlConfigContainer
()
{
var
urlConfigContainer
=
document
.
createElement
(
"
span
"
);
urlConfigContainer
.
innerHTML
=
getUrlConfigHtml
();
// For oldIE support:
// * Add handlers to the individual elements instead of the container
// * Use "click" instead of "change" for checkboxes
// * Fallback from event.target to event.srcElement
addEvents
(
urlConfigContainer
.
getElementsByTagName
(
"
input
"
),
"
click
"
,
function
(
event
)
{
var
params
=
{},
target
=
event
.
target
||
event
.
srcElement
;
params
[
target
.
name
]
=
target
.
checked
?
target
.
defaultValue
||
true
:
undefined
;
window
.
location
=
QUnit
.
url
(
params
);
});
addEvents
(
urlConfigContainer
.
getElementsByTagName
(
"
select
"
),
"
change
"
,
function
(
event
)
{
var
params
=
{},
target
=
event
.
target
||
event
.
srcElement
;
params
[
target
.
name
]
=
target
.
options
[
target
.
selectedIndex
].
value
||
undefined
;
window
.
location
=
QUnit
.
url
(
params
);
});
return
urlConfigContainer
;
}
function
getModuleNames
()
{
var
i
,
moduleNames
=
[];
for
(
i
in
config
.
modules
)
{
if
(
config
.
modules
.
hasOwnProperty
(
i
)
)
{
moduleNames
.
push
(
i
);
}
}
moduleNames
.
sort
(
function
(
a
,
b
)
{
return
a
.
localeCompare
(
b
);
});
return
moduleNames
;
}
function
toolbarModuleFilterHtml
()
{
var
i
,
moduleFilterHtml
=
""
,
moduleNames
=
getModuleNames
();
if
(
moduleNames
.
length
<=
1
)
{
return
false
;
}
moduleFilterHtml
+=
"
<label for='qunit-modulefilter'>Module: </label>
"
+
"
<select id='qunit-modulefilter' name='modulefilter'><option value=''
"
+
(
config
.
module
===
undefined
?
"
selected='selected'
"
:
""
)
+
"
>< All Modules ></option>
"
;
for
(
i
=
0
;
i
<
moduleNames
.
length
;
i
++
)
{
moduleFilterHtml
+=
"
<option value='
"
+
escapeText
(
encodeURIComponent
(
moduleNames
[
i
]
)
)
+
"
'
"
+
(
config
.
module
===
moduleNames
[
i
]
?
"
selected='selected'
"
:
""
)
+
"
>
"
+
escapeText
(
moduleNames
[
i
]
)
+
"
</option>
"
;
}
moduleFilterHtml
+=
"
</select>
"
;
return
moduleFilterHtml
;
}
function
toolbarModuleFilter
()
{
var
moduleFilter
=
document
.
createElement
(
"
span
"
),
moduleFilterHtml
=
toolbarModuleFilterHtml
();
if
(
!
moduleFilterHtml
)
{
return
false
;
}
moduleFilter
.
setAttribute
(
"
id
"
,
"
qunit-modulefilter-container
"
);
moduleFilter
.
innerHTML
=
moduleFilterHtml
;
addEvent
(
moduleFilter
.
lastChild
,
"
change
"
,
function
()
{
var
selectBox
=
moduleFilter
.
getElementsByTagName
(
"
select
"
)[
0
],
selectedModule
=
decodeURIComponent
(
selectBox
.
options
[
selectBox
.
selectedIndex
].
value
);
window
.
location
=
QUnit
.
url
({
module
:
(
selectedModule
===
""
)
?
undefined
:
selectedModule
,
// Remove any existing filters
filter
:
undefined
,
testNumber
:
undefined
});
});
return
moduleFilter
;
}
function
toolbarFilter
()
{
var
testList
=
id
(
"
qunit-tests
"
),
filter
=
document
.
createElement
(
"
input
"
);
filter
.
type
=
"
checkbox
"
;
filter
.
id
=
"
qunit-filter-pass
"
;
addEvent
(
filter
,
"
click
"
,
function
()
{
if
(
filter
.
checked
)
{
addClass
(
testList
,
"
hidepass
"
);
if
(
defined
.
sessionStorage
)
{
sessionStorage
.
setItem
(
"
qunit-filter-passed-tests
"
,
"
true
"
);
}
}
else
{
removeClass
(
testList
,
"
hidepass
"
);
if
(
defined
.
sessionStorage
)
{
sessionStorage
.
removeItem
(
"
qunit-filter-passed-tests
"
);
}
}
});
if
(
config
.
hidepassed
||
defined
.
sessionStorage
&&
sessionStorage
.
getItem
(
"
qunit-filter-passed-tests
"
)
)
{
filter
.
checked
=
true
;
addClass
(
testList
,
"
hidepass
"
);
}
return
filter
;
}
function
toolbarLabel
()
{
var
label
=
document
.
createElement
(
"
label
"
);
label
.
setAttribute
(
"
for
"
,
"
qunit-filter-pass
"
);
label
.
setAttribute
(
"
title
"
,
"
Only show tests and assertions that fail. Stored in sessionStorage.
"
);
label
.
innerHTML
=
"
Hide passed tests
"
;
return
label
;
}
function
appendToolbar
()
{
var
moduleFilter
,
toolbar
=
id
(
"
qunit-testrunner-toolbar
"
);
if
(
toolbar
)
{
toolbar
.
appendChild
(
toolbarFilter
()
);
toolbar
.
appendChild
(
toolbarLabel
()
);
toolbar
.
appendChild
(
toolbarUrlConfigContainer
()
);
moduleFilter
=
toolbarModuleFilter
();
if
(
moduleFilter
)
{
toolbar
.
appendChild
(
moduleFilter
);
}
}
}
function
appendBanner
()
{
var
banner
=
id
(
"
qunit-banner
"
);
if
(
banner
)
{
banner
.
className
=
""
;
banner
.
innerHTML
=
"
<a href='
"
+
QUnit
.
url
({
filter
:
undefined
,
module
:
undefined
,
testNumber
:
undefined
})
+
"
'>
"
+
banner
.
innerHTML
+
"
</a>
"
;
}
}
function
appendTestResults
()
{
var
tests
=
id
(
"
qunit-tests
"
),
result
=
id
(
"
qunit-testresult
"
);
if
(
result
)
{
result
.
parentNode
.
removeChild
(
result
);
}
if
(
tests
)
{
tests
.
innerHTML
=
""
;
result
=
document
.
createElement
(
"
p
"
);
result
.
id
=
"
qunit-testresult
"
;
result
.
className
=
"
result
"
;
tests
.
parentNode
.
insertBefore
(
result
,
tests
);
result
.
innerHTML
=
"
Running...<br>
"
;
}
}
function
storeFixture
()
{
var
fixture
=
id
(
"
qunit-fixture
"
);
if
(
fixture
)
{
config
.
fixture
=
fixture
.
innerHTML
;
}
}
function
appendUserAgent
()
{
var
userAgent
=
id
(
"
qunit-userAgent
"
);
if
(
userAgent
)
{
userAgent
.
innerHTML
=
navigator
.
userAgent
;
}
}
// HTML Reporter initialization and load
QUnit
.
begin
(
function
()
{
var
qunit
=
id
(
"
qunit
"
);
if
(
qunit
)
{
qunit
.
innerHTML
=
"
<h1 id='qunit-header'>
"
+
escapeText
(
document
.
title
)
+
"
</h1>
"
+
"
<h2 id='qunit-banner'></h2>
"
+
"
<div id='qunit-testrunner-toolbar'></div>
"
+
"
<h2 id='qunit-userAgent'></h2>
"
+
"
<ol id='qunit-tests'></ol>
"
;
}
appendBanner
();
appendTestResults
();
appendUserAgent
();
appendToolbar
();
storeFixture
();
});
QUnit
.
done
(
function
(
details
)
{
var
i
,
key
,
banner
=
id
(
"
qunit-banner
"
),
tests
=
id
(
"
qunit-tests
"
),
html
=
[
"
Tests completed in
"
,
details
.
runtime
,
"
milliseconds.<br>
"
,
"
<span class='passed'>
"
,
details
.
passed
,
"
</span> assertions of <span class='total'>
"
,
details
.
total
,
"
</span> passed, <span class='failed'>
"
,
details
.
failed
,
"
</span> failed.
"
].
join
(
""
);
if
(
banner
)
{
banner
.
className
=
details
.
failed
?
"
qunit-fail
"
:
"
qunit-pass
"
;
}
if
(
tests
)
{
id
(
"
qunit-testresult
"
).
innerHTML
=
html
;
}
if
(
config
.
altertitle
&&
defined
.
document
&&
document
.
title
)
{
// show ✖ for good, ✔ for bad suite result in title
// use escape sequences in case file gets loaded with non-utf-8-charset
document
.
title
=
[
(
details
.
failed
?
"
\
u2716
"
:
"
\
u2714
"
),
document
.
title
.
replace
(
/^
[\u
2714
\u
2716
]
/i
,
""
)
].
join
(
"
"
);
}
// clear own sessionStorage items if all tests passed
if
(
config
.
reorder
&&
defined
.
sessionStorage
&&
details
.
failed
===
0
)
{
for
(
i
=
0
;
i
<
sessionStorage
.
length
;
i
++
)
{
key
=
sessionStorage
.
key
(
i
++
);
if
(
key
.
indexOf
(
"
qunit-test-
"
)
===
0
)
{
sessionStorage
.
removeItem
(
key
);
}
}
}
// scroll back to top to show results
if
(
config
.
scrolltop
&&
window
.
scrollTo
)
{
window
.
scrollTo
(
0
,
0
);
}
});
function
getNameHtml
(
name
,
module
)
{
var
nameHtml
=
""
;
if
(
module
)
{
nameHtml
=
"
<span class='module-name'>
"
+
escapeText
(
module
)
+
"
</span>:
"
;
}
nameHtml
+=
"
<span class='test-name'>
"
+
escapeText
(
name
)
+
"
</span>
"
;
return
nameHtml
;
}
QUnit
.
testStart
(
function
(
details
)
{
var
a
,
b
,
li
,
running
,
assertList
,
name
=
getNameHtml
(
details
.
name
,
details
.
module
),
tests
=
id
(
"
qunit-tests
"
);
if
(
tests
)
{
b
=
document
.
createElement
(
"
strong
"
);
b
.
innerHTML
=
name
;
a
=
document
.
createElement
(
"
a
"
);
a
.
innerHTML
=
"
Rerun
"
;
a
.
href
=
QUnit
.
url
({
testNumber
:
details
.
testNumber
});
li
=
document
.
createElement
(
"
li
"
);
li
.
appendChild
(
b
);
li
.
appendChild
(
a
);
li
.
className
=
"
running
"
;
li
.
id
=
"
qunit-test-output
"
+
details
.
testNumber
;
assertList
=
document
.
createElement
(
"
ol
"
);
assertList
.
className
=
"
qunit-assert-list
"
;
li
.
appendChild
(
assertList
);
tests
.
appendChild
(
li
);
}
running
=
id
(
"
qunit-testresult
"
);
if
(
running
)
{
running
.
innerHTML
=
"
Running: <br>
"
+
name
;
}
});
QUnit
.
log
(
function
(
details
)
{
var
assertList
,
assertLi
,
message
,
expected
,
actual
,
testItem
=
id
(
"
qunit-test-output
"
+
details
.
testNumber
);
if
(
!
testItem
)
{
return
;
}
message
=
escapeText
(
details
.
message
)
||
(
details
.
result
?
"
okay
"
:
"
failed
"
);
message
=
"
<span class='test-message'>
"
+
message
+
"
</span>
"
;
// pushFailure doesn't provide details.expected
// when it calls, it's implicit to also not show expected and diff stuff
// Also, we need to check details.expected existence, as it can exist and be undefined
if
(
!
details
.
result
&&
hasOwn
.
call
(
details
,
"
expected
"
)
)
{
expected
=
escapeText
(
QUnit
.
dump
.
parse
(
details
.
expected
)
);
actual
=
escapeText
(
QUnit
.
dump
.
parse
(
details
.
actual
)
);
message
+=
"
<table><tr class='test-expected'><th>Expected: </th><td><pre>
"
+
expected
+
"
</pre></td></tr>
"
;
if
(
actual
!==
expected
)
{
message
+=
"
<tr class='test-actual'><th>Result: </th><td><pre>
"
+
actual
+
"
</pre></td></tr>
"
+
"
<tr class='test-diff'><th>Diff: </th><td><pre>
"
+
QUnit
.
diff
(
expected
,
actual
)
+
"
</pre></td></tr>
"
;
}
if
(
details
.
source
)
{
message
+=
"
<tr class='test-source'><th>Source: </th><td><pre>
"
+
escapeText
(
details
.
source
)
+
"
</pre></td></tr>
"
;
}
message
+=
"
</table>
"
;
// this occours when pushFailure is set and we have an extracted stack trace
}
else
if
(
!
details
.
result
&&
details
.
source
)
{
message
+=
"
<table>
"
+
"
<tr class='test-source'><th>Source: </th><td><pre>
"
+
escapeText
(
details
.
source
)
+
"
</pre></td></tr>
"
+
"
</table>
"
;
}
assertList
=
testItem
.
getElementsByTagName
(
"
ol
"
)[
0
];
assertLi
=
document
.
createElement
(
"
li
"
);
assertLi
.
className
=
details
.
result
?
"
pass
"
:
"
fail
"
;
assertLi
.
innerHTML
=
message
;
assertList
.
appendChild
(
assertLi
);
});
QUnit
.
testDone
(
function
(
details
)
{
var
testTitle
,
time
,
testItem
,
assertList
,
good
,
bad
,
testCounts
,
tests
=
id
(
"
qunit-tests
"
);
// QUnit.reset() is deprecated and will be replaced for a new
// fixture reset function on QUnit 2.0/2.1.
// It's still called here for backwards compatibility handling
QUnit
.
reset
();
if
(
!
tests
)
{
return
;
}
testItem
=
id
(
"
qunit-test-output
"
+
details
.
testNumber
);
assertList
=
testItem
.
getElementsByTagName
(
"
ol
"
)[
0
];
good
=
details
.
passed
;
bad
=
details
.
failed
;
// store result when possible
if
(
config
.
reorder
&&
defined
.
sessionStorage
)
{
if
(
bad
)
{
sessionStorage
.
setItem
(
"
qunit-test-
"
+
details
.
module
+
"
-
"
+
details
.
name
,
bad
);
}
else
{
sessionStorage
.
removeItem
(
"
qunit-test-
"
+
details
.
module
+
"
-
"
+
details
.
name
);
}
}
if
(
bad
===
0
)
{
addClass
(
assertList
,
"
qunit-collapsed
"
);
}
// testItem.firstChild is the test name
testTitle
=
testItem
.
firstChild
;
testCounts
=
bad
?
"
<b class='failed'>
"
+
bad
+
"
</b>,
"
+
"
<b class='passed'>
"
+
good
+
"
</b>,
"
:
""
;
testTitle
.
innerHTML
+=
"
<b class='counts'>(
"
+
testCounts
+
details
.
assertions
.
length
+
"
)</b>
"
;
addEvent
(
testTitle
,
"
click
"
,
function
()
{
toggleClass
(
assertList
,
"
qunit-collapsed
"
);
});
time
=
document
.
createElement
(
"
span
"
);
time
.
className
=
"
runtime
"
;
time
.
innerHTML
=
details
.
runtime
+
"
ms
"
;
testItem
.
className
=
bad
?
"
fail
"
:
"
pass
"
;
testItem
.
insertBefore
(
time
,
assertList
);
});
if
(
!
defined
.
document
||
document
.
readyState
===
"
complete
"
)
{
config
.
autorun
=
true
;
}
if
(
defined
.
document
)
{
addEvent
(
window
,
"
load
"
,
QUnit
.
load
);
}
})();
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment