Skip to content

Commit

Permalink
Merge pull request #1 from benjamn/run-tests-in-iframes
Browse files Browse the repository at this point in the history
Run each test in its own <iframe>
  • Loading branch information
benjamn committed Jun 3, 2013
2 parents 9425e58 + 603c9ef commit e829f8f
Show file tree
Hide file tree
Showing 24 changed files with 241 additions and 79 deletions.
2 changes: 2 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ module.exports = function(grunt) {
grunt.registerTask('build:min', ['jsx:release', 'browserify:min']);
grunt.registerTask('build:test', [
'jsx:debug',
'jsx:jasmine',
'jsx:test',
'browserify:jasmine',
'browserify:test'
]);

Expand Down
16 changes: 15 additions & 1 deletion grunt/config/browserify.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,23 @@ var transformer = {
after: [simpleBannerify]
};

var jasmine = {
entries: [
"./build/jasmine/all.js"
],
requires: {
"jasmine": "./build/jasmine/all.js"
},
outfile: "./build/jasmine.js",
debug: false
};

var test = {
entries: [
"./build/modules/test/all.js",
"./build/modules/**/__tests__/*-test.js"
],
requires: [
"**/__tests__/*-test.js"
],
outfile: './build/react-test.js',
debug: false,
Expand All @@ -88,6 +101,7 @@ var test = {

module.exports = {
basic: basic,
jasmine: jasmine,
test: test,
min: min,
transformer: transformer
Expand Down
22 changes: 19 additions & 3 deletions grunt/config/jsx/jsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,40 @@ var rootIDs = [

var debug = {
rootIDs: rootIDs,
configFile: "grunt/config/jsx/debug.json"
configFile: "grunt/config/jsx/debug.json",
sourceDir: "src",
outputDir: "build/modules"
};

var jasmine = {
rootIDs: [
"all"
],
configFile: debug.configFile,
sourceDir: "vendor/jasmine",
outputDir: "build/jasmine"
};

var test = {
rootIDs: rootIDs.concat([
"test/all.js",
"**/__tests__/*.js"
]),
configFile: debug.configFile
configFile: debug.configFile,
sourceDir: "src",
outputDir: "build/modules"
};

var release = {
rootIDs: rootIDs,
configFile: "grunt/config/jsx/release.json"
configFile: "grunt/config/jsx/release.json",
sourceDir: "src",
outputDir: "build/modules"
};

module.exports = {
debug: debug,
jasmine: jasmine,
test: test,
release: release
};
5 changes: 4 additions & 1 deletion grunt/config/phantom.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ exports.run = {
port: 8080,
harness: "test/phantom-harness.js",
// Run `grunt test --debug` to enable in-browser testing.
debug: !!grunt.option("debug")
debug: !!grunt.option("debug"),
tests: [
"**/__tests__/*-test.js"
]
};
18 changes: 14 additions & 4 deletions grunt/tasks/browserify.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ module.exports = function() {
// More/better assertions
// grunt.config.requires('outfile');
// grunt.config.requires('entries');
config.requires = config.requires || {};
config.transforms = config.transforms || [];
config.after = config.after || [];
if (typeof config.after === 'function') {
Expand All @@ -24,9 +23,20 @@ module.exports = function() {
var bundle = browserify(entries);

// Make sure the things that need to be exposed are.
// TODO: support a blob pattern maybe?
for (var name in config.requires) {
bundle.require(config.requires[name], { expose: name });
var requires = config.requires || {};
if (requires instanceof Array) {
grunt.file.expand({
nonull: true, // Keep IDs that don't expand to anything.
cwd: "src"
}, requires).forEach(function(name) {
bundle.require("./build/modules/" + name, {
expose: name.replace(/\.js$/i, "")
});
});
} else if (typeof requires === "object") {
Object.keys(requires).forEach(function(name) {
bundle.require(requires[name], { expose: name });
});
}

// Extract other options
Expand Down
4 changes: 2 additions & 2 deletions grunt/tasks/jsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ module.exports = function() {

var args = [
"bin/jsx",
"src",
"build/modules"
config.sourceDir,
config.outputDir
];

var rootIDs = expand({
Expand Down
8 changes: 8 additions & 0 deletions grunt/tasks/phantom.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ function run(config, done) {
args.push("--debug");
}

args.push("--tests");
var tests = grunt.file.expand({
nonull: true,
cwd: "src"
}, config.tests || []).forEach(function(file) {
args.push(file.replace(/\.js$/i, ""));
});

var child = spawn({
cmd: phantomjs,
args: args
Expand Down
57 changes: 48 additions & 9 deletions src/test/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,56 @@
// modules in src/test and to specify an ordering on those modules, since
// some still have implicit dependencies on others.

require("./phantom");
require("./console");
var Ap = Array.prototype;
var slice = Ap.slice;
var Fp = Function.prototype;

if (!Fp.bind) {
// PhantomJS doesn't support Function.prototype.bind natively, so
// polyfill it whenever this module is required.
Fp.bind = function(context) {
var func = this;
var args = slice.call(arguments, 1);
var bound;

if (func.prototype) {
if (args.length > 0) {
bound = function() {
return func.apply(
!(this instanceof func) && context || this,
args.concat(slice.call(arguments))
);
};
} else {
bound = function() {
return func.apply(
!(this instanceof func) && context || this,
arguments
);
};
}

bound.prototype = Object.create(func.prototype);

} else if (args.length > 0) {
bound = function() {
return func.apply(
context || this,
args.concat(slice.call(arguments))
);
};
} else {
bound = function() {
return func.apply(context || this, arguments);
};
}

return bound;
};
}

require("ReactTestUtils");
require("reactComponentExpect");
require("./diff");
require("./PrintReporter");
require("./HtmlReporter");
require("./ReporterView");
require("./SpecView");
require("./SuiteView");
require("./jasmine-support");
require("mocks");
require("mock-modules");
require("./mock-timers");
4 changes: 4 additions & 0 deletions src/utils/__tests__/ImmutableObject-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,23 @@ describe('ImmutableObject', function() {
});

testDev('should prevent shallow field addition when strict', function() {
if (window.callPhantom) return;
expect(function() {
var io = new ImmutableObject({oldField: 'asdf'});
io.newField = 'this will not work';
}).toThrow();
});

testDev('should prevent shallow field mutation when strict', function() {
if (window.callPhantom) return;
expect(function() {
var io = new ImmutableObject({oldField: 'asdf'});
io.oldField = 'this will not work!';
}).toThrow();
});

testDev('should prevent deep field addition when strict', function() {
if (window.callPhantom) return;
expect(function() {
var io =
new ImmutableObject({shallowField: {deepField: {oldField: null}}});
Expand All @@ -122,6 +125,7 @@ describe('ImmutableObject', function() {
});

testDev('should prevent deep field mutation when strict', function() {
if (window.callPhantom) return;
expect(function() {
var io =
new ImmutableObject({shallowField: {deepField: {oldField: null}}});
Expand Down
18 changes: 18 additions & 0 deletions test/frame.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<script>
jasmine = parent.jasmine;
jasmine.exposeFrom(window);

console = parent.console;
callPhantom = parent.callPhantom;
</script>
<script src="react-test.js"></script>
</head>
<body>
<script>
require(window.frameElement.getAttribute("test"));
</script>
</body>
</html>
12 changes: 9 additions & 3 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="jasmine.css" />
<style type="text/css">
iframe {
visibility: hidden;
position: absolute;
left: -1000px;
top: -1000px;
}
</style>
<script src="jasmine.js"></script>
<script src="jasmine-html.js"></script>
<script src="react-test.js"></script>
<script>
window.onload = function() {
jasmine.getEnv().execute();
require("jasmine").getEnv().execute();
};
</script>
</head>
Expand Down
44 changes: 33 additions & 11 deletions test/phantom-harness.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,58 @@ fs.changeWorkingDirectory(cwd);
// Hard to believe PhantomJS has no option parsing module.
var port = 8080;
var debug = false;
var lastArg;
var tests = [];
var rest = [];
while (argv.length > 0) {
var arg = argv.pop();
if (arg === "--port") {
port = +lastArg;
port = +rest.pop();
} else if (arg === "--debug") {
debug = true;
} else if (arg === "--tests") {
while (rest.length > 0)
tests.push(rest.pop());
}
lastArg = arg;
rest.push(arg);
}

// Dynamically interpolate the individual test <iframe>s.
var indexHtml = fs.read("index.html").replace(
/<body>([\s\S]*?)<\/body>/im,
function(outer, inner) {
return "<body>" + tests.map(function(test) {
return '\n <iframe src="frame.html" test=' +
JSON.stringify(test) + '></iframe>';
}).join("") + inner + "</body>";
}
);

var server = require("webserver").create();
server.listen(port, function(req, res) {
var file = req.url.replace(/^\/+/, "");
var content;

switch (file) {
case "":
default:
file = "index.html";
break;

case "react-test.js":
file = "../build/" + file;
break;

case "jasmine.css":
case "jasmine.js":
case "jasmine-html.js":
file = "../vendor/jasmine/" + file;
break;

case "jasmine.js":
file = "../build/" + file;
break;

case "frame.html":
break;

case "":
default:
file = "index.html";
content = indexHtml; // Prevents calling fs.read again.
break;
}

if (/\.css$/i.test(file)) {
Expand All @@ -60,7 +82,7 @@ server.listen(port, function(req, res) {
}

res.statusCode = 200;
res.write(fs.read(file));
res.write(content || fs.read(file));
res.close();
});

Expand Down
2 changes: 2 additions & 0 deletions src/test/HtmlReporter.js → vendor/jasmine/HtmlReporter.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var jasmine = require("./jasmine");

exports.HtmlReporter =
jasmine.HtmlReporter = function(_doc) {
var self = this;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var jasmine = require("./jasmine");
var diff = require('./diff');

var red = '\u001b[1;41m';
Expand Down Expand Up @@ -54,7 +55,7 @@ PrintReporter.prototype.reportRunnerResults = function(runner) {
this.failCount + " fail"
].join(" "));

require("test/phantom").exit(this.failCount);
require("./phantom").exit(this.failCount);
};


Expand Down
2 changes: 2 additions & 0 deletions src/test/ReporterView.js → vendor/jasmine/ReporterView.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var jasmine = require("jasmine");

jasmine.HtmlReporter.ReporterView = function(dom) {
this.startedAt = new Date();
this.runningSpecCount = 0;
Expand Down
Loading

0 comments on commit e829f8f

Please sign in to comment.