diff --git a/Gruntfile.js b/Gruntfile.js index d5c201ad38..fba98aab27 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -80,7 +80,7 @@ module.exports = function(grunt) { 'populist:test' ]); - grunt.registerTask('test', ['build:test', 'phantom:run']); + grunt.registerTask('test', ['build:test', 'build:basic', 'phantom:run']); grunt.registerTask('npm:test', ['build', 'npm:pack']); // Optimized build task that does all of our builds. The subtasks will be run diff --git a/src/environment/__tests__/ReactWebWorker-test.js b/src/environment/__tests__/ReactWebWorker-test.js new file mode 100644 index 0000000000..87f093f8c0 --- /dev/null +++ b/src/environment/__tests__/ReactWebWorker-test.js @@ -0,0 +1,50 @@ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @jsx React.DOM + * @emails react-core + */ + +/*jslint evil: true */ + +"use strict"; + +describe('ReactWebWorker', function() { + it('can run React in a web worker', function() { + var done = false; + var error; + + var worker = new Worker('/worker.js'); + worker.addEventListener('message', function(e) { + var data = JSON.parse(e.data); + if (data.type == 'error') { + error = data.message + "\n" + data.stack; + } else { + expect(data.type).toBe('done'); + done = true; + } + }); + + waitsFor(function() { + return done; + }); + runs(function() { + if (error) { + console.log(error); + throw new Error(error); + } + }); + }); +}); diff --git a/src/test/all.js b/src/test/all.js index 75d347b897..3549f081b3 100644 --- a/src/test/all.js +++ b/src/test/all.js @@ -2,38 +2,7 @@ // modules in src/test and to specify an ordering on those modules, since // some still have implicit dependencies on others. -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); - - function bound() { - var invokedAsConstructor = func.prototype && (this instanceof func); - return func.apply( - // Ignore the context parameter when invoking the bound function - // as a constructor. Note that this includes not only constructor - // invocations using the new keyword but also calls to base class - // constructors such as BaseClass.call(this, ...) or super(...). - !invokedAsConstructor && context || this, - args.concat(slice.call(arguments)) - ); - } - - // The bound function must share the .prototype of the unbound - // function so that any object created by one constructor will count - // as an instance of both constructors. - bound.prototype = func.prototype; - - return bound; - }; -} - +require("./phantomjs-shims"); require("ReactTestUtils"); require("reactComponentExpect"); require("mocks"); diff --git a/src/test/phantomjs-shims.js b/src/test/phantomjs-shims.js new file mode 100644 index 0000000000..12fe3bba9c --- /dev/null +++ b/src/test/phantomjs-shims.js @@ -0,0 +1,35 @@ +(function() { + +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); + + function bound() { + var invokedAsConstructor = func.prototype && (this instanceof func); + return func.apply( + // Ignore the context parameter when invoking the bound function + // as a constructor. Note that this includes not only constructor + // invocations using the new keyword but also calls to base class + // constructors such as BaseClass.call(this, ...) or super(...). + !invokedAsConstructor && context || this, + args.concat(slice.call(arguments)) + ); + } + + // The bound function must share the .prototype of the unbound + // function so that any object created by one constructor will count + // as an instance of both constructors. + bound.prototype = func.prototype; + + return bound; + }; +} + +})(); diff --git a/src/test/worker.js b/src/test/worker.js new file mode 100644 index 0000000000..2918cb6e4d --- /dev/null +++ b/src/test/worker.js @@ -0,0 +1,20 @@ +/* jshint worker: true */ +"use strict"; + +// The UMD wrapper tries to store on `global` if `window` isn't available +var global = {}; +importScripts("phantomjs-shims.js"); + +try { + importScripts("react.js"); +} catch (e) { + postMessage(JSON.stringify({ + type: 'error', + message: e.message, + stack: e.stack + })); +} + +postMessage(JSON.stringify({ + type: 'done' +})); diff --git a/test/phantom-harness.js b/test/phantom-harness.js index c07142ccad..c89f971a44 100644 --- a/test/phantom-harness.js +++ b/test/phantom-harness.js @@ -50,16 +50,19 @@ server.listen(port, function(req, res) { var content; switch (file) { + case "jasmine.js": + case "react.js": case "react-test.js": file = "../build/" + file; break; - case "jasmine.css": - file = "../vendor/jasmine/" + file; + case "phantomjs-shims.js": + case "worker.js": + file = "../src/test/" + file; break; - case "jasmine.js": - file = "../build/" + file; + case "jasmine.css": + file = "../vendor/jasmine/" + file; break; case "":