Skip to content

Commit fd2bc1a

Browse files
committed
Make jsdom browserifiable and add browser test runner
To run the tests: `node test/browser-runner.js`. The runner accepts the same options as `test/runner`, as well as some optional arguments that control the test setup.
1 parent 15e3c4f commit fd2bc1a

11 files changed

+437
-2
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
gmon.out
55
v8.log
66
node_modules
7+
test/worker-bundle.js

lib/jsdom.js

+7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ exports.debugMode = false;
3434
});
3535
});
3636

37+
exports.debugMode = false;
38+
39+
defineGetter(exports, 'version', function() {
40+
return pkg.version;
41+
});
42+
43+
var level2Html = require('./jsdom/level2/html');
3744
exports.level = function (level, feature) {
3845
if(!feature) {
3946
feature = 'core';

lib/jsdom/contextify-shim.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = function (o) {
2+
o.getGlobal = function () {
3+
return o;
4+
};
5+
};

package.json

+16-1
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,24 @@
6767
"contextify": "~0.1.5"
6868
},
6969
"devDependencies" : {
70+
"browser-request": "~0.3.1",
71+
"cssstyle-browserify": "git://github.com/TreehouseJS/CSSStyleDeclaration.git",
7072
"nodeunit": "~0.8.0",
7173
"optimist": "*",
72-
"urlmaster": ">=0.2.15"
74+
"urlmaster": ">=0.2.15",
75+
"http-browserify": "git://github.com/kumavis/http-browserify.git#dc84f15eb15c58505c0dea29de7ee64ff56dfe4f",
76+
"browserify": "~3.24.1",
77+
"q": "^1.0.1",
78+
"wd": "^0.2.21",
79+
"selenium-standalone": "^2.42.0-2.9.0",
80+
"http-server": "^0.6.1"
81+
},
82+
"browser": {
83+
"canvas": false,
84+
"contextify": "./lib/jsdom/contextify-shim.js",
85+
"cssstyle": "./node_modules/cssstyle-browserify/lib/CSSStyleDeclaration.js",
86+
"http": "./node_modules/http-browserify/index.js",
87+
"request": "./node_modules/browser-request/index.js"
7388
},
7489
"scripts": {
7590
"test": "node ./test/runner"

test/browser-main.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
window._browserRunner = {
2+
events: []
3+
};
4+
5+
var worker = new Worker('./worker-bundle.js');
6+
var consoleEl = document.querySelector('.console');
7+
8+
function fire(event, detail) {
9+
window._browserRunner.events.push({
10+
event: event,
11+
detail: detail
12+
});
13+
}
14+
15+
worker.onmessage = function (e) {
16+
if (e.data.method) {
17+
switch (e.data.method) {
18+
case 'fire':
19+
fire(e.data.params.event, e.data.params.data);
20+
break;
21+
case 'console':
22+
fire('console', e.data.params);
23+
console[e.data.params.level].apply(console, e.data.params.message);
24+
break;
25+
case 'ready':
26+
fire('ready');
27+
worker.postMessage(location.search.slice(1));
28+
break;
29+
default:
30+
console.error('Unknown method', e.data.method);
31+
}
32+
}
33+
};
34+

test/browser-runner.js

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
require('colors');
2+
var EventEmitter = require('events').EventEmitter;
3+
var wd = require('wd');
4+
var Q = require('q');
5+
var browser;
6+
7+
var optimist = require('./runner-options');
8+
9+
optimist.
10+
usage('Run the jsdom test suite in a browser via WebDriver').
11+
describe('http-port', 'port to run test server on (defaults to pid + 20000)').
12+
describe('web-driver-port', 'port to run Selenium on (defaults to pid + 20000)').
13+
describe('verbose-web-driver', 'print verbose output from wd to stdout').
14+
describe('verbose-browser-console', 'print browser console to stdout');
15+
16+
var argv = optimist.argv;
17+
18+
if (argv.help) {
19+
optimist.showHelp();
20+
process.exit();
21+
}
22+
23+
var httpPort = argv['http-port'] || process.pid + 20000;
24+
var wdPort = argv['web-driver-port'] || httpPort + 10000;
25+
26+
/**
27+
* Return the body of a function as a string
28+
*
29+
* wd should do this for us, but it doesn't
30+
*/
31+
function getFnBody(fn) {
32+
var src = fn.toString();
33+
return src.slice(src.indexOf('{') + 1, src.lastIndexOf('}'));
34+
}
35+
36+
function run() {
37+
var passed = false;
38+
browser.init({ browserName: 'chrome' }).
39+
then(function () {
40+
return browser.setAsyncScriptTimeout(5000);
41+
}).
42+
then(function () {
43+
return browser.get([
44+
'http://localhost:',
45+
httpPort,
46+
'/test?',
47+
require('querystring').stringify(argv)
48+
].join(''));
49+
}).
50+
then(function (result) {
51+
function browserPoll() {
52+
var events = window._browserRunner.events;
53+
54+
return events.splice(0, events.length);
55+
}
56+
57+
var deferred = Q.defer();
58+
59+
var runner = new EventEmitter();
60+
require('./runner-display')(runner, argv, function (err) {
61+
passed = !err;
62+
deferred.resolve();
63+
});
64+
var nodeunitTypes = require('nodeunit').types;
65+
66+
function poll() {
67+
browser.
68+
execute(getFnBody(browserPoll)).
69+
then(function (events) {
70+
var done = false;
71+
72+
events.forEach(function (event) {
73+
switch (event.event) {
74+
case 'testDone':
75+
case 'moduleDone':
76+
runner.emit(event.event,
77+
event.detail[0],
78+
nodeunitTypes.assertionList(
79+
event.detail[1].map(nodeunitTypes.assertion)));
80+
break;
81+
case 'log':
82+
runner.emit(event.event,
83+
nodeunitTypes.assertion(event.detail[0]));
84+
break;
85+
case 'done':
86+
runner.emit(event.event,
87+
nodeunitTypes.assertionList(
88+
event.detail[0].map(nodeunitTypes.assertion)));
89+
break;
90+
case 'console':
91+
case 'http':
92+
case 'status':
93+
case 'command':
94+
browser.
95+
emit.apply(browser, [event.event].concat(event.detail));
96+
break;
97+
default:
98+
runner.emit.apply(runner, [event.event].concat(event.detail));
99+
}
100+
101+
if (event.detail && event.event === 'done') {
102+
done = true;
103+
}
104+
});
105+
106+
if (!done) {
107+
setTimeout(poll, 50);
108+
}
109+
});
110+
}
111+
112+
poll();
113+
return deferred.promise;
114+
}).
115+
fin(function () {
116+
return browser.quit();
117+
}).
118+
fin(function () {
119+
process.exit(passed ? 0 : 1);
120+
}).
121+
done();
122+
}
123+
124+
// browserify and run the tests
125+
require('child_process').exec(
126+
'node_modules/browserify/bin/cmd.js test/worker.js -o test/worker-bundle.js',
127+
function (err, stdout, stderr) {
128+
if (err) {
129+
console.log(stdout.toString());
130+
console.log('Failed to browserify test/worker');
131+
console.log(err);
132+
process.exit(1);
133+
return;
134+
}
135+
136+
// start web server
137+
var httpServer = require('http-server').createServer().listen(httpPort);
138+
139+
// set up webdriver
140+
browser = wd.promiseRemote({
141+
port: wdPort
142+
});
143+
144+
if (argv['verbose-web-driver']) {
145+
// really verbose wd logging
146+
browser.on('status', function (info) {
147+
console.log(info.cyan);
148+
});
149+
browser.on('command', function (eventType, command, response) {
150+
console.log(' > ' + eventType.cyan, command, (response || '').grey);
151+
});
152+
browser.on('http', function (method, path, data) {
153+
console.log(' > ' + method.magenta, path, (data || '').grey);
154+
});
155+
}
156+
157+
if (argv['verbose-browser-console']) {
158+
browser.on('console', function (detail) {
159+
console[detail.level].apply(console, detail.message);
160+
});
161+
}
162+
163+
// start selenium
164+
var selenium = require('selenium-standalone');
165+
var wdServer = selenium({
166+
stdio: 'pipe'
167+
}, ['-port', wdPort]);
168+
169+
// time out after a default of 30 seconds
170+
var h = setTimeout(function () {
171+
console.log('Timed out waiting for selenium server to start');
172+
wdServer.kill();
173+
process.exit(1);
174+
}, argv.wdTimeout || 30 * 1000);
175+
176+
// Wait for selenium server to start.
177+
wdServer.stdout.on('data', function (output) {
178+
if (output.toString().indexOf('Started org.openqa.jetty.jetty.Server') >= 0) {
179+
clearTimeout(h);
180+
run();
181+
}
182+
});
183+
});

test/index.html

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>Browserify in worker test</title>
5+
</head>
6+
<body>
7+
<pre class='console'></pre>
8+
<script src="./browser-main.js"></script>
9+
</body>
10+
</html>

test/level2/core/files/staff2.xml.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var dom = require(__dirname + "/../../../../lib/jsdom/level2/core").dom.level2.core;
1+
var dom = require("../../../../lib/jsdom/level2/core").dom.level2.core;
22

33
exports.staff2 = function() {
44

test/level2/style.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var assert = require('assert');
33
var http = require('http');
44
var fs = require('fs');
55
var path = require('path');
6+
67
exports.tests = {
78

89
HTMLStyleElement01 : function (test) {

0 commit comments

Comments
 (0)