Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
officejs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
officejs
Commits
741a9b4f
Commit
741a9b4f
authored
Apr 25, 2012
by
Tristan Cavelier
Committed by
Sebastien Robin
May 18, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
qunit tests
parent
3c5348b8
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
2563 additions
and
271 deletions
+2563
-271
jiotest/debug.html
jiotest/debug.html
+222
-0
jiotest/index.html
jiotest/index.html
+7
-213
jiotest/jiotests.js
jiotest/jiotests.js
+294
-0
jiotest/qunit/qunit-1.5.0.css
jiotest/qunit/qunit-1.5.0.css
+235
-0
jiotest/qunit/qunit-1.5.0.js
jiotest/qunit/qunit-1.5.0.js
+1669
-0
jiotest/unhosted/jio.js
jiotest/unhosted/jio.js
+132
-53
jiotest/unhosted/jio.storage.js
jiotest/unhosted/jio.storage.js
+4
-5
No files found.
jiotest/debug.html
0 → 100644
View file @
741a9b4f
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"utf-8"
/>
<title>
JIO
</title>
<script
type=
"text/javascript"
src=
"js/jquery/jquery.js"
></script>
<script
type=
"text/javascript"
src=
"unhosted/jio.js"
></script>
<script
type=
"text/javascript"
src=
"unhosted/base64.js"
></script>
<script
type=
"text/javascript"
src=
"unhosted/jio.storage.js"
></script>
<!-- <script type="text/javascript" src="unhosted/sjcl.js"></script> -->
</head>
<body>
<!-- <div id="test" class="test"><div1></div>
<div id="test" class="test"><div2></div> -->
<div
id=
"divbody"
>
<div
id=
"divmessage"
></div>
<div
id=
"divdebug"
style=
"color: grey"
></div>
<div
id=
"diverror"
style=
"color: red"
></div>
</div>
<script
type=
"text/javascript"
>
<!--
////////////////////////////////////////////////////////////////////////////////
// little functions
var
objectDump
=
function
(
o
)
{
console
.
log
(
JSON
.
stringify
(
o
));
};
var
toString
=
function
(
o
)
{
return
JSON
.
stringify
(
o
);
};
var
is_array
=
function
(
v
)
{
return
Object
.
prototype
.
toString
.
apply
(
v
)
===
'
[object Array]
'
;
};
////////////////////////////////////////////////////////////////////////////////
// Preparing jio
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
job_done
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divdebug
'
).
html
(
$
(
'
#divdebug
'
).
html
()
+
'
<br />
'
+
toString
(
o
));
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
job_fail
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#diverror
'
).
html
(
$
(
'
#diverror
'
).
html
()
+
'
<br />
'
+
toString
(
o
));
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_saving
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Saving ...
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_saving
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Saving ended.
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_loading
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Loading ...
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_loading
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Loading ended.
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_checkingNameAvailability
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Checking name
'
+
o
.
job
.
userName
+
'
...
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_checkingNameAvailability
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Checking name ended:
'
+
o
.
job
.
message
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_gettingList
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Getting list ...
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_gettingList
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Getting list ended:
'
+
toString
(
o
)
);
}});
$
.
jio
({
'
storage
'
:{
'
type
'
:
'
local
'
,
'
userName
'
:
'
tristan
'
},
'
applicant
'
:{
'
ID
'
:
'
www.ungproject.org
'
}});
// $.jio({'storage':{'type':'dav','userName':'tristan','password':'test',
// 'location':'https://ca-davstorage:8080','provider':'Unknown'},
// 'applicant':{'ID':'www.ungproject.org'}});
// TODO
// doc string
// localStorage.status
$
.
jio
(
'
checkNameAvailability
'
,{
'
userName
'
:
'
toto
'
});
// $.jio('isAvailable',{'userName':'tristan'});
// $.jio('saveDocument',{'fileName':'SonNom','fileContent':'SonContenu'});
// $.jio({'fileName':'SonNom','fileContent':'SonContenu','method':'saveDocument'});
// $.jio({'fileName':'SonNom2','fileContent':'SonContenu2','method':'saveDocument'});
// $.jio('loadDocument',{'fileName':'SonNom'});
// $.jio('removeDocument',{'fileName':'SonNom'});
// $.jio('getDocumentList');
////////////////////////////////////////////////////////////////////////////////
/*
// Preparing JIO
//// Setting events reactions
JIO.subscribe('job_done', function (job) {
switch(job.method) {
case 'load':
objectDump(job);
$('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.fileName + '" OK!' +
' Content : "' + job.file.content + '"');
break;
case 'userNameAvailable':
objectDump(job);
$('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.userName + '" OK!' +
' isAvailable ? "' + job.userIsAvailable + '"' +
' message : ' + job.message);
break;
default:
objectDump(job);
$('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.fileName + '" OK!');
break;
}
});
JIO.subscribe('job_fail', function (job) {
$('#diverror').html($('#diverror').html() + '<br/>' +
job.method + ': "' + job.fileName + '" FAILED! ' +
job.message);
});
JIO.subscribe('start_saving', function () {
console.log ('start_saving received');
$('#divmessage').html($('#divmessage').html() + '<br/>' +
'Saving ...');
// $('#divdebug').html($('#divdebug').html() + '<br/>' +
// 'save remainingjobs: ' + o.remaining.save);
});
JIO.subscribe('stop_saving', function () {
console.log ('stop_saving received');
$('#divmessage').html($('#divmessage').html() + '<br/>' +
'Saving ended.');
});
JIO.subscribe('start_loading', function () {
console.log ('start_loading received');
$('#divmessage').html($('#divmessage').html() + '<br/>' +
'Loading ...');
});
JIO.subscribe('stop_loading', function () {
console.log ('stop_loading received');
$('#divmessage').html($('#divmessage').html() + '<br/>' +
'Loading ended.');
});
// JIO.subscribe('start_deleting', function (e,o,r) {
// console.log ('start_deleting received');
// objectDump(o);
// $('#divmessage').html($('#divmessage').html() + '<br/>' +
// 'Deleting "' + o.fileName + '"...');
// $('#divdebug').html($('#divdebug').html() + '<br/>' +
// 'delete remainingjobs: ' + r);
// });
// JIO.subscribe('stop_deleting', function (e,o) {
// console.log ('stop_deleting received');
// objectDump(o);
// $('#divmessage').html($('#divmessage').html() + '<br/>' +
// 'Deleting ended with result: ' + o.status + ', message: ' + o.message);
// });
// JIO.subscribe('start_gettinglist', function (e,o) {
// console.log ('start_deleting received');
// objectDump(o);
// $('#divmessage').html($('#divmessage').html() + '<br/>' +
// 'Getting list...');
// });
// JIO.subscribe('stop_gettinglist', function (e,o) {
// console.log ('stop_deleting received');
// objectDump(o);
// $('#divmessage').html($('#divmessage').html() + '<br/>' +
// 'Getting list ended with result: ' + o.status + ', message: ' + o.message);
// $('#divdebug').html($('#divdebug').html() + '<br/>' +
// 'getList: ' + JSON.stringify(o.list));
// });
//// events set
//// init JIO
JIO.initialize({"type":"local","userName":"tristan"},"www.ungproject.com");
//// end init
//// Let's test!
if ( !JIO.isReady() ) alert('Not ready');
else {
// JIO.userNameAvailable("tristan");
// JIO.userNameAvailable("json");
// JIO.loadDocument("SonNom");
// JIO.saveDocument("Inside the document.","SonNom");
// JIO.saveDocument("Inside the document.","SonNom");
// JIO.saveDocument("Inside the document.","SonNom2");
// JIO.getDocumentList();
// JIO.loadDocument("SonNom");
// JIO.deleteDocument("SonNom");
// JIO.deleteDocument("SonNom");
// JIO.deleteDocument("SonNom3");
// JIO.getDocumentList();
}
////////////////////////////////////////////////////////////////////////////////
/* */
//-->
</script>
</body>
</html>
jiotest/index.html
View file @
741a9b4f
...
...
@@ -2,222 +2,16 @@
<html
lang=
"en"
>
<head>
<meta
charset=
"utf-8"
/>
<title>
JIO
</title>
<title>
JIO QUnit Test
</title>
<link
rel=
"stylesheet"
href=
"qunit/qunit-1.5.0.css"
/>
</head>
<body>
<div
id=
"qunit"
></div>
<script
type=
"text/javascript"
src=
"qunit/qunit-1.5.0.js"
></script>
<script
type=
"text/javascript"
src=
"js/jquery/jquery.js"
></script>
<script
type=
"text/javascript"
src=
"unhosted/jio.js"
></script>
<script
type=
"text/javascript"
src=
"unhosted/jquery.storage.js"
></script>
<script
type=
"text/javascript"
src=
"unhosted/base64.js"
></script>
<script
type=
"text/javascript"
src=
"unhosted/jio.storage.js"
></script>
<!-- <script type="text/javascript" src="unhosted/sjcl.js"></script> -->
</head>
<body>
<!-- <div id="test" class="test"><div1></div>
<div id="test" class="test"><div2></div> -->
<div
id=
"divbody"
>
<div
id=
"divmessage"
></div>
<div
id=
"divdebug"
style=
"color: grey"
></div>
<div
id=
"diverror"
style=
"color: red"
></div>
</div>
<script
type=
"text/javascript"
>
<!--
////////////////////////////////////////////////////////////////////////////////
// little functions
var
objectDump
=
function
(
o
)
{
console
.
log
(
JSON
.
stringify
(
o
));
};
var
toString
=
function
(
o
)
{
return
JSON
.
stringify
(
o
);
};
var
is_array
=
function
(
v
)
{
return
Object
.
prototype
.
toString
.
apply
(
v
)
===
'
[object Array]
'
;
};
////////////////////////////////////////////////////////////////////////////////
// Preparing jio
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
job_done
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divdebug
'
).
html
(
$
(
'
#divdebug
'
).
html
()
+
'
<br />
'
+
toString
(
o
));
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
job_fail
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#diverror
'
).
html
(
$
(
'
#diverror
'
).
html
()
+
'
<br />
'
+
toString
(
o
));
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_saving
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Saving ...
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_saving
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Saving ended.
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_loading
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Loading ...
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_loading
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Loading ended.
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_checkingNameAvailability
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Checking name
'
+
o
.
job
.
userName
+
'
...
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_checkingNameAvailability
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Checking name ended:
'
+
o
.
job
.
message
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_gettingList
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Getting list ...
'
);
}});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_gettingList
'
,
'
func
'
:
function
(
o
)
{
$
(
'
#divmessage
'
).
html
(
$
(
'
#divmessage
'
).
html
()
+
'
<br />
'
+
'
Getting list ended:
'
+
toString
(
o
)
);
}});
$
.
jio
({
'
storage
'
:{
'
type
'
:
'
local
'
,
'
userName
'
:
'
tristan
'
},
'
applicant
'
:{
'
ID
'
:
'
www.ungproject.org
'
}});
// $.jio({'storage':{'type':'dav','userName':'tristan','password':'test',
// 'location':'https://ca-davstorage:8080','provider':'Unknown'},
// 'applicant':{'ID':'www.ungproject.org'}});
// TODO
// doc string
// localStorage.status
// $.jio('isAvailable',{'userName':'toto'});
// $.jio('isAvailable',{'userName':'tristan'});
// $.jio('saveDocument',{'fileName':'SonNom','fileContent':'SonContenu'});
// $.jio({'fileName':'SonNom','fileContent':'SonContenu','method':'saveDocument'});
// $.jio({'fileName':'SonNom2','fileContent':'SonContenu2','method':'saveDocument'});
// $.jio('loadDocument',{'fileName':'SonNom'});
// $.jio('removeDocument',{'fileName':'SonNom'});
// $.jio('getDocumentList');
////////////////////////////////////////////////////////////////////////////////
/*
// Preparing JIO
//// Setting events reactions
JIO.subscribe('job_done', function (job) {
switch(job.method) {
case 'load':
objectDump(job);
$('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.fileName + '" OK!' +
' Content : "' + job.file.content + '"');
break;
case 'userNameAvailable':
objectDump(job);
$('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.userName + '" OK!' +
' isAvailable ? "' + job.userIsAvailable + '"' +
' message : ' + job.message);
break;
default:
objectDump(job);
$('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.fileName + '" OK!');
break;
}
});
JIO.subscribe('job_fail', function (job) {
$('#diverror').html($('#diverror').html() + '<br/>' +
job.method + ': "' + job.fileName + '" FAILED! ' +
job.message);
});
JIO.subscribe('start_saving', function () {
console.log ('start_saving received');
$('#divmessage').html($('#divmessage').html() + '<br/>' +
'Saving ...');
// $('#divdebug').html($('#divdebug').html() + '<br/>' +
// 'save remainingjobs: ' + o.remaining.save);
});
JIO.subscribe('stop_saving', function () {
console.log ('stop_saving received');
$('#divmessage').html($('#divmessage').html() + '<br/>' +
'Saving ended.');
});
JIO.subscribe('start_loading', function () {
console.log ('start_loading received');
$('#divmessage').html($('#divmessage').html() + '<br/>' +
'Loading ...');
});
JIO.subscribe('stop_loading', function () {
console.log ('stop_loading received');
$('#divmessage').html($('#divmessage').html() + '<br/>' +
'Loading ended.');
});
// JIO.subscribe('start_deleting', function (e,o,r) {
// console.log ('start_deleting received');
// objectDump(o);
// $('#divmessage').html($('#divmessage').html() + '<br/>' +
// 'Deleting "' + o.fileName + '"...');
// $('#divdebug').html($('#divdebug').html() + '<br/>' +
// 'delete remainingjobs: ' + r);
// });
// JIO.subscribe('stop_deleting', function (e,o) {
// console.log ('stop_deleting received');
// objectDump(o);
// $('#divmessage').html($('#divmessage').html() + '<br/>' +
// 'Deleting ended with result: ' + o.status + ', message: ' + o.message);
// });
// JIO.subscribe('start_gettinglist', function (e,o) {
// console.log ('start_deleting received');
// objectDump(o);
// $('#divmessage').html($('#divmessage').html() + '<br/>' +
// 'Getting list...');
// });
// JIO.subscribe('stop_gettinglist', function (e,o) {
// console.log ('stop_deleting received');
// objectDump(o);
// $('#divmessage').html($('#divmessage').html() + '<br/>' +
// 'Getting list ended with result: ' + o.status + ', message: ' + o.message);
// $('#divdebug').html($('#divdebug').html() + '<br/>' +
// 'getList: ' + JSON.stringify(o.list));
// });
//// events set
//// init JIO
JIO.initialize({"type":"local","userName":"tristan"},"www.ungproject.com");
//// end init
//// Let's test!
if ( !JIO.isReady() ) alert('Not ready');
else {
// JIO.userNameAvailable("tristan");
// JIO.userNameAvailable("json");
// JIO.loadDocument("SonNom");
// JIO.saveDocument("Inside the document.","SonNom");
// JIO.saveDocument("Inside the document.","SonNom");
// JIO.saveDocument("Inside the document.","SonNom2");
// JIO.getDocumentList();
// JIO.loadDocument("SonNom");
// JIO.deleteDocument("SonNom");
// JIO.deleteDocument("SonNom");
// JIO.deleteDocument("SonNom3");
// JIO.getDocumentList();
}
////////////////////////////////////////////////////////////////////////////////
/* */
//-->
</script>
<script
type=
"text/javascript"
src=
"jiotests.js"
></script>
</body>
</html>
jiotest/jiotests.js
0 → 100644
View file @
741a9b4f
// test ( "QUnit", function () {
// ok ( true , "QUnit works!" );
// });
var
o
=
{};
var
globalIndex
=
1
;
var
globalTestIndex
=
0
;
var
globalMax
=
10
;
var
globalID
=
setInterval
(
function
(){
if
(
globalIndex
===
globalTestIndex
)
return
;
switch
(
globalIndex
)
{
default
:
globalIndex
++
;
break
;
case
1
:
globalTestIndex
=
globalIndex
;
test
(
"
Jio simple methods
"
,
function
()
{
ok
(
$
.
jio
(
'
addStorageType
'
,{
'
type
'
:
'
qunit
'
,
'
creator
'
:
function
(){}})
,
"
storage type qunit added.
"
);
var
tmp
=
$
.
jio
(
'
isReady
'
);
ok
(
tmp
===
false
,
'
isReady ===
'
+
tmp
);
var
tmp
=
$
.
jio
({
'
storage
'
:{
'
type
'
:
'
local
'
,
'
userName
'
:
'
myName
'
},
'
applicant
'
:{
'
ID
'
:
'
myID
'
}});
ok
(
tmp
===
true
,
'
initialized ?
'
+
tmp
);
var
tmp
=
$
.
jio
(
'
isReady
'
);
ok
(
tmp
===
true
,
'
isReady ===
'
+
tmp
);
var
tmp
=
$
.
jio
(
'
getApplicant
'
);
deepEqual
(
tmp
,
{
'
ID
'
:
'
myID
'
},
'
get the good applicant.
'
);
globalIndex
++
;
});
break
;
case
2
:
globalTestIndex
=
globalIndex
;
o
.
local
=
{};
test
(
'
Jio Pub/Sub methods
'
,
function
()
{
stop
();
var
i
=
1
,
ti
=
0
,
m
=
10
;
var
id
=
setInterval
(
function
(){
switch
(
i
){
default
:
i
++
;
break
;
case
1
:
// if(i===ti)return;ti=i; // force do only one time
o
.
local
.
pubsub_test
=
false
;
$
.
jio
(
'
subscribe
'
,
{
'
event
'
:
'
pubsub_test
'
,
'
func
'
:
function
()
{
o
.
local
.
pubsub_test
=
true
;
}});
$
.
jio
(
'
publish
'
,{
'
event
'
:
'
pubsub_test
'
});
i
++
;
break
;
case
5
:
// wait a little
deepEqual
(
o
.
local
.
pubsub_test
,
true
,
'
subscribe & publish
'
);
if
(
o
.
local
.
pubsub_test
)
{
i
++
;
}
else
{
i
=
m
;
globalIndex
=
globalMax
;
}
break
;
case
6
:
o
.
local
.
pubsub_test
=
false
;
$
.
jio
(
'
unsubscribe
'
,{
'
event
'
:
'
pubsub_test
'
});
$
.
jio
(
'
publish
'
,{
'
event
'
:
'
pubsub_test
'
});
i
++
;
break
;
case
9
:
// wait a little
deepEqual
(
o
.
local
.
pubsub_test
,
false
,
'
unsubscribe
'
);
i
++
;
break
;
case
m
:
start
();
globalIndex
++
;
clearInterval
(
id
);
break
;
}
},
100
);
});
break
;
case
3
:
globalTestIndex
=
globalIndex
;
test
(
'
LocalStorage
'
,
function
()
{
stop
();
var
i
=
1
,
ti
=
0
,
m
=
31
;
var
id
=
setInterval
(
function
(){
switch
(
i
){
default
:
i
++
;
break
;
case
1
:
o
.
local
.
start_check
=
false
;
o
.
local
.
stop_check
=
false
;
o
.
local
.
ret_check
=
false
;
o
.
start_check_func
=
function
()
{
o
.
local
.
start_check
=
true
;
};
o
.
stop_check_func
=
function
(
e
)
{
o
.
local
.
ret_check
=
e
.
job
.
isAvailable
;
o
.
local
.
stop_check
=
true
;
};
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_checkingNameAvailability
'
,
'
func
'
:
function
(
e
)
{
o
.
start_check_func
(
e
);
}})
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_checkingNameAvailability
'
,
'
func
'
:
function
(
e
)
{
o
.
stop_check_func
(
e
);
}})
$
.
jio
(
'
checkNameAvailability
'
,{
'
userName
'
:
'
myName
'
});
i
++
;
break
;
case
5
:
// wait a little
deepEqual
(
[
o
.
local
.
start_check
,
o
.
local
.
stop_check
,
o
.
local
.
ret_check
],
[
true
,
true
,
true
],
'
checking name availability
'
);
i
++
;
break
;
case
6
:
o
.
local
.
start_save
=
false
;
o
.
local
.
stop_save
=
false
;
o
.
local
.
ret_save
=
false
;
o
.
start_save_func
=
function
()
{
o
.
local
.
start_save
=
true
;
};
o
.
job_done_func
=
function
(
e
)
{
o
.
local
.
ret_save
=
e
.
job
.
isSaved
;
};
o
.
stop_save_func
=
function
()
{
o
.
local
.
stop_save
=
true
;
};
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_saving
'
,
'
func
'
:
function
(
e
)
{
o
.
start_save_func
(
e
);
}})
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
job_done
'
,
'
func
'
:
function
(
e
){
o
.
job_done_func
(
e
);}
});
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_saving
'
,
'
func
'
:
function
(
e
)
{
o
.
stop_save_func
(
e
);
}})
$
.
jio
(
'
saveDocument
'
,{
'
fileName
'
:
'
file
'
,
'
fileContent
'
:
'
content
'
});
i
++
;
break
;
case
10
:
// wait a little
deepEqual
(
[
o
.
local
.
start_save
,
o
.
local
.
stop_save
,
o
.
local
.
ret_save
],
[
true
,
true
,
true
],
'
saving
'
);
i
++
;
break
;
case
11
:
o
.
local
.
start_check
=
false
;
o
.
local
.
stop_check
=
false
;
o
.
local
.
ret_check
=
true
;
// already subscribed
$
.
jio
(
'
checkNameAvailability
'
,{
'
userName
'
:
'
myName
'
});
i
++
;
break
;
case
15
:
// wait a little
deepEqual
(
[
o
.
local
.
start_check
,
o
.
local
.
stop_check
,
o
.
local
.
ret_check
],
[
true
,
true
,
false
],
'
checking name availability
'
);
i
++
;
break
;
case
16
:
o
.
local
.
start_load
=
false
;
o
.
local
.
stop_load
=
false
;
o
.
local
.
ret_load
=
null
;
o
.
start_load_func
=
function
()
{
o
.
local
.
start_load
=
true
;
};
o
.
job_done_func
=
function
(
e
)
{
o
.
local
.
ret_load
=
e
.
job
.
fileContent
;
};
o
.
stop_load_func
=
function
()
{
o
.
local
.
stop_load
=
true
;
};
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_loading
'
,
'
func
'
:
function
(
e
)
{
o
.
start_load_func
(
e
);
}})
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_loading
'
,
'
func
'
:
function
(
e
)
{
o
.
stop_load_func
(
e
);
}})
$
.
jio
(
'
loadDocument
'
,{
'
fileName
'
:
'
file
'
});
i
++
;
break
;
case
20
:
// wait a little
deepEqual
(
[
o
.
local
.
start_load
,
o
.
local
.
stop_load
,
o
.
local
.
ret_load
],
[
true
,
true
,
'
content
'
],
'
loading
'
);
i
++
;
break
;
case
21
:
o
.
local
.
start_getlist
=
false
;
o
.
local
.
stop_getlist
=
false
;
o
.
local
.
ret_getlist_at_job
=
[];
o
.
local
.
ret_getlist_at_stop
=
[];
o
.
start_getlist_func
=
function
()
{
o
.
local
.
start_getlist
=
true
;
};
o
.
job_done_func
=
function
(
e
)
{
o
.
local
.
ret_getlist_at_job
=
e
.
job
.
list
;
};
o
.
stop_getlist_func
=
function
(
e
)
{
o
.
local
.
ret_getlist_at_stop
=
e
.
job
.
list
;
o
.
local
.
stop_getlist
=
true
;
};
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_gettingList
'
,
'
func
'
:
function
(
e
)
{
o
.
start_getlist_func
(
e
);
}})
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_gettingList
'
,
'
func
'
:
function
(
e
)
{
o
.
stop_getlist_func
(
e
);
}})
$
.
jio
(
'
getDocumentList
'
);
i
++
;
break
;
case
25
:
// wait a little
var
expected
=
JSON
.
parse
(
localStorage
[
'
jio/local/myName/myID/file
'
]);
delete
expected
.
fileContent
;
expected
=
[
expected
];
deepEqual
(
[
o
.
local
.
start_getlist
,
o
.
local
.
stop_getlist
,
o
.
local
.
ret_getlist_at_job
,
o
.
local
.
ret_getlist_at_stop
],
[
true
,
true
,
expected
,
expected
],
'
get list
'
);
i
++
;
break
;
case
26
:
o
.
local
.
start_remove
=
false
;
o
.
local
.
stop_remove
=
false
;
o
.
local
.
ret_remove
=
false
;
o
.
start_remove_func
=
function
()
{
o
.
local
.
start_remove
=
true
;
};
o
.
job_done_func
=
function
(
e
)
{
o
.
local
.
ret_remove
=
e
.
job
.
isRemoved
;
};
o
.
stop_remove_func
=
function
()
{
o
.
local
.
stop_remove
=
true
;
};
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
start_removing
'
,
'
func
'
:
function
(
e
)
{
o
.
start_remove_func
(
e
);
}})
$
.
jio
(
'
subscribe
'
,{
'
event
'
:
'
stop_removing
'
,
'
func
'
:
function
(
e
)
{
o
.
stop_remove_func
(
e
);
}})
$
.
jio
(
'
removeDocument
'
,{
'
fileName
'
:
'
file
'
});
i
++
;
break
;
case
30
:
// wait a little
deepEqual
(
[
o
.
local
.
start_remove
,
o
.
local
.
stop_remove
,
o
.
local
.
ret_remove
],
[
true
,
true
,
true
],
'
remove
'
);
i
++
;
break
;
case
m
:
start
();
globalIndex
++
;
clearInterval
(
id
);
break
;
}
},
100
);
});
break
;
case
globalMax
:
clearInterval
(
globalID
);
break
;
}
},
100
);
jiotest/qunit/qunit-1.5.0.css
0 → 100644
View file @
741a9b4f
/**
* QUnit v1.5.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
*/
/** Font Family and Sizes */
#qunit-tests
,
#qunit-header
,
#qunit-banner
,
#qunit-testrunner-toolbar
,
#qunit-userAgent
,
#qunit-testresult
{
font-family
:
"Helvetica Neue Light"
,
"HelveticaNeue-Light"
,
"Helvetica Neue"
,
Calibri
,
Helvetica
,
Arial
,
sans-serif
;
}
#qunit-testrunner-toolbar
,
#qunit-userAgent
,
#qunit-testresult
,
#qunit-tests
li
{
font-size
:
small
;
}
#qunit-tests
{
font-size
:
smaller
;
}
/** Resets */
#qunit-tests
,
#qunit-tests
ol
,
#qunit-header
,
#qunit-banner
,
#qunit-userAgent
,
#qunit-testresult
{
margin
:
0
;
padding
:
0
;
}
/** Header */
#qunit-header
{
padding
:
0.5em
0
0.5em
1em
;
color
:
#8699a4
;
background-color
:
#0d3349
;
font-size
:
1.5em
;
line-height
:
1em
;
font-weight
:
normal
;
border-radius
:
15px
15px
0
0
;
-moz-border-radius
:
15px
15px
0
0
;
-webkit-border-top-right-radius
:
15px
;
-webkit-border-top-left-radius
:
15px
;
}
#qunit-header
a
{
text-decoration
:
none
;
color
:
#c2ccd1
;
}
#qunit-header
a
:hover
,
#qunit-header
a
:focus
{
color
:
#fff
;
}
#qunit-header
label
{
display
:
inline-block
;
}
#qunit-banner
{
height
:
5px
;
}
#qunit-testrunner-toolbar
{
padding
:
0.5em
0
0.5em
2em
;
color
:
#5E740B
;
background-color
:
#eee
;
}
#qunit-userAgent
{
padding
:
0.5em
0
0.5em
2.5em
;
background-color
:
#2b81af
;
color
:
#fff
;
text-shadow
:
rgba
(
0
,
0
,
0
,
0.5
)
2px
2px
1px
;
}
/** Tests: Pass/Fail */
#qunit-tests
{
list-style-position
:
inside
;
}
#qunit-tests
li
{
padding
:
0.4em
0.5em
0.4em
2.5em
;
border-bottom
:
1px
solid
#fff
;
list-style-position
:
inside
;
}
#qunit-tests
.hidepass
li
.pass
,
#qunit-tests
.hidepass
li
.running
{
display
:
none
;
}
#qunit-tests
li
strong
{
cursor
:
pointer
;
}
#qunit-tests
li
a
{
padding
:
0.5em
;
color
:
#c2ccd1
;
text-decoration
:
none
;
}
#qunit-tests
li
a
:hover
,
#qunit-tests
li
a
:focus
{
color
:
#000
;
}
#qunit-tests
ol
{
margin-top
:
0.5em
;
padding
:
0.5em
;
background-color
:
#fff
;
border-radius
:
15px
;
-moz-border-radius
:
15px
;
-webkit-border-radius
:
15px
;
box-shadow
:
inset
0px
2px
13px
#999
;
-moz-box-shadow
:
inset
0px
2px
13px
#999
;
-webkit-box-shadow
:
inset
0px
2px
13px
#999
;
}
#qunit-tests
table
{
border-collapse
:
collapse
;
margin-top
:
.2em
;
}
#qunit-tests
th
{
text-align
:
right
;
vertical-align
:
top
;
padding
:
0
.5em
0
0
;
}
#qunit-tests
td
{
vertical-align
:
top
;
}
#qunit-tests
pre
{
margin
:
0
;
white-space
:
pre-wrap
;
word-wrap
:
break-word
;
}
#qunit-tests
del
{
background-color
:
#e0f2be
;
color
:
#374e0c
;
text-decoration
:
none
;
}
#qunit-tests
ins
{
background-color
:
#ffcaca
;
color
:
#500
;
text-decoration
:
none
;
}
/*** Test Counts */
#qunit-tests
b
.counts
{
color
:
black
;
}
#qunit-tests
b
.passed
{
color
:
#5E740B
;
}
#qunit-tests
b
.failed
{
color
:
#710909
;
}
#qunit-tests
li
li
{
margin
:
0.5em
;
padding
:
0.4em
0.5em
0.4em
0.5em
;
background-color
:
#fff
;
border-bottom
:
none
;
list-style-position
:
inside
;
}
/*** Passing Styles */
#qunit-tests
li
li
.pass
{
color
:
#5E740B
;
background-color
:
#fff
;
border-left
:
26px
solid
#C6E746
;
}
#qunit-tests
.pass
{
color
:
#528CE0
;
background-color
:
#D2E0E6
;
}
#qunit-tests
.pass
.test-name
{
color
:
#366097
;
}
#qunit-tests
.pass
.test-actual
,
#qunit-tests
.pass
.test-expected
{
color
:
#999999
;
}
#qunit-banner
.qunit-pass
{
background-color
:
#C6E746
;
}
/*** Failing Styles */
#qunit-tests
li
li
.fail
{
color
:
#710909
;
background-color
:
#fff
;
border-left
:
26px
solid
#EE5757
;
white-space
:
pre
;
}
#qunit-tests
>
li
:last-child
{
border-radius
:
0
0
15px
15px
;
-moz-border-radius
:
0
0
15px
15px
;
-webkit-border-bottom-right-radius
:
15px
;
-webkit-border-bottom-left-radius
:
15px
;
}
#qunit-tests
.fail
{
color
:
#000000
;
background-color
:
#EE5757
;
}
#qunit-tests
.fail
.test-name
,
#qunit-tests
.fail
.module-name
{
color
:
#000000
;
}
#qunit-tests
.fail
.test-actual
{
color
:
#EE5757
;
}
#qunit-tests
.fail
.test-expected
{
color
:
green
;
}
#qunit-banner
.qunit-fail
{
background-color
:
#EE5757
;
}
/** Result */
#qunit-testresult
{
padding
:
0.5em
0.5em
0.5em
2.5em
;
color
:
#2b81af
;
background-color
:
#D2E0E6
;
border-bottom
:
1px
solid
white
;
}
#qunit-testresult
.module-name
{
font-weight
:
bold
;
}
/** Fixture */
#qunit-fixture
{
position
:
absolute
;
top
:
-10000px
;
left
:
-10000px
;
width
:
1000px
;
height
:
1000px
;
}
jiotest/qunit/qunit-1.5.0.js
0 → 100644
View file @
741a9b4f
/**
* QUnit v1.5.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
*/
(
function
(
window
)
{
var
defined
=
{
setTimeout
:
typeof
window
.
setTimeout
!==
"
undefined
"
,
sessionStorage
:
(
function
()
{
var
x
=
"
qunit-test-string
"
;
try
{
sessionStorage
.
setItem
(
x
,
x
);
sessionStorage
.
removeItem
(
x
);
return
true
;
}
catch
(
e
)
{
return
false
;
}
}())
};
var
testId
=
0
,
toString
=
Object
.
prototype
.
toString
,
hasOwn
=
Object
.
prototype
.
hasOwnProperty
;
var
Test
=
function
(
name
,
testName
,
expected
,
async
,
callback
)
{
this
.
name
=
name
;
this
.
testName
=
testName
;
this
.
expected
=
expected
;
this
.
async
=
async
;
this
.
callback
=
callback
;
this
.
assertions
=
[];
};
Test
.
prototype
=
{
init
:
function
()
{
var
tests
=
id
(
"
qunit-tests
"
);
if
(
tests
)
{
var
b
=
document
.
createElement
(
"
strong
"
);
b
.
innerHTML
=
"
Running
"
+
this
.
name
;
var
li
=
document
.
createElement
(
"
li
"
);
li
.
appendChild
(
b
);
li
.
className
=
"
running
"
;
li
.
id
=
this
.
id
=
"
test-output
"
+
testId
++
;
tests
.
appendChild
(
li
);
}
},
setup
:
function
()
{
if
(
this
.
module
!=
config
.
previousModule
)
{
if
(
config
.
previousModule
)
{
runLoggingCallbacks
(
'
moduleDone
'
,
QUnit
,
{
name
:
config
.
previousModule
,
failed
:
config
.
moduleStats
.
bad
,
passed
:
config
.
moduleStats
.
all
-
config
.
moduleStats
.
bad
,
total
:
config
.
moduleStats
.
all
}
);
}
config
.
previousModule
=
this
.
module
;
config
.
moduleStats
=
{
all
:
0
,
bad
:
0
};
runLoggingCallbacks
(
'
moduleStart
'
,
QUnit
,
{
name
:
this
.
module
}
);
}
else
if
(
config
.
autorun
)
{
runLoggingCallbacks
(
'
moduleStart
'
,
QUnit
,
{
name
:
this
.
module
}
);
}
config
.
current
=
this
;
this
.
testEnvironment
=
extend
({
setup
:
function
()
{},
teardown
:
function
()
{}
},
this
.
moduleTestEnvironment
);
runLoggingCallbacks
(
'
testStart
'
,
QUnit
,
{
name
:
this
.
testName
,
module
:
this
.
module
});
// allow utility functions to access the current test environment
// TODO why??
QUnit
.
current_testEnvironment
=
this
.
testEnvironment
;
if
(
!
config
.
pollution
)
{
saveGlobal
();
}
if
(
config
.
notrycatch
)
{
this
.
testEnvironment
.
setup
.
call
(
this
.
testEnvironment
);
return
;
}
try
{
this
.
testEnvironment
.
setup
.
call
(
this
.
testEnvironment
);
}
catch
(
e
)
{
QUnit
.
pushFailure
(
"
Setup failed on
"
+
this
.
testName
+
"
:
"
+
e
.
message
,
extractStacktrace
(
e
,
1
)
);
}
},
run
:
function
()
{
config
.
current
=
this
;
var
running
=
id
(
"
qunit-testresult
"
);
if
(
running
)
{
running
.
innerHTML
=
"
Running: <br/>
"
+
this
.
name
;
}
if
(
this
.
async
)
{
QUnit
.
stop
();
}
if
(
config
.
notrycatch
)
{
this
.
callback
.
call
(
this
.
testEnvironment
);
return
;
}
try
{
this
.
callback
.
call
(
this
.
testEnvironment
);
}
catch
(
e
)
{
QUnit
.
pushFailure
(
"
Died on test #
"
+
(
this
.
assertions
.
length
+
1
)
+
"
:
"
+
e
.
message
,
extractStacktrace
(
e
,
1
)
);
// else next test will carry the responsibility
saveGlobal
();
// Restart the tests if they're blocking
if
(
config
.
blocking
)
{
QUnit
.
start
();
}
}
},
teardown
:
function
()
{
config
.
current
=
this
;
if
(
config
.
notrycatch
)
{
this
.
testEnvironment
.
teardown
.
call
(
this
.
testEnvironment
);
return
;
}
else
{
try
{
this
.
testEnvironment
.
teardown
.
call
(
this
.
testEnvironment
);
}
catch
(
e
)
{
QUnit
.
pushFailure
(
"
Teardown failed on
"
+
this
.
testName
+
"
:
"
+
e
.
message
,
extractStacktrace
(
e
,
1
)
);
}
}
checkPollution
();
},
finish
:
function
()
{
config
.
current
=
this
;
if
(
this
.
expected
!=
null
&&
this
.
expected
!=
this
.
assertions
.
length
)
{
QUnit
.
pushFailure
(
"
Expected
"
+
this
.
expected
+
"
assertions, but
"
+
this
.
assertions
.
length
+
"
were run
"
);
}
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.
"
);
}
var
good
=
0
,
bad
=
0
,
li
,
i
,
tests
=
id
(
"
qunit-tests
"
);
config
.
stats
.
all
+=
this
.
assertions
.
length
;
config
.
moduleStats
.
all
+=
this
.
assertions
.
length
;
if
(
tests
)
{
var
ol
=
document
.
createElement
(
"
ol
"
);
for
(
i
=
0
;
i
<
this
.
assertions
.
length
;
i
++
)
{
var
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
)
{
ol
.
style
.
display
=
"
none
"
;
}
var
b
=
document
.
createElement
(
"
strong
"
);
b
.
innerHTML
=
this
.
name
+
"
<b class='counts'>(<b class='failed'>
"
+
bad
+
"
</b>, <b class='passed'>
"
+
good
+
"
</b>,
"
+
this
.
assertions
.
length
+
"
)</b>
"
;
var
a
=
document
.
createElement
(
"
a
"
);
a
.
innerHTML
=
"
Rerun
"
;
a
.
href
=
QUnit
.
url
({
filter
:
getText
([
b
]).
replace
(
/
\([^
)
]
+
\)
$/
,
""
).
replace
(
/
(
^
\s
*|
\s
*$
)
/g
,
""
)
});
addEvent
(
b
,
"
click
"
,
function
()
{
var
next
=
b
.
nextSibling
.
nextSibling
,
display
=
next
.
style
.
display
;
next
.
style
.
display
=
display
===
"
none
"
?
"
block
"
:
"
none
"
;
});
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
({
filter
:
getText
([
target
]).
replace
(
/
\([^
)
]
+
\)
$/
,
""
).
replace
(
/
(
^
\s
*|
\s
*$
)
/g
,
""
)
});
}
});
li
=
id
(
this
.
id
);
li
.
className
=
bad
?
"
fail
"
:
"
pass
"
;
li
.
removeChild
(
li
.
firstChild
);
li
.
appendChild
(
b
);
li
.
appendChild
(
a
);
li
.
appendChild
(
ol
);
}
else
{
for
(
i
=
0
;
i
<
this
.
assertions
.
length
;
i
++
)
{
if
(
!
this
.
assertions
[
i
].
result
)
{
bad
++
;
config
.
stats
.
bad
++
;
config
.
moduleStats
.
bad
++
;
}
}
}
QUnit
.
reset
();
runLoggingCallbacks
(
'
testDone
'
,
QUnit
,
{
name
:
this
.
testName
,
module
:
this
.
module
,
failed
:
bad
,
passed
:
this
.
assertions
.
length
-
bad
,
total
:
this
.
assertions
.
length
}
);
},
queue
:
function
()
{
var
test
=
this
;
synchronize
(
function
()
{
test
.
init
();
});
function
run
()
{
// each of these can by async
synchronize
(
function
()
{
test
.
setup
();
});
synchronize
(
function
()
{
test
.
run
();
});
synchronize
(
function
()
{
test
.
teardown
();
});
synchronize
(
function
()
{
test
.
finish
();
});
}
// defer when previous test run passed, if storage is available
var
bad
=
QUnit
.
config
.
reorder
&&
defined
.
sessionStorage
&&
+
sessionStorage
.
getItem
(
"
qunit-test-
"
+
this
.
module
+
"
-
"
+
this
.
testName
);
if
(
bad
)
{
run
();
}
else
{
synchronize
(
run
,
true
);
}
}
};
var
QUnit
=
{
// call on start of module test to prepend name to all tests
module
:
function
(
name
,
testEnvironment
)
{
config
.
currentModule
=
name
;
config
.
currentModuleTestEnviroment
=
testEnvironment
;
},
asyncTest
:
function
(
testName
,
expected
,
callback
)
{
if
(
arguments
.
length
===
2
)
{
callback
=
expected
;
expected
=
null
;
}
QUnit
.
test
(
testName
,
expected
,
callback
,
true
);
},
test
:
function
(
testName
,
expected
,
callback
,
async
)
{
var
name
=
'
<span class="test-name">
'
+
escapeInnerText
(
testName
)
+
'
</span>
'
;
if
(
arguments
.
length
===
2
)
{
callback
=
expected
;
expected
=
null
;
}
if
(
config
.
currentModule
)
{
name
=
'
<span class="module-name">
'
+
config
.
currentModule
+
"
</span>:
"
+
name
;
}
if
(
!
validTest
(
config
.
currentModule
+
"
:
"
+
testName
)
)
{
return
;
}
var
test
=
new
Test
(
name
,
testName
,
expected
,
async
,
callback
);
test
.
module
=
config
.
currentModule
;
test
.
moduleTestEnvironment
=
config
.
currentModuleTestEnviroment
;
test
.
queue
();
},
// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
expect
:
function
(
asserts
)
{
config
.
current
.
expected
=
asserts
;
},
// Asserts true.
// @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
;
var
details
=
{
result
:
result
,
message
:
msg
};
msg
=
escapeInnerText
(
msg
||
(
result
?
"
okay
"
:
"
failed
"
));
if
(
!
result
)
{
var
source
=
sourceFromStacktrace
(
2
);
if
(
source
)
{
details
.
source
=
source
;
msg
+=
'
<table><tr class="test-source"><th>Source: </th><td><pre>
'
+
escapeInnerText
(
source
)
+
'
</pre></td></tr></table>
'
;
}
}
runLoggingCallbacks
(
'
log
'
,
QUnit
,
details
);
config
.
current
.
assertions
.
push
({
result
:
result
,
message
:
msg
});
},
// Checks that the first two arguments are equal, with an optional message. Prints out both actual and expected values.
// @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
equal
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
expected
==
actual
,
actual
,
expected
,
message
);
},
notEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
expected
!=
actual
,
actual
,
expected
,
message
);
},
deepEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
},
notDeepEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
!
QUnit
.
equiv
(
actual
,
expected
),
actual
,
expected
,
message
);
},
strictEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
expected
===
actual
,
actual
,
expected
,
message
);
},
notStrictEqual
:
function
(
actual
,
expected
,
message
)
{
QUnit
.
push
(
expected
!==
actual
,
actual
,
expected
,
message
);
},
raises
:
function
(
block
,
expected
,
message
)
{
var
actual
,
ok
=
false
;
if
(
typeof
expected
===
'
string
'
)
{
message
=
expected
;
expected
=
null
;
}
try
{
block
.
call
(
config
.
current
.
testEnvironment
);
}
catch
(
e
)
{
actual
=
e
;
}
if
(
actual
)
{
// we don't want to validate thrown error
if
(
!
expected
)
{
ok
=
true
;
// expected is a regexp
}
else
if
(
QUnit
.
objectType
(
expected
)
===
"
regexp
"
)
{
ok
=
expected
.
test
(
actual
);
// expected is a constructor
}
else
if
(
actual
instanceof
expected
)
{
ok
=
true
;
// expected is a validation function which returns true is validation passed
}
else
if
(
expected
.
call
({},
actual
)
===
true
)
{
ok
=
true
;
}
}
QUnit
.
ok
(
ok
,
message
);
},
start
:
function
(
count
)
{
config
.
semaphore
-=
count
||
1
;
if
(
config
.
semaphore
>
0
)
{
// don't start until equal number of stop-calls
return
;
}
if
(
config
.
semaphore
<
0
)
{
// ignore if start is called more often then stop
config
.
semaphore
=
0
;
}
// A slight delay, to avoid any current callbacks
if
(
defined
.
setTimeout
)
{
window
.
setTimeout
(
function
()
{
if
(
config
.
semaphore
>
0
)
{
return
;
}
if
(
config
.
timeout
)
{
clearTimeout
(
config
.
timeout
);
}
config
.
blocking
=
false
;
process
(
true
);
},
13
);
}
else
{
config
.
blocking
=
false
;
process
(
true
);
}
},
stop
:
function
(
count
)
{
config
.
semaphore
+=
count
||
1
;
config
.
blocking
=
true
;
if
(
config
.
testTimeout
&&
defined
.
setTimeout
)
{
clearTimeout
(
config
.
timeout
);
config
.
timeout
=
window
.
setTimeout
(
function
()
{
QUnit
.
ok
(
false
,
"
Test timed out
"
);
config
.
semaphore
=
1
;
QUnit
.
start
();
},
config
.
testTimeout
);
}
}
};
//We want access to the constructor's prototype
(
function
()
{
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
;
}());
// deprecated; still export them to window to provide clear error messages
// next step: remove entirely
QUnit
.
equals
=
function
()
{
QUnit
.
push
(
false
,
false
,
false
,
"
QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead
"
);
};
QUnit
.
same
=
function
()
{
QUnit
.
push
(
false
,
false
,
false
,
"
QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead
"
);
};
// Maintain internal state
var
config
=
{
// The queue of tests to run
queue
:
[],
// block until document ready
blocking
:
true
,
// when enabled, show only failing tests
// gets persisted through sessionStorage and can be changed in UI via checkbox
hidepassed
:
false
,
// by default, run previously failed tests first
// very useful in combination with "Hide passed tests" checked
reorder
:
true
,
// by default, modify document.title when suite is done
altertitle
:
true
,
urlConfig
:
[
'
noglobals
'
,
'
notrycatch
'
],
//logging callback queues
begin
:
[],
done
:
[],
log
:
[],
testStart
:
[],
testDone
:
[],
moduleStart
:
[],
moduleDone
:
[]
};
// Load paramaters
(
function
()
{
var
location
=
window
.
location
||
{
search
:
""
,
protocol
:
"
file:
"
},
params
=
location
.
search
.
slice
(
1
).
split
(
"
&
"
),
length
=
params
.
length
,
urlParams
=
{},
current
;
if
(
params
[
0
]
)
{
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
current
=
params
[
i
].
split
(
"
=
"
);
current
[
0
]
=
decodeURIComponent
(
current
[
0
]
);
// allow just a key to turn on a flag, e.g., test.html?noglobals
current
[
1
]
=
current
[
1
]
?
decodeURIComponent
(
current
[
1
]
)
:
true
;
urlParams
[
current
[
0
]
]
=
current
[
1
];
}
}
QUnit
.
urlParams
=
urlParams
;
config
.
filter
=
urlParams
.
filter
;
// Figure out if we're running the tests from a server or not
QUnit
.
isLocal
=
location
.
protocol
===
'
file:
'
;
}());
// Expose the API as global variables, unless an 'exports'
// object exists, in that case we assume we're in CommonJS - export everything at the end
if
(
typeof
exports
===
"
undefined
"
||
typeof
require
===
"
undefined
"
)
{
extend
(
window
,
QUnit
);
window
.
QUnit
=
QUnit
;
}
// define these after exposing globals to keep them in these QUnit namespace only
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
:
0
});
var
qunit
=
id
(
"
qunit
"
);
if
(
qunit
)
{
qunit
.
innerHTML
=
'
<h1 id="qunit-header">
'
+
escapeInnerText
(
document
.
title
)
+
'
</h1>
'
+
'
<h2 id="qunit-banner"></h2>
'
+
'
<div id="qunit-testrunner-toolbar"></div>
'
+
'
<h2 id="qunit-userAgent"></h2>
'
+
'
<ol id="qunit-tests"></ol>
'
;
}
var
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.
// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
reset
:
function
()
{
if
(
window
.
jQuery
)
{
jQuery
(
"
#qunit-fixture
"
).
html
(
config
.
fixture
);
}
else
{
var
main
=
id
(
'
qunit-fixture
'
);
if
(
main
)
{
main
.
innerHTML
=
config
.
fixture
;
}
}
},
// Trigger an event on an element.
// @example triggerEvent( document.body, "click" );
triggerEvent
:
function
(
elem
,
type
,
event
)
{
if
(
document
.
createEvent
)
{
event
=
document
.
createEvent
(
"
MouseEvents
"
);
event
.
initMouseEvent
(
type
,
true
,
true
,
elem
.
ownerDocument
.
defaultView
,
0
,
0
,
0
,
0
,
0
,
false
,
false
,
false
,
false
,
0
,
null
);
elem
.
dispatchEvent
(
event
);
}
else
if
(
elem
.
fireEvent
)
{
elem
.
fireEvent
(
"
on
"
+
type
);
}
},
// Safe object type checking
is
:
function
(
type
,
obj
)
{
return
QUnit
.
objectType
(
obj
)
==
type
;
},
objectType
:
function
(
obj
)
{
if
(
typeof
obj
===
"
undefined
"
)
{
return
"
undefined
"
;
// consider: typeof null === object
}
if
(
obj
===
null
)
{
return
"
null
"
;
}
var
type
=
toString
.
call
(
obj
).
match
(
/^
\[
object
\s(
.*
)\]
$/
)[
1
]
||
''
;
switch
(
type
)
{
case
'
Number
'
:
if
(
isNaN
(
obj
))
{
return
"
nan
"
;
}
return
"
number
"
;
case
'
String
'
:
case
'
Boolean
'
:
case
'
Array
'
:
case
'
Date
'
:
case
'
RegExp
'
:
case
'
Function
'
:
return
type
.
toLowerCase
();
}
if
(
typeof
obj
===
"
object
"
)
{
return
"
object
"
;
}
return
undefined
;
},
push
:
function
(
result
,
actual
,
expected
,
message
)
{
if
(
!
config
.
current
)
{
throw
new
Error
(
"
assertion outside test context, was
"
+
sourceFromStacktrace
());
}
var
details
=
{
result
:
result
,
message
:
message
,
actual
:
actual
,
expected
:
expected
};
message
=
escapeInnerText
(
message
)
||
(
result
?
"
okay
"
:
"
failed
"
);
message
=
'
<span class="test-message">
'
+
message
+
"
</span>
"
;
var
output
=
message
;
if
(
!
result
)
{
expected
=
escapeInnerText
(
QUnit
.
jsDump
.
parse
(
expected
));
actual
=
escapeInnerText
(
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>
'
;
}
var
source
=
sourceFromStacktrace
();
if
(
source
)
{
details
.
source
=
source
;
output
+=
'
<tr class="test-source"><th>Source: </th><td><pre>
'
+
escapeInnerText
(
source
)
+
'
</pre></td></tr>
'
;
}
output
+=
"
</table>
"
;
}
runLoggingCallbacks
(
'
log
'
,
QUnit
,
details
);
config
.
current
.
assertions
.
push
({
result
:
!!
result
,
message
:
output
});
},
pushFailure
:
function
(
message
,
source
)
{
var
details
=
{
result
:
false
,
message
:
message
};
var
output
=
escapeInnerText
(
message
);
if
(
source
)
{
details
.
source
=
source
;
output
+=
'
<table><tr class="test-source"><th>Source: </th><td><pre>
'
+
escapeInnerText
(
source
)
+
'
</pre></td></tr></table>
'
;
}
runLoggingCallbacks
(
'
log
'
,
QUnit
,
details
);
config
.
current
.
assertions
.
push
({
result
:
false
,
message
:
output
});
},
url
:
function
(
params
)
{
params
=
extend
(
extend
(
{},
QUnit
.
urlParams
),
params
);
var
querystring
=
"
?
"
,
key
;
for
(
key
in
params
)
{
if
(
!
hasOwn
.
call
(
params
,
key
)
)
{
continue
;
}
querystring
+=
encodeURIComponent
(
key
)
+
"
=
"
+
encodeURIComponent
(
params
[
key
]
)
+
"
&
"
;
}
return
window
.
location
.
pathname
+
querystring
.
slice
(
0
,
-
1
);
},
extend
:
extend
,
id
:
id
,
addEvent
:
addEvent
});
//QUnit.constructor is set to the empty F() above so that we can add to it's prototype later
//Doing this allows us to tell if the following methods have been overwritten on the actual
//QUnit object, which is a deprecated way of using the callbacks.
extend
(
QUnit
.
constructor
.
prototype
,
{
// Logging callbacks; all receive a single argument with the listed properties
// run test/logs.html for any related changes
begin
:
registerLoggingCallback
(
'
begin
'
),
// done: { failed, passed, total, runtime }
done
:
registerLoggingCallback
(
'
done
'
),
// log: { result, actual, expected, message }
log
:
registerLoggingCallback
(
'
log
'
),
// testStart: { name }
testStart
:
registerLoggingCallback
(
'
testStart
'
),
// testDone: { name, failed, passed, total }
testDone
:
registerLoggingCallback
(
'
testDone
'
),
// moduleStart: { name }
moduleStart
:
registerLoggingCallback
(
'
moduleStart
'
),
// moduleDone: { name, failed, passed, total }
moduleDone
:
registerLoggingCallback
(
'
moduleDone
'
)
});
if
(
typeof
document
===
"
undefined
"
||
document
.
readyState
===
"
complete
"
)
{
config
.
autorun
=
true
;
}
QUnit
.
load
=
function
()
{
runLoggingCallbacks
(
'
begin
'
,
QUnit
,
{}
);
// Initialize the config, saving the execution queue
var
oldconfig
=
extend
({},
config
);
QUnit
.
init
();
extend
(
config
,
oldconfig
);
config
.
blocking
=
false
;
var
urlConfigHtml
=
''
,
len
=
config
.
urlConfig
.
length
;
for
(
var
i
=
0
,
val
;
i
<
len
;
i
++
)
{
val
=
config
.
urlConfig
[
i
];
config
[
val
]
=
QUnit
.
urlParams
[
val
];
urlConfigHtml
+=
'
<label><input name="
'
+
val
+
'
" type="checkbox"
'
+
(
config
[
val
]
?
'
checked="checked"
'
:
''
)
+
'
>
'
+
val
+
'
</label>
'
;
}
var
userAgent
=
id
(
"
qunit-userAgent
"
);
if
(
userAgent
)
{
userAgent
.
innerHTML
=
navigator
.
userAgent
;
}
var
banner
=
id
(
"
qunit-header
"
);
if
(
banner
)
{
banner
.
innerHTML
=
'
<a href="
'
+
QUnit
.
url
({
filter
:
undefined
})
+
'
">
'
+
banner
.
innerHTML
+
'
</a>
'
+
urlConfigHtml
;
addEvent
(
banner
,
"
change
"
,
function
(
event
)
{
var
params
=
{};
params
[
event
.
target
.
name
]
=
event
.
target
.
checked
?
true
:
undefined
;
window
.
location
=
QUnit
.
url
(
params
);
});
}
var
toolbar
=
id
(
"
qunit-testrunner-toolbar
"
);
if
(
toolbar
)
{
var
filter
=
document
.
createElement
(
"
input
"
);
filter
.
type
=
"
checkbox
"
;
filter
.
id
=
"
qunit-filter-pass
"
;
addEvent
(
filter
,
"
click
"
,
function
()
{
var
ol
=
document
.
getElementById
(
"
qunit-tests
"
);
if
(
filter
.
checked
)
{
ol
.
className
=
ol
.
className
+
"
hidepass
"
;
}
else
{
var
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
;
var
ol
=
document
.
getElementById
(
"
qunit-tests
"
);
ol
.
className
=
ol
.
className
+
"
hidepass
"
;
}
toolbar
.
appendChild
(
filter
);
var
label
=
document
.
createElement
(
"
label
"
);
label
.
setAttribute
(
"
for
"
,
"
qunit-filter-pass
"
);
label
.
innerHTML
=
"
Hide passed tests
"
;
toolbar
.
appendChild
(
label
);
}
var
main
=
id
(
'
qunit-fixture
'
);
if
(
main
)
{
config
.
fixture
=
main
.
innerHTML
;
}
if
(
config
.
autostart
)
{
QUnit
.
start
();
}
};
addEvent
(
window
,
"
load
"
,
QUnit
.
load
);
// addEvent(window, "error") gives us a useless event object
window
.
onerror
=
function
(
message
,
file
,
line
)
{
if
(
QUnit
.
config
.
current
)
{
QUnit
.
pushFailure
(
message
,
file
+
"
:
"
+
line
);
}
else
{
QUnit
.
test
(
"
global failure
"
,
function
()
{
QUnit
.
pushFailure
(
message
,
file
+
"
:
"
+
line
);
});
}
};
function
done
()
{
config
.
autorun
=
true
;
// Log the last module results
if
(
config
.
currentModule
)
{
runLoggingCallbacks
(
'
moduleDone
'
,
QUnit
,
{
name
:
config
.
currentModule
,
failed
:
config
.
moduleStats
.
bad
,
passed
:
config
.
moduleStats
.
all
-
config
.
moduleStats
.
bad
,
total
:
config
.
moduleStats
.
all
}
);
}
var
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> tests 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
&&
typeof
document
!==
"
undefined
"
&&
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
)
{
var
key
;
for
(
var
i
=
0
;
i
<
sessionStorage
.
length
;
i
++
)
{
key
=
sessionStorage
.
key
(
i
++
);
if
(
key
.
indexOf
(
"
qunit-test-
"
)
===
0
)
{
sessionStorage
.
removeItem
(
key
);
}
}
}
runLoggingCallbacks
(
'
done
'
,
QUnit
,
{
failed
:
config
.
stats
.
bad
,
passed
:
passed
,
total
:
config
.
stats
.
all
,
runtime
:
runtime
}
);
}
function
validTest
(
name
)
{
var
filter
=
config
.
filter
,
run
=
false
;
if
(
!
filter
)
{
return
true
;
}
var
not
=
filter
.
charAt
(
0
)
===
"
!
"
;
if
(
not
)
{
filter
=
filter
.
slice
(
1
);
}
if
(
name
.
indexOf
(
filter
)
!==
-
1
)
{
return
!
not
;
}
if
(
not
)
{
run
=
true
;
}
return
run
;
}
// 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
// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
function
extractStacktrace
(
e
,
offset
)
{
offset
=
offset
||
3
;
if
(
e
.
stacktrace
)
{
// Opera
return
e
.
stacktrace
.
split
(
"
\n
"
)[
offset
+
3
];
}
else
if
(
e
.
stack
)
{
// Firefox, Chrome
var
stack
=
e
.
stack
.
split
(
"
\n
"
);
if
(
/^error$/i
.
test
(
stack
[
0
]))
{
stack
.
shift
();
}
return
stack
[
offset
];
}
else
if
(
e
.
sourceURL
)
{
// Safari, PhantomJS
// hopefully one day Safari provides actual stacktraces
// 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
;
}
}
function
sourceFromStacktrace
(
offset
)
{
try
{
throw
new
Error
();
}
catch
(
e
)
{
return
extractStacktrace
(
e
,
offset
);
}
}
function
escapeInnerText
(
s
)
{
if
(
!
s
)
{
return
""
;
}
s
=
s
+
""
;
return
s
.
replace
(
/
[\&
<>
]
/g
,
function
(
s
)
{
switch
(
s
)
{
case
"
&
"
:
return
"
&
"
;
case
"
<
"
:
return
"
<
"
;
case
"
>
"
:
return
"
>
"
;
default
:
return
s
;
}
});
}
function
synchronize
(
callback
,
last
)
{
config
.
queue
.
push
(
callback
);
if
(
config
.
autorun
&&
!
config
.
blocking
)
{
process
(
last
);
}
}
function
process
(
last
)
{
function
next
()
{
process
(
last
);
}
var
start
=
new
Date
().
getTime
();
config
.
depth
=
config
.
depth
?
config
.
depth
+
1
:
1
;
while
(
config
.
queue
.
length
&&
!
config
.
blocking
)
{
if
(
!
defined
.
setTimeout
||
config
.
updateRate
<=
0
||
(
(
new
Date
().
getTime
()
-
start
)
<
config
.
updateRate
)
)
{
config
.
queue
.
shift
()();
}
else
{
window
.
setTimeout
(
next
,
13
);
break
;
}
}
config
.
depth
--
;
if
(
last
&&
!
config
.
blocking
&&
!
config
.
queue
.
length
&&
config
.
depth
===
0
)
{
done
();
}
}
function
saveGlobal
()
{
config
.
pollution
=
[];
if
(
config
.
noglobals
)
{
for
(
var
key
in
window
)
{
if
(
!
hasOwn
.
call
(
window
,
key
)
)
{
continue
;
}
config
.
pollution
.
push
(
key
);
}
}
}
function
checkPollution
(
name
)
{
var
old
=
config
.
pollution
;
saveGlobal
();
var
newGlobals
=
diff
(
config
.
pollution
,
old
);
if
(
newGlobals
.
length
>
0
)
{
QUnit
.
pushFailure
(
"
Introduced global variable(s):
"
+
newGlobals
.
join
(
"
,
"
)
);
}
var
deletedGlobals
=
diff
(
old
,
config
.
pollution
);
if
(
deletedGlobals
.
length
>
0
)
{
QUnit
.
pushFailure
(
"
Deleted global variable(s):
"
+
deletedGlobals
.
join
(
"
,
"
)
);
}
}
// returns a new Array with the elements that are in a but not in b
function
diff
(
a
,
b
)
{
var
result
=
a
.
slice
();
for
(
var
i
=
0
;
i
<
result
.
length
;
i
++
)
{
for
(
var
j
=
0
;
j
<
b
.
length
;
j
++
)
{
if
(
result
[
i
]
===
b
[
j
]
)
{
result
.
splice
(
i
,
1
);
i
--
;
break
;
}
}
}
return
result
;
}
function
extend
(
a
,
b
)
{
for
(
var
prop
in
b
)
{
if
(
b
[
prop
]
===
undefined
)
{
delete
a
[
prop
];
// Avoid "Member not found" error in IE8 caused by setting window.constructor
}
else
if
(
prop
!==
"
constructor
"
||
a
!==
window
)
{
a
[
prop
]
=
b
[
prop
];
}
}
return
a
;
}
function
addEvent
(
elem
,
type
,
fn
)
{
if
(
elem
.
addEventListener
)
{
elem
.
addEventListener
(
type
,
fn
,
false
);
}
else
if
(
elem
.
attachEvent
)
{
elem
.
attachEvent
(
"
on
"
+
type
,
fn
);
}
else
{
fn
();
}
}
function
id
(
name
)
{
return
!!
(
typeof
document
!==
"
undefined
"
&&
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
)
{
//debugger;
var
callbacks
;
if
(
QUnit
.
hasOwnProperty
(
key
)
)
{
QUnit
[
key
].
call
(
scope
,
args
);
}
else
{
callbacks
=
config
[
key
];
for
(
var
i
=
0
;
i
<
callbacks
.
length
;
i
++
)
{
callbacks
[
i
].
call
(
scope
,
args
);
}
}
}
// Test for equality any JavaScript type.
// Author: Philippe Rathé <prathe@gmail.com>
QUnit
.
equiv
=
(
function
()
{
var
innerEquiv
;
// the real equiv function
var
callers
=
[];
// stack to decide between skip/abort functions
var
parents
=
[];
// stack to avoiding loops from circular referencing
// Call the o related callback with the given arguments.
function
bindCallbacks
(
o
,
callbacks
,
args
)
{
var
prop
=
QUnit
.
objectType
(
o
);
if
(
prop
)
{
if
(
QUnit
.
objectType
(
callbacks
[
prop
])
===
"
function
"
)
{
return
callbacks
[
prop
].
apply
(
callbacks
,
args
);
}
else
{
return
callbacks
[
prop
];
// or undefined
}
}
}
var
getProto
=
Object
.
getPrototypeOf
||
function
(
obj
)
{
return
obj
.
__proto__
;
};
var
callbacks
=
(
function
()
{
// for string, boolean, number and null
function
useStrictEquality
(
b
,
a
)
{
if
(
b
instanceof
a
.
constructor
||
a
instanceof
b
.
constructor
)
{
// to catch short annotaion VS 'new' annotation of a
// declaration
// e.g. var i = 1;
// var j = new Number(1);
return
a
==
b
;
}
else
{
return
a
===
b
;
}
}
return
{
"
string
"
:
useStrictEquality
,
"
boolean
"
:
useStrictEquality
,
"
number
"
:
useStrictEquality
,
"
null
"
:
useStrictEquality
,
"
undefined
"
:
useStrictEquality
,
"
nan
"
:
function
(
b
)
{
return
isNaN
(
b
);
},
"
date
"
:
function
(
b
,
a
)
{
return
QUnit
.
objectType
(
b
)
===
"
date
"
&&
a
.
valueOf
()
===
b
.
valueOf
();
},
"
regexp
"
:
function
(
b
,
a
)
{
return
QUnit
.
objectType
(
b
)
===
"
regexp
"
&&
// the regex itself
a
.
source
===
b
.
source
&&
// and its modifers
a
.
global
===
b
.
global
&&
// (gmi) ...
a
.
ignoreCase
===
b
.
ignoreCase
&&
a
.
multiline
===
b
.
multiline
;
},
// - skip when the property is a method of an instance (OOP)
// - abort otherwise,
// initial === would have catch identical references anyway
"
function
"
:
function
()
{
var
caller
=
callers
[
callers
.
length
-
1
];
return
caller
!==
Object
&&
typeof
caller
!==
"
undefined
"
;
},
"
array
"
:
function
(
b
,
a
)
{
var
i
,
j
,
loop
;
var
len
;
// b could be an object literal here
if
(
QUnit
.
objectType
(
b
)
!==
"
array
"
)
{
return
false
;
}
len
=
a
.
length
;
if
(
len
!==
b
.
length
)
{
// safe and faster
return
false
;
}
// track reference to avoid circular references
parents
.
push
(
a
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
loop
=
false
;
for
(
j
=
0
;
j
<
parents
.
length
;
j
++
)
{
if
(
parents
[
j
]
===
a
[
i
])
{
loop
=
true
;
// dont rewalk array
}
}
if
(
!
loop
&&
!
innerEquiv
(
a
[
i
],
b
[
i
]))
{
parents
.
pop
();
return
false
;
}
}
parents
.
pop
();
return
true
;
},
"
object
"
:
function
(
b
,
a
)
{
var
i
,
j
,
loop
;
var
eq
=
true
;
// unless we can proove it
var
aProperties
=
[],
bProperties
=
[];
// collection of
// strings
// 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
;
}
}
// stack constructor before traversing properties
callers
.
push
(
a
.
constructor
);
// track reference to avoid circular references
parents
.
push
(
a
);
for
(
i
in
a
)
{
// be strict: don't ensures hasOwnProperty
// and go deep
loop
=
false
;
for
(
j
=
0
;
j
<
parents
.
length
;
j
++
)
{
if
(
parents
[
j
]
===
a
[
i
])
{
// don't go down the same path twice
loop
=
true
;
}
}
aProperties
.
push
(
i
);
// collect a's properties
if
(
!
loop
&&
!
innerEquiv
(
a
[
i
],
b
[
i
]))
{
eq
=
false
;
break
;
}
}
callers
.
pop
();
// unstack, we are done
parents
.
pop
();
for
(
i
in
b
)
{
bProperties
.
push
(
i
);
// collect b's properties
}
// Ensures identical properties name
return
eq
&&
innerEquiv
(
aProperties
.
sort
(),
bProperties
.
sort
());
}
};
}());
innerEquiv
=
function
()
{
// can take multiple arguments
var
args
=
Array
.
prototype
.
slice
.
apply
(
arguments
);
if
(
args
.
length
<
2
)
{
return
true
;
// end transition
}
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
}
else
{
return
bindCallbacks
(
a
,
callbacks
,
[
b
,
a
]);
}
// apply transition with (1..n) arguments
}(
args
[
0
],
args
[
1
])
&&
arguments
.
callee
.
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
()
{
function
quote
(
str
)
{
return
'
"
'
+
str
.
toString
().
replace
(
/"/g
,
'
\\
"
'
)
+
'
"
'
;
}
function
literal
(
o
)
{
return
o
+
''
;
}
function
join
(
pre
,
arr
,
post
)
{
var
s
=
jsDump
.
separator
(),
base
=
jsDump
.
indent
(),
inner
=
jsDump
.
indent
(
1
);
if
(
arr
.
join
)
{
arr
=
arr
.
join
(
'
,
'
+
s
+
inner
);
}
if
(
!
arr
)
{
return
pre
+
post
;
}
return
[
pre
,
inner
+
arr
,
base
+
post
].
join
(
s
);
}
function
array
(
arr
,
stack
)
{
var
i
=
arr
.
length
,
ret
=
new
Array
(
i
);
this
.
up
();
while
(
i
--
)
{
ret
[
i
]
=
this
.
parse
(
arr
[
i
]
,
undefined
,
stack
);
}
this
.
down
();
return
join
(
'
[
'
,
ret
,
'
]
'
);
}
var
reName
=
/^function
(\w
+
)
/
;
var
jsDump
=
{
parse
:
function
(
obj
,
type
,
stack
)
{
//type is used mostly internally, you can fix a (custom)type in advance
stack
=
stack
||
[
];
var
parser
=
this
.
parsers
[
type
||
this
.
typeOf
(
obj
)
];
type
=
typeof
parser
;
var
inStack
=
inArray
(
obj
,
stack
);
if
(
inStack
!=
-
1
)
{
return
'
recursion(
'
+
(
inStack
-
stack
.
length
)
+
'
)
'
;
}
//else
if
(
type
==
'
function
'
)
{
stack
.
push
(
obj
);
var
res
=
parser
.
call
(
this
,
obj
,
stack
);
stack
.
pop
();
return
res
;
}
// else
return
(
type
==
'
string
'
)
?
parser
:
this
.
parsers
.
error
;
},
typeOf
:
function
(
obj
)
{
var
type
;
if
(
obj
===
null
)
{
type
=
"
null
"
;
}
else
if
(
typeof
obj
===
"
undefined
"
)
{
type
=
"
undefined
"
;
}
else
if
(
QUnit
.
is
(
"
RegExp
"
,
obj
))
{
type
=
"
regexp
"
;
}
else
if
(
QUnit
.
is
(
"
Date
"
,
obj
))
{
type
=
"
date
"
;
}
else
if
(
QUnit
.
is
(
"
Function
"
,
obj
))
{
type
=
"
function
"
;
}
else
if
(
typeof
obj
.
setInterval
!==
undefined
&&
typeof
obj
.
document
!==
"
undefined
"
&&
typeof
obj
.
nodeType
===
"
undefined
"
)
{
type
=
"
window
"
;
}
else
if
(
obj
.
nodeType
===
9
)
{
type
=
"
document
"
;
}
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
"
)
)
)
)
{
type
=
"
array
"
;
}
else
{
type
=
typeof
obj
;
}
return
type
;
},
separator
:
function
()
{
return
this
.
multiline
?
this
.
HTML
?
'
<br />
'
:
'
\n
'
:
this
.
HTML
?
'
'
:
'
'
;
},
indent
:
function
(
extra
)
{
// extra can be a number, shortcut for increasing-calling-decreasing
if
(
!
this
.
multiline
)
{
return
''
;
}
var
chr
=
this
.
indentChar
;
if
(
this
.
HTML
)
{
chr
=
chr
.
replace
(
/
\t
/g
,
'
'
).
replace
(
/ /g
,
'
'
);
}
return
new
Array
(
this
.
_depth_
+
(
extra
||
0
)
).
join
(
chr
);
},
up
:
function
(
a
)
{
this
.
_depth_
+=
a
||
1
;
},
down
:
function
(
a
)
{
this
.
_depth_
-=
a
||
1
;
},
setParser
:
function
(
name
,
parser
)
{
this
.
parsers
[
name
]
=
parser
;
},
// The next 3 are exposed so you can use them
quote
:
quote
,
literal
:
literal
,
join
:
join
,
//
_depth_
:
1
,
// This is the list of parsers, to modify them, use jsDump.setParser
parsers
:
{
window
:
'
[Window]
'
,
document
:
'
[Document]
'
,
error
:
'
[ERROR]
'
,
//when no parser is found, shouldn't happen
unknown
:
'
[Unknown]
'
,
'
null
'
:
'
null
'
,
'
undefined
'
:
'
undefined
'
,
'
function
'
:
function
(
fn
)
{
var
ret
=
'
function
'
,
name
=
'
name
'
in
fn
?
fn
.
name
:
(
reName
.
exec
(
fn
)
||
[])[
1
];
//functions never have name in IE
if
(
name
)
{
ret
+=
'
'
+
name
;
}
ret
+=
'
(
'
;
ret
=
[
ret
,
QUnit
.
jsDump
.
parse
(
fn
,
'
functionArgs
'
),
'
){
'
].
join
(
''
);
return
join
(
ret
,
QUnit
.
jsDump
.
parse
(
fn
,
'
functionCode
'
),
'
}
'
);
},
array
:
array
,
nodelist
:
array
,
'
arguments
'
:
array
,
object
:
function
(
map
,
stack
)
{
var
ret
=
[
],
keys
,
key
,
val
,
i
;
QUnit
.
jsDump
.
up
();
if
(
Object
.
keys
)
{
keys
=
Object
.
keys
(
map
);
}
else
{
keys
=
[];
for
(
key
in
map
)
{
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
.
jsDump
.
parse
(
val
,
undefined
,
stack
)
);
}
QUnit
.
jsDump
.
down
();
return
join
(
'
{
'
,
ret
,
'
}
'
);
},
node
:
function
(
node
)
{
var
open
=
QUnit
.
jsDump
.
HTML
?
'
<
'
:
'
<
'
,
close
=
QUnit
.
jsDump
.
HTML
?
'
>
'
:
'
>
'
;
var
tag
=
node
.
nodeName
.
toLowerCase
(),
ret
=
open
+
tag
;
for
(
var
a
in
QUnit
.
jsDump
.
DOMAttrs
)
{
var
val
=
node
[
QUnit
.
jsDump
.
DOMAttrs
[
a
]];
if
(
val
)
{
ret
+=
'
'
+
a
+
'
=
'
+
QUnit
.
jsDump
.
parse
(
val
,
'
attribute
'
);
}
}
return
ret
+
close
+
open
+
'
/
'
+
tag
+
close
;
},
functionArgs
:
function
(
fn
)
{
//function calls it internally, it's the arguments part of the function
var
l
=
fn
.
length
;
if
(
!
l
)
{
return
''
;
}
var
args
=
new
Array
(
l
);
while
(
l
--
)
{
args
[
l
]
=
String
.
fromCharCode
(
97
+
l
);
//97 is 'a'
}
return
'
'
+
args
.
join
(
'
,
'
)
+
'
'
;
},
key
:
quote
,
//object calls it internally, the key part of an item in a map
functionCode
:
'
[code]
'
,
//function calls it internally, it's the content of the function
attribute
:
quote
,
//node calls it internally, it's an html attribute value
string
:
quote
,
date
:
quote
,
regexp
:
literal
,
//regex
number
:
literal
,
'
boolean
'
:
literal
},
DOMAttrs
:{
//attributes to dump from nodes, name=>realName
id
:
'
id
'
,
name
:
'
name
'
,
'
class
'
:
'
className
'
},
HTML
:
false
,
//if true, entities are escaped ( <, >, \t, space and \n )
indentChar
:
'
'
,
//indentation unit
multiline
:
true
//if true, items in a collection, are separated by a \n, else just a space.
};
return
jsDump
;
}());
// from Sizzle.js
function
getText
(
elems
)
{
var
ret
=
""
,
elem
;
for
(
var
i
=
0
;
elems
[
i
];
i
++
)
{
elem
=
elems
[
i
];
// Get the text from text nodes and CDATA nodes
if
(
elem
.
nodeType
===
3
||
elem
.
nodeType
===
4
)
{
ret
+=
elem
.
nodeValue
;
// Traverse everything else, except comment nodes
}
else
if
(
elem
.
nodeType
!==
8
)
{
ret
+=
getText
(
elem
.
childNodes
);
}
}
return
ret
;
}
//from jquery.js
function
inArray
(
elem
,
array
)
{
if
(
array
.
indexOf
)
{
return
array
.
indexOf
(
elem
);
}
for
(
var
i
=
0
,
length
=
array
.
length
;
i
<
length
;
i
++
)
{
if
(
array
[
i
]
===
elem
)
{
return
i
;
}
}
return
-
1
;
}
/*
* Javascript Diff Algorithm
* By John Resig (http://ejohn.org/)
* Modified by Chu Alan "sprite"
*
* Released under the MIT license.
*
* More Info:
* http://ejohn.org/projects/javascript-diff-algorithm/
*
* Usage: QUnit.diff(expected, actual)
*
* 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
()
{
function
diff
(
o
,
n
)
{
var
ns
=
{};
var
os
=
{};
var
i
;
for
(
i
=
0
;
i
<
n
.
length
;
i
++
)
{
if
(
ns
[
n
[
i
]]
==
null
)
{
ns
[
n
[
i
]]
=
{
rows
:
[],
o
:
null
};
}
ns
[
n
[
i
]].
rows
.
push
(
i
);
}
for
(
i
=
0
;
i
<
o
.
length
;
i
++
)
{
if
(
os
[
o
[
i
]]
==
null
)
{
os
[
o
[
i
]]
=
{
rows
:
[],
n
:
null
};
}
os
[
o
[
i
]].
rows
.
push
(
i
);
}
for
(
i
in
ns
)
{
if
(
!
hasOwn
.
call
(
ns
,
i
)
)
{
continue
;
}
if
(
ns
[
i
].
rows
.
length
==
1
&&
typeof
(
os
[
i
])
!=
"
undefined
"
&&
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
]
};
}
}
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
])
{
n
[
i
+
1
]
=
{
text
:
n
[
i
+
1
],
row
:
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
])
{
n
[
i
-
1
]
=
{
text
:
n
[
i
-
1
],
row
:
n
[
i
].
row
-
1
};
o
[
n
[
i
].
row
-
1
]
=
{
text
:
o
[
n
[
i
].
row
-
1
],
row
:
i
-
1
};
}
}
return
{
o
:
o
,
n
:
n
};
}
return
function
(
o
,
n
)
{
o
=
o
.
replace
(
/
\s
+$/
,
''
);
n
=
n
.
replace
(
/
\s
+$/
,
''
);
var
out
=
diff
(
o
===
""
?
[]
:
o
.
split
(
/
\s
+/
),
n
===
""
?
[]
:
n
.
split
(
/
\s
+/
));
var
str
=
""
;
var
i
;
var
oSpace
=
o
.
match
(
/
\s
+/g
);
if
(
oSpace
==
null
)
{
oSpace
=
[
"
"
];
}
else
{
oSpace
.
push
(
"
"
);
}
var
nSpace
=
n
.
match
(
/
\s
+/g
);
if
(
nSpace
==
null
)
{
nSpace
=
[
"
"
];
}
else
{
nSpace
.
push
(
"
"
);
}
if
(
out
.
n
.
length
===
0
)
{
for
(
i
=
0
;
i
<
out
.
o
.
length
;
i
++
)
{
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>
"
;
}
}
for
(
i
=
0
;
i
<
out
.
n
.
length
;
i
++
)
{
if
(
out
.
n
[
i
].
text
==
null
)
{
str
+=
'
<ins>
'
+
out
.
n
[
i
]
+
nSpace
[
i
]
+
"
</ins>
"
;
}
else
{
var
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>
"
;
}
str
+=
"
"
+
out
.
n
[
i
].
text
+
nSpace
[
i
]
+
pre
;
}
}
}
return
str
;
};
}());
// for CommonJS enviroments, export everything
if
(
typeof
exports
!==
"
undefined
"
||
typeof
require
!==
"
undefined
"
)
{
extend
(
exports
,
QUnit
);
}
// get at whatever the global object is, like window in browsers
}(
(
function
()
{
return
this
;}.
call
())
));
jiotest/unhosted/jio.js
View file @
741a9b4f
...
...
@@ -2,13 +2,12 @@
;(
function
(
$
)
{
////////////////////////////////////////////////////////////////////////////
//
private var
s
//
constant
s
var
jioAttributeObject
=
{
'
jobMethodObject
'
:
{
'
isAvailable
'
:
{
'
checkNameAvailability
'
:
{
'
start_event
'
:
'
start_checkingNameAvailability
'
,
'
stop_event
'
:
'
stop_checkingNameAvailability
'
,
'
func
'
:
'
checkNameAvailability
'
,
'
retvalue
'
:
'
isAvailable
'
},
// returns 'boolean'
'
saveDocument
'
:
{
'
start_event
'
:
'
start_saving
'
,
...
...
@@ -27,18 +26,17 @@
'
stop_event
'
:
'
stop_removing
'
,
'
retvalue
'
:
'
isRemoved
'
}
// returns 'boolean'
},
'
localStorage
'
:
null
,
'
tabid
'
:
0
,
'
localStorage
'
:
null
,
// where the browser stores data
'
tabid
'
:
0
,
// this jio id
'
queue
'
:
null
,
// the job manager
'
storage
'
:
null
,
// the storage given at init
'
applicant
'
:
null
,
// the applicant given at init
'
listener
'
:
null
,
// the job listener
'
pubsub
'
:
null
,
// publisher subscriber
'
isReady
'
:
false
,
// check if jio is ready
'
storageTypeObject
'
:
{}
'
storageTypeObject
'
:
{}
// ex: {'type':'local','creator': fun ...}
};
// end private vars
// end constants
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
...
...
@@ -118,7 +116,7 @@
////////////////////////////////////////////////////////////////////////////
// Tools
var
createStorageObject
=
function
(
options
)
{
//
create a storage thanks to jioAttributeObject.storageTypeObject
//
Create a storage thanks to storages types set with 'addStorageType'.
if
(
!
jioAttributeObject
.
storageTypeObject
[
options
.
storage
.
type
])
return
null
;
// error!
...
...
@@ -131,9 +129,9 @@
////////////////////////////////////////////////////////////////////////////
// Publisher Subcriber
var
PubSub
=
function
()
{
if
(
!
$
.
jiopubsub
)
{
if
(
!
this
.
eventAction
)
{
var
topics
=
{};
$
.
jiopubsub
=
function
(
id
)
{
this
.
eventAction
=
function
(
id
)
{
var
callbacks
;
var
topic
=
id
&&
topics
[
id
];
if
(
!
topic
)
{
...
...
@@ -153,13 +151,13 @@
};
PubSub
.
prototype
=
{
publish
:
function
(
eventname
,
obj
)
{
$
.
jiopubsub
(
eventname
).
publish
(
obj
);
this
.
eventAction
(
eventname
).
publish
(
obj
);
},
subscribe
:
function
(
eventname
,
func
)
{
$
.
jiopubsub
(
eventname
).
subscribe
(
func
);
this
.
eventAction
(
eventname
).
subscribe
(
func
);
},
unsubscribe
:
function
(
eventname
)
{
$
.
jiopubsub
(
eventname
).
unsubscribe
();
this
.
eventAction
(
eventname
).
unsubscribe
();
}
};
jioAttributeObject
.
pubsub
=
new
PubSub
();
...
...
@@ -170,6 +168,7 @@
// Job & JobQueue
var
Job
=
function
(
options
)
{
// Job constructor
console
.
log
(
'
Job
'
);
var
job
=
$
.
extend
({},
options
);
job
[
'
id
'
]
=
0
;
...
...
@@ -178,6 +177,9 @@
};
var
JobQueue
=
function
()
{
// JobQueue is a queue of jobs. It will regulary copy this queue
// into localStorage to resume undone tasks.
// restore job list from local storage, if it exists
this
.
jobObject
=
jioAttributeObject
.
localStorage
.
getItem
(
'
jio/jobObject/
'
+
jioAttributeObject
.
tabid
);
...
...
@@ -210,14 +212,14 @@
}))
{
switch
(
job
.
method
)
{
// TODO merging is done with jio? or by the user's scripts?
case
'
isAvailable
'
:
case
'
checkNameAvailability
'
:
// TODO merge name availability between storages
// TODO send job ?
$
.
jio
(
'
publish
'
,{
'
event
'
:
jioAttributeObject
.
jobMethodObject
[
job
.
method
].
stop_event
,
'
job
'
:
job
});
return
;
case
'
getList
'
:
case
'
get
Document
List
'
:
// TODO merge list if necessary (we can create
// this.getList, deleted after sending the event,
// filled with done event) -> merge here or show
...
...
@@ -244,7 +246,7 @@
if
(
methods
.
isReady
())
{
t
.
done
(
o
.
job
);
returnedJobAnalyse
(
o
.
job
);
t
.
setJobObject
ToLocalStorage
();
t
.
copyJobQueue
ToLocalStorage
();
}
},
50
);
}});
...
...
@@ -253,7 +255,7 @@
if
(
methods
.
isReady
())
{
t
.
fail
(
o
.
job
);
returnedJobAnalyse
(
o
.
job
);
t
.
setJobObject
ToLocalStorage
();
t
.
copyJobQueue
ToLocalStorage
();
}
},
50
);
}});
...
...
@@ -262,7 +264,8 @@
JobQueue
.
prototype
=
{
isThereJobsWhere
:
function
(
func
)
{
// check if there is jobs where [func](job) == true
// Check if there is jobs, in the queue,
// where [func](job) == true.
if
(
!
func
)
return
true
;
...
...
@@ -272,15 +275,15 @@
}
return
false
;
},
setJobObject
ToLocalStorage
:
function
()
{
//
set the jobs to the local storage
copyJobQueue
ToLocalStorage
:
function
()
{
//
Copy job queue into localStorage.
return
jioAttributeObject
.
localStorage
.
setItem
(
'
jio/jobObject/
'
+
jioAttributeObject
.
tabid
,
this
.
jobObject
);
},
addJob
:
function
(
options
)
{
// Add a job to the
Job list
// Add a job to the
queue
// options.storage : the storage object
// options.job : the job object (may be a 'string')
...
...
@@ -295,16 +298,19 @@
// set job id
options
.
job
.
id
=
this
.
jobid
;
this
.
jobid
++
;
// save the new job
// save the new job
into the queue
this
.
jobObject
[
this
.
jobid
]
=
options
.
job
;
// save into localStorage
this
.
setJobObject
ToLocalStorage
();
this
.
copyJobQueue
ToLocalStorage
();
},
// end addJob
removeJob
:
function
(
options
)
{
// remove a job from localStorage
// Remove job(s) from queue where [options.where](job) === true.
// If there is no job in [options], then it will treat all job.
// If there is no [where] function, then it will remove all selected
// job. It means that if no option was given, it'll remove all jobs.
// options.job : the job object containing at least {id:..}.
// options.where : remove values where options.where(
a,
b) === true
// options.where : remove values where options.where(
jo
b) === true
console
.
log
(
'
removeJob
'
);
//// set tests functions
...
...
@@ -331,41 +337,43 @@
$
.
error
(
'
No jobs was found, when trying to remove some.
'
);
}
//// end modifying
this
.
setJobObject
ToLocalStorage
();
this
.
copyJobQueue
ToLocalStorage
();
console
.
log
(
'
end removeJob
'
);
},
resetAll
:
function
()
{
//
reset All job to 'initial'
//
Reset all job to 'initial'.
for
(
var
id
in
this
.
jobObject
)
{
this
.
jobObject
[
id
].
status
=
'
initial
'
;
}
this
.
setJobObject
ToLocalStorage
();
this
.
copyJobQueue
ToLocalStorage
();
},
invokeAll
:
function
()
{
// Do all jobs in the list
// Do all jobs in the queue.
//// do All jobs
for
(
var
i
in
this
.
jobObject
)
{
if
(
this
.
jobObject
[
i
].
status
===
'
initial
'
)
{
this
.
invoke
(
this
.
jobObject
[
i
]);
}
}
this
.
setJobObject
ToLocalStorage
();
this
.
copyJobQueue
ToLocalStorage
();
//// end, continue doing jobs asynchronously
},
invoke
:
function
(
job
)
{
// Do a job
// Do a job
invoking the good method in the good storage.
console
.
log
(
'
invoke
'
);
//// analysing job method
//
browsing methods
//
if the method does not exist, do nothing
if
(
!
jioAttributeObject
.
jobMethodObject
[
job
.
method
])
// TODO do an appropriate error reaction ? unknown job method
return
false
;
return
false
;
// suppose never happen
// test if a similar job is on going, in order to publish a start
// event if it is the first of his kind (method).
if
(
!
this
.
isThereJobsWhere
(
function
(
testjob
){
return
(
testjob
.
method
===
job
.
method
&&
testjob
.
method
===
'
ongoing
'
);
...
...
@@ -379,30 +387,29 @@
}
else
{
job
.
status
=
'
ongoing
'
;
}
//
create an
object and use it to save,load,...!
//
Create a storage
object and use it to save,load,...!
createStorageObject
(
{
'
storage
'
:
job
.
storage
,
'
applicant
'
:
jioAttributeObject
.
applicant
})[
job
.
method
](
job
);
//// end method analyse
console
.
log
(
'
end invoke
'
);
},
done
:
function
(
job
)
{
// This job is supposed done, we can remove it from
localStorag
e.
// This job is supposed done, we can remove it from
queu
e.
this
.
removeJob
({
'
job
'
:
job
});
},
fail
:
function
(
job
)
{
// This job cannot be done, change its status
into localStorage
.
// This job cannot be done, change its status.
this
.
jobObject
[
job
.
id
]
=
job
;
// save to local storage
this
.
setJobObject
ToLocalStorage
();
this
.
copyJobQueue
ToLocalStorage
();
},
clean
:
function
()
{
// Clean the job list, removing all jobs that have failed.
// It also change the localStorage
Job list
// It also change the localStorage
job queue
this
.
removeJob
(
undefined
,
{
'
where
'
:
function
(
job
)
{
...
...
@@ -426,9 +433,13 @@
JobListener
.
prototype
=
{
setIntervalDelay
:
function
(
interval
)
{
// Set the time between two joblist check in millisec
this
.
interval
=
interval
;
},
start
:
function
()
{
// Start the listener. It will always check if there are jobs in the
// queue
if
(
!
this
.
id
)
{
this
.
id
=
setInterval
(
function
()
{
// if there are jobs
...
...
@@ -459,6 +470,10 @@
// jio methods
var
methods
=
{
init
:
function
(
options
)
{
// Initialize jio. Create/Update all jio attributes and start
// listening to jobs. If jio is already initialized, arguments
// will be given to 'doMethod' which will treat them as a 'job'.
var
settings
=
$
.
extend
({},
options
);
// if already initialized
if
(
methods
.
isReady
())
{
...
...
@@ -512,14 +527,22 @@
jioAttributeObject
.
listener
=
new
JobListener
();
jioAttributeObject
.
listener
.
start
();
jioAttributeObject
.
isReady
=
true
;
return
true
;
},
isReady
:
function
()
{
// check if jio is ready
// Check if jio is ready to use.
return
jioAttributeObject
.
isReady
;
},
addStorageType
:
function
(
options
)
{
// Add a storage type to jio. Jio must have keys/types which are
// bound to a storage creation function. ex: 'local', will
// create a LocalStorage (in jio.storage.js).
// It can replace a older type with a newer creation function.
// options.type : the type of the storage.
// options.creator : the function to create a storage object.
var
settings
=
$
.
extend
({},
options
);
// add LocalStorage to storage object
if
(
settings
.
type
&&
settings
.
creator
)
{
jioAttributeObject
.
storageTypeObject
[
settings
.
type
]
=
settings
.
creator
;
...
...
@@ -528,10 +551,15 @@
return
false
;
},
getApplicant
:
function
()
{
// return applicant
// return applicant set at init of jio
return
jioAttributeObject
.
applicant
;
},
publish
:
function
(
options
)
{
// publish a jio event
// options.event : contains the event name.
// options[*] : are the arguments sent with this event.
if
(
!
methods
.
isReady
())
return
null
;
console
.
log
(
'
publish
'
+
options
.
event
);
var
tmp
=
$
.
extend
({},
options
);
...
...
@@ -539,34 +567,55 @@
jioAttributeObject
.
pubsub
.
publish
(
options
.
event
,
tmp
);
},
subscribe
:
function
(
options
)
{
// subscribe to a jio event. We can subscribe to jio event even
// if jio is not initialized.
// options.event : contains the event name.
// options.func : will call this function after receiving event.
console
.
log
(
'
subscribe
'
);
jioAttributeObject
.
pubsub
.
subscribe
(
options
.
event
,
options
.
func
);
},
unsubscribe
:
function
(
options
)
{
// unsubscribe to a jio event.
// options.event : contains the event name.
// TODO I wonder if it works.. ?
console
.
log
(
'
unsubscribe
'
);
jioAttributeObject
.
pubsub
.
unsubscribe
(
options
.
event
);
},
doMethod
:
function
(
options
)
{
// Do a method in jio. The method is set in [options.method],
// it can be everything but itself.
// $.jio({'fileName':'a','fileContent':'b','method':'save'}
if
(
options
.
method
)
{
if
(
options
.
method
===
'
doMethod
'
)
{
$
.
error
(
'
Cannot do method "doMethod" recursively.
'
);
return
null
;
}
if
(
methods
[
options
.
method
])
{
methods
[
options
.
method
](
options
);
}
else
{
$
.
error
(
'
Method
'
+
options
.
method
+
'
not found.
'
)
return
methods
[
options
.
method
](
options
);
}
$
.
error
(
'
Method
'
+
options
.
method
+
'
not found.
'
)
}
return
null
;
},
checkUserNameAvailability
:
function
(
options
)
{
checkNameAvailability
:
function
(
options
)
{
// Check the user availability in the storage set in [options]
// or in the storage set at init. At the end of the job,
// 'job_done' will be sent with this job and its 'isAvailable'
// return value.
// options.storage : the storage where to remove (optional)
// options.applicant : the applicant (optional)
// $.jio('check
User
NameAvailability',{'userName':'toto'});
// $.jio('checkNameAvailability',{'userName':'toto'});
console
.
log
(
'
isAvailable
'
);
if
(
!
methods
.
isReady
())
return
null
;
var
settings
=
$
.
extend
({
'
userName
'
:
jioAttributeObject
.
storage
.
userName
,
'
storage
'
:
jioAttributeObject
.
storage
,
'
applicant
'
:
jioAttributeObject
.
applicant
,
'
method
'
:
'
check
User
NameAvailability
'
'
method
'
:
'
checkNameAvailability
'
},
options
);
// check dependencies
if
(
settings
.
userName
)
{
...
...
@@ -576,6 +625,11 @@
return
null
;
},
saveDocument
:
function
(
options
)
{
// Load a document in the storage set in [options]
// or in the storage set at init. At the end of the job,
// 'job_done' will be sent with this job.
// options.storage : the storage where to remove (optional)
// options.applicant : the applicant (optional)
// $.jio('saveDocument',{'fileName':'a','fileContent':'b','options':{
// 'overwrite':false}}
...
...
@@ -595,6 +649,12 @@
return
null
;
},
loadDocument
:
function
(
options
)
{
// Load a document in the storage set in [options]
// or in the storage set at init. At the end of the job,
// 'job_done' will be sent with this job and its 'fileContent'
// return value.
// options.storage : the storage where to remove (optional)
// options.applicant : the applicant (optional)
// $.jio('loadDocument',{'fileName':'a'});
console
.
log
(
'
load
'
);
...
...
@@ -611,7 +671,16 @@
}
return
null
;
},
getDocument
:
function
(
options
)
{
// TODO
},
getDocumentList
:
function
(
options
)
{
// Get a document list of the user in the storage set in [options]
// or in the storage set at init. At the end of the job,
// 'job_done' will be sent with this job and its 'list'
// return value.
// options.storage : the storage where to remove (optional)
// options.applicant : the applicant (optional)
// $.jio('getDocumentList');
console
.
log
(
'
getList
'
);
...
...
@@ -625,6 +694,12 @@
{
'
job
'
:(
new
Job
(
settings
))}
);
},
removeDocument
:
function
(
options
)
{
// Remove a document in the storage set in [options]
// or in the storage set at init. At the end of the job,
// 'job_done' will be sent with this job.
// options.storage : the storage where to remove (optional)
// options.applicant : the applicant (optional)
// $.jio('removeDocument',{'fileName':'a'});
console
.
log
(
'
removeDocument
'
);
if
(
!
methods
.
isReady
())
return
null
;
...
...
@@ -639,9 +714,12 @@
}
return
null
;
},
start
:
function
(
options
)
{
// TODO
},
close
:
function
(
options
)
{
//
f
inish some job if possible and close jio.
//
i
t can be re-init later.
//
F
inish some job if possible and close jio.
//
I
t can be re-init later.
// TODO if someone is managing the browser closure or go to previous
// page, $.jio('close') will close tab id (if any) to free its jobs,
...
...
@@ -649,6 +727,7 @@
jioAttributeObject
.
listener
.
stop
();
jioAttributeObject
.
isReady
=
false
;
return
true
;
},
getJioAttributes
:
function
(
options
)
{
return
$
.
extend
({},
jioAttributeObject
);
...
...
jiotest/unhosted/jio.storage.js
View file @
741a9b4f
...
...
@@ -176,12 +176,11 @@
splitk
[
1
]
===
'
local
'
&&
splitk
[
2
]
===
job
.
storage
.
userName
&&
splitk
[
3
]
===
job
.
applicant
.
ID
)
{
// TODO error here
console
.
log
(
JSON
.
stringify
(
localStor
[
k
]));
fileObject
=
JSON
.
parse
(
localStor
[
k
]);
job
.
list
.
push
({
'
fileName
'
:
localStor
[
k
]
.
fileName
,
'
creationDate
'
:
localStor
[
k
]
.
creationDate
,
'
lastModified
'
:
localStor
[
k
]
.
lastModified
});
'
fileName
'
:
fileObject
.
fileName
,
'
creationDate
'
:
fileObject
.
creationDate
,
'
lastModified
'
:
fileObject
.
lastModified
});
}
}
console
.
log
(
JSON
.
stringify
(
job
.
list
));
...
...
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