├── docs
├── _config.yml
└── index.md
├── tests
├── fixtures
│ ├── define-env.js
│ ├── define-env-2.js
│ ├── simple-worker.js
│ ├── environment-worker.js
│ └── import-worker.js
├── .eslintrc.json
├── index.html
└── index.js
├── .travis.yml
├── testem.js
├── .eslintrc.json
├── package.json
├── CHANGELOG.md
├── LICENSE
├── RELEASE.md
├── README.md
└── index.js
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/tests/fixtures/define-env.js:
--------------------------------------------------------------------------------
1 | self.env = {
2 | from: 'define-env',
3 | };
4 |
--------------------------------------------------------------------------------
/tests/fixtures/define-env-2.js:
--------------------------------------------------------------------------------
1 | self.env = Object.assign(self.env, {
2 | again: 'define-env-2',
3 | });
4 |
--------------------------------------------------------------------------------
/tests/fixtures/simple-worker.js:
--------------------------------------------------------------------------------
1 | self.onmessage = function onmessage(message) {
2 |
3 | 'use strict';
4 |
5 | postMessage(message.data);
6 |
7 | };
8 |
--------------------------------------------------------------------------------
/tests/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "globals": {
3 | "QUnit": true,
4 | "WorkerBox": true
5 | },
6 | "rules": {
7 | "func-names": "off",
8 | "prefer-arrow-callback": "off"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tests/fixtures/environment-worker.js:
--------------------------------------------------------------------------------
1 | self.onmessage = function onmessage(message) {
2 |
3 | 'use strict';
4 |
5 | postMessage({
6 | message: message.data,
7 | environment: self.env,
8 | });
9 |
10 | };
11 |
--------------------------------------------------------------------------------
/tests/fixtures/import-worker.js:
--------------------------------------------------------------------------------
1 | self.importScripts('./define-env.js');
2 |
3 | self.onmessage = function onmessage(message) {
4 |
5 | 'use strict';
6 |
7 | postMessage({
8 | message: message.data,
9 | environment: self.env,
10 | });
11 |
12 | };
13 |
14 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "8"
5 |
6 | addons:
7 | chrome: stable
8 |
9 | branches:
10 | only:
11 | - master
12 |
13 | cache:
14 | directories:
15 | - $HOME/.npm
16 |
17 | script:
18 | - npm run lint
19 | - npm run test
20 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | test_page: 'tests/index.html',
3 | launch_in_ci: [
4 | 'Chrome',
5 | ],
6 | launch_in_dev: [
7 | 'Chrome',
8 | ],
9 | browser_args: {
10 | Chrome: {
11 | mode: 'ci',
12 | args: [
13 | '--disable-gpu',
14 | '--headless',
15 | '--remote-debugging-port=9222',
16 | ],
17 | },
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb-base",
3 | "parserOptions": {
4 | "sourceType": "script"
5 | },
6 | "env":{
7 | "browser": true
8 | },
9 | "rules": {
10 | "no-param-reassign": [ "error", { "props": false } ],
11 | "no-restricted-globals": "off",
12 | "padded-blocks": [ "error", "always" ],
13 | "space-before-function-paren": "off",
14 | "strict": [ "error", "function" ]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | WorkerBox Tests
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "worker-box",
3 | "version": "1.1.0",
4 | "description": "A toolbox to help you test Web Workers",
5 | "main": "index.js",
6 | "directories": {
7 | "doc": "docs"
8 | },
9 | "scripts": {
10 | "lint": "eslint '**/*.js'",
11 | "test": "testem ci",
12 | "test:dev": "testem"
13 | },
14 | "author": "Trent Willis ",
15 | "repository": "trentmwillis/worker-box",
16 | "license": "MIT",
17 | "devDependencies": {
18 | "eslint": "^4.6.1",
19 | "eslint-config-airbnb-base": "^12.0.0",
20 | "eslint-plugin-import": "^2.7.0",
21 | "qunitjs": "^2.4.0",
22 | "testem": "^1.18.4"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | 1.1.0 / 2017-11-08
2 | ==================
3 |
4 | * Add unregister function for removing previous definitions
5 |
6 | 1.0.1 / 2017-09-14
7 | ==================
8 |
9 | * Add release documentation
10 | * Ensure imports from created workers are relative to location
11 | * Add CHANGELOG.md
12 | * Add a bit more of an intro to the readme
13 | * Add repo info to package.json
14 | * Add basic installation instructions
15 | * Add npm badge
16 |
17 | v1.0.0 / 2017-09-13
18 | ===================
19 |
20 | * Setup Travis
21 | * Add create function
22 | * Finish v1 implementation
23 | * Finish v1 docs
24 | * Finish vast majority of initial implementation
25 | * More initial work on stub API
26 | * Create LICENSE
27 | * Set theme jekyll-theme-cayman
28 | * Set theme jekyll-theme-minimal
29 | * Initial work
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Trent Willis
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
1 | # Release Process
2 |
3 | The following details how to perform a release for `worker-box`.
4 |
5 | ## Update Changelog
6 |
7 | First, we need to update the changelog using [`git-extras`](https://github.com/tj/git-extras).
8 |
9 | ```bash
10 | git changelog
11 | ```
12 |
13 | Be sure to cleanup the changelog by removing merge commits or any commits that don't provide meaningful information. Then, commit the changes with the following message:
14 |
15 | ```bash
16 | git commit -am "Update changelog for vx.x.x"
17 | ```
18 |
19 | ## Tag A New Version
20 |
21 | Next, we need to tag the new version. We do this using the built in `npm` command:
22 |
23 | ```bash
24 | npm version x.x.x
25 | ```
26 |
27 | Then, we push the new commits and tag to the repo:
28 |
29 | ```
30 | git push origin master --tags
31 | ```
32 |
33 | ## Publish The New Version
34 |
35 | Almost there! We now publish the new version using:
36 |
37 | ```bash
38 | npm publish
39 | ```
40 |
41 | ## Update release notes
42 |
43 | Finally, publish the [release on GitHub](https://github.com/trentmwillis/worker-box/releases) by drafting a new release. Use the changelog to populate the entry.
44 |
45 | And that's it! Congratulations!
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Worker Box [](https://travis-ci.org/trentmwillis/worker-box) [](https://pretty-okay.com/worker-box) [](https://www.npmjs.com/package/worker-box)
2 |
3 | Worker Box is a toolbox to help you test [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API). It provides an easy way to create, stub, and modify your Workers without complicated test servers or monkey patches. For more info, be sure to check out the [documentation](https://pretty-okay.com/worker-box/)!
4 |
5 | ## Installation
6 |
7 | Install Worker Box through [npm](https://www.npmjs.com/):
8 |
9 | ```bash
10 | npm install --save-dev worker-box
11 | ```
12 |
13 | And then load it via a script tag in your page:
14 |
15 | ```html
16 |
17 | ```
18 |
19 | And that's it! The `WorkerBox` global should now be available for use.
20 |
21 | ## Usage
22 |
23 | For information on how to use Worker Box and the APIs it provides, check out [the official documentation]([documentation](https://pretty-okay.com/worker-box/)).
24 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | Worker Box is a toolbox to help you test [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API). It provides an easy way to stub and modify your Workers without complicated test servers or monkey patches.
2 |
3 | ## Installation
4 |
5 | Install Worker Box through [npm](https://www.npmjs.com/):
6 |
7 | ```bash
8 | npm install --save-dev worker-box
9 | ```
10 |
11 | And then load it via a script tag in your page:
12 |
13 | ```html
14 |
15 | ```
16 |
17 | And that's it! The `WorkerBox` global should now be available for use.
18 |
19 | ## Setup and Cleanup
20 |
21 | To use Worker Box, you start by simply calling:
22 |
23 | ```js
24 | WorkerBox.setup();
25 | ```
26 |
27 | By default, this won't do much except replace your global `Worker` class with a wrapper that allows Worker Box to work its magic.
28 |
29 | On the flip side, when you're ready to stop using Worker Box (such as at the end of a test), you simply call:
30 |
31 | ```js
32 | WorkerBox.cleanup();
33 | ```
34 |
35 | One notable thing that you get simply for setting up Worker Box is tracking of all Worker instances that get created. This means that when you decide to cleanup Worker Box can terminate all running instances immediately. Pretty nifty.
36 |
37 | ## Stubbing A Worker
38 |
39 | You can [stub](https://en.wikipedia.org/wiki/Method_stub) a Worker by using the `stub` method.
40 |
41 | ```js
42 | WorkerBox.stub(scriptPath, {
43 | importScripts: [],
44 | code: () => {}
45 | });
46 | ```
47 |
48 | When trying to create a stubbed Worker, the original script will be ignored and instead you will get a Worker that either does nothing or executes code/scripts you have provided.
49 |
50 | It takes two arguments:
51 |
52 | 1. A string path to the Worker to stub.
53 | 2. An options object.
54 |
55 | The path to the Worker will be resolved relative to your current path. So, if you have tests running at `localhost:8080/tests/index.html`, then using either `/workers/my-worker.js` or `../workers/my-worker.js` will yield the same result.
56 |
57 | The options object can define two optional properties.
58 |
59 | The first is `importScripts` which allows you to specify an array of paths to other scripts which should be imported into the Worker. These script paths are resolved relative to your current path.
60 |
61 | The second is `code` which is a function that defines code to execute within the Worker. This can be any arbitrary code that you wish to execute within the Worker and will have complete access to the Worker's scope. Note that since this code is executed within the Worker you will not have access to the scope outside your function as you normally would.
62 |
63 | Note: When using both `importScripts` and `code`, the `importScripts` will be imported _before_ executing the contents of `code`.
64 |
65 | ## Prepending Code To A Worker
66 |
67 | Similarly to stubbing, you can also prepend code to a Worker by using the `prepend` method.
68 |
69 | ```js
70 | WorkerBox.prepend(scriptPath, {
71 | importScripts: [],
72 | code: () => {}
73 | });
74 | ```
75 |
76 | This is particularly useful for scenarios where you wish to alter some state before the Worker executes, such as setting up a mock server to handle external requests.
77 |
78 | The parameters and options for `prepend` are the same as for `stub`. The only difference is that after `importScripts` and `code` execute, the original Worker script will also execute. Note that `importScripts` executed from within your original Worker will resolve paths relative to that Worker's path as they would in normal usage.
79 |
80 | ## Unregister Prepend or Stub Definitions
81 |
82 | By default, if you prepend or stub a Worker, you can not use prepend or stub again on that same Worker. If you need to redefine the override for any reason, you can use the `unregister` method.
83 |
84 | ```js
85 | WorkerBox.stub(scriptPath);
86 | WorkerBox.unregister(scriptPath);
87 | ```
88 |
89 | ## Creating A Worker
90 |
91 | If you want to create a Worker directly, as opposed to stubbing/modifying a Worker script, you can use the `create` function.
92 |
93 | ```js
94 | WorkerBox.create(code);
95 | ```
96 |
97 | This will create a Worker instance from the provided function, `code`, which you can then interact with like a normal Worker just without a separate file.
98 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | window.WorkerBox = (function initWorkerBox() {
2 |
3 | 'use strict';
4 |
5 | function stubImportScripts() {
6 |
7 | let relativeTo;
8 |
9 | const originalImportScripts = self.importScripts;
10 | self.importScripts = function stubbedImportScripts(...scripts) {
11 |
12 | scripts.forEach((script) => {
13 |
14 | originalImportScripts(new URL(script, relativeTo));
15 |
16 | });
17 |
18 | };
19 |
20 | self.importScripts.relativeTo = function setImportScriptsRelativeTo(base) {
21 |
22 | relativeTo = base;
23 |
24 | };
25 |
26 | self.importScriptAndChangeRelativity = function importScriptAndChangeRelativity(script) {
27 |
28 | const absoluteScript = new URL(script, relativeTo);
29 | self.importScripts.relativeTo(absoluteScript);
30 | self.importScripts(absoluteScript);
31 |
32 | };
33 |
34 | }
35 |
36 | function stringifyFunction(fn) {
37 |
38 | let functionString = fn.toString();
39 | const needsFunctionKeyword = !functionString.startsWith('function') && !functionString.startsWith('() =>');
40 | if (needsFunctionKeyword) {
41 |
42 | functionString = `function ${functionString}`;
43 |
44 | }
45 |
46 | return `(${functionString})();`;
47 |
48 | }
49 |
50 | function createWorkerPrepend(workerDefinition, workerOptions) {
51 |
52 | const { script, options: { code, importScripts } } = workerDefinition;
53 | const src = [];
54 |
55 | src.push(`${stubImportScripts.toString()}`);
56 | src.push('stubImportScripts();');
57 | src.push(`importScripts.relativeTo('${location.href}');`);
58 |
59 | if (importScripts.length) {
60 |
61 | const importScriptList = importScripts.map(importScript => `'${importScript}'`).join(', ');
62 | src.push(`importScripts(${importScriptList});`);
63 |
64 | }
65 |
66 | src.push(`${stringifyFunction(code)}`);
67 | src.push(`importScriptAndChangeRelativity('${script}');`);
68 |
69 | const blob = new Blob([src.join('\n')], { type: 'application/javascript' });
70 | const url = URL.createObjectURL(blob);
71 | return new Worker(url, workerOptions);
72 |
73 | }
74 |
75 | function createWorkerStub(workerDefinition, workerOptions) {
76 |
77 | const { options: { code, importScripts } } = workerDefinition;
78 | const src = [];
79 |
80 | src.push(`${stubImportScripts.toString()}`);
81 | src.push('stubImportScripts();');
82 | src.push(`importScripts.relativeTo('${location.href}');`);
83 |
84 | if (importScripts.length) {
85 |
86 | const importScriptList = importScripts.map(script => `'${script}'`).join(', ');
87 | src.push(`importScripts(${importScriptList});`);
88 |
89 | }
90 |
91 | src.push(stringifyFunction(code));
92 |
93 | const blob = new Blob([src.join('\n')], { type: 'application/javascript' });
94 | const url = URL.createObjectURL(blob);
95 | return new Worker(url, workerOptions);
96 |
97 | }
98 |
99 | const creator = {
100 | prepend: createWorkerPrepend,
101 | stub: createWorkerStub,
102 | };
103 |
104 | const workerDefinitions = [];
105 | const workers = [];
106 |
107 | function findWorkerDefinition(script) {
108 |
109 | return workerDefinitions.find(definition => definition.script === script);
110 |
111 | }
112 |
113 | /**
114 | * Creates a Worker from the given function and options.
115 | *
116 | * @public
117 | * @param {Function} code
118 | * @param {object} workerOptions
119 | * @return {Worker}
120 | */
121 | function create(code, workerOptions) {
122 |
123 | const src = [];
124 |
125 | src.push(`${stubImportScripts.toString()}`);
126 | src.push('stubImportScripts();');
127 | src.push(`importScripts.relativeTo('${location.href}');`);
128 | src.push(stringifyFunction(code));
129 |
130 | const blob = new Blob([src.join('\n')], { type: 'application/javascript' });
131 | const url = URL.createObjectURL(blob);
132 | return new Worker(url, workerOptions);
133 |
134 | }
135 |
136 | /**
137 | * Replaces the given worker with an augmented version that can execute
138 | * additional imports and code before running the actual script.
139 | *
140 | * @public
141 | * @param {string} script
142 | * @param {object} options
143 | */
144 | function prepend(script, options = {}) {
145 |
146 | const absoluteScript = (new URL(script, location.href)).toString();
147 | const workerDefinition = findWorkerDefinition(absoluteScript);
148 | if (workerDefinition) {
149 |
150 | throw new Error(`The Worker script "${script}" has already been registered with "${workerDefinition.type}".`);
151 |
152 | }
153 |
154 | options.importScripts = options.importScripts || [];
155 | options.code = options.code || (() => {});
156 |
157 | workerDefinitions.push({
158 | type: 'prepend',
159 | script: absoluteScript,
160 | options,
161 | });
162 |
163 | }
164 |
165 | /**
166 | * Replaces the given worker with an empty version or the specified function.
167 | *
168 | * @public
169 | * @param {string} script
170 | * @param {object} options
171 | */
172 | function stub(script, options = {}) {
173 |
174 | const absoluteScript = (new URL(script, location.href)).toString();
175 | const workerDefinition = findWorkerDefinition(absoluteScript);
176 | if (workerDefinition) {
177 |
178 | throw new Error(`The Worker script "${script}" has already been registered with "${workerDefinition.type}".`);
179 |
180 | }
181 |
182 | options.importScripts = options.importScripts || [];
183 | options.code = options.code || (() => {});
184 |
185 | workerDefinitions.push({
186 | type: 'stub',
187 | script: absoluteScript,
188 | options,
189 | });
190 |
191 | }
192 |
193 |
194 | /**
195 | * Unregisters a worker definition that was previously registered with either
196 | * prepend or stub. Returns a boolean indicating whether or not a registration
197 | * was removed.
198 | *
199 | * @public
200 | * @param {string} script
201 | * @return {boolean}
202 | */
203 | function unregister(script) {
204 |
205 | const absoluteScript = (new URL(script, location.href)).toString();
206 | const index = workerDefinitions.findIndex(definition => definition.script === absoluteScript);
207 |
208 | if (index !== -1) {
209 |
210 | workerDefinitions.splice(index, 1);
211 | return true;
212 |
213 | }
214 |
215 | return false;
216 |
217 | }
218 |
219 | function setup() {
220 |
221 | if (self.Worker.isWorkerBox) {
222 |
223 | return;
224 |
225 | }
226 |
227 | function FakeWorker(script, workerOptions) {
228 |
229 | const absoluteScript = (new URL(script, location.href)).toString();
230 | const workerDefinition = findWorkerDefinition(absoluteScript);
231 | let worker;
232 | if (workerDefinition) {
233 |
234 | worker = creator[workerDefinition.type](workerDefinition, workerOptions);
235 |
236 | } else {
237 |
238 | worker = new FakeWorker.Original(script, workerOptions);
239 |
240 | }
241 |
242 | workers.push(worker);
243 |
244 | return worker;
245 |
246 | }
247 | FakeWorker.isWorkerBox = true;
248 | FakeWorker.Original = self.Worker;
249 |
250 | self.Worker = FakeWorker;
251 |
252 | }
253 |
254 | function cleanup() {
255 |
256 | if (self.Worker.isWorkerBox) {
257 |
258 | workerDefinitions.length = 0;
259 | workers.forEach(worker => worker.terminate());
260 | workers.length = 0;
261 | self.Worker = self.Worker.Original;
262 |
263 | }
264 |
265 | }
266 |
267 | return {
268 | cleanup,
269 | create,
270 | prepend,
271 | setup,
272 | stub,
273 | unregister,
274 | };
275 |
276 | }());
277 |
--------------------------------------------------------------------------------
/tests/index.js:
--------------------------------------------------------------------------------
1 | QUnit.module('WorkerBox', function(hooks) {
2 |
3 | 'use strict';
4 |
5 | hooks.afterEach(function() {
6 |
7 | WorkerBox.cleanup();
8 |
9 | });
10 |
11 | QUnit.test('ensure /tests/fixtures/simple-worker.js behaves as expected', async function(assert) {
12 |
13 | const done = assert.async();
14 | const originalMessage = 'foo';
15 | const worker = new Worker('/tests/fixtures/simple-worker.js');
16 | worker.onmessage = (message) => {
17 |
18 | assert.strictEqual(message.data, originalMessage);
19 | worker.terminate();
20 | done();
21 |
22 | };
23 | worker.postMessage(originalMessage);
24 |
25 | });
26 |
27 | QUnit.test('ensure /tests/fixtures/environment-worker.js behaves as expected', async function(assert) {
28 |
29 | const done = assert.async();
30 | const originalMessage = 'foo';
31 | const worker = new Worker('/tests/fixtures/environment-worker.js');
32 | worker.onmessage = (message) => {
33 |
34 | assert.deepEqual(message.data, {
35 | message: originalMessage,
36 | environment: undefined,
37 | });
38 | worker.terminate();
39 | done();
40 |
41 | };
42 | worker.postMessage(originalMessage);
43 |
44 | });
45 |
46 | QUnit.module('setup', function() {
47 |
48 | QUnit.test('replaces the global Worker with a FakeWorker', function(assert) {
49 |
50 | const originalWorker = self.Worker;
51 | assert.notOk('isWorkerBox' in Worker);
52 | assert.notOk('Original' in Worker);
53 |
54 | WorkerBox.setup();
55 |
56 | assert.ok('isWorkerBox' in Worker);
57 | assert.ok('Original' in Worker);
58 |
59 | assert.notStrictEqual(Worker, originalWorker);
60 | assert.strictEqual(Worker.Original, originalWorker);
61 |
62 | });
63 |
64 | });
65 |
66 | QUnit.module('create', function() {
67 |
68 | QUnit.test('creates a worker from the given function', function(assert) {
69 |
70 | const done = assert.async();
71 | const originalMessage = 'foo';
72 | const worker = WorkerBox.create(() => {
73 |
74 | self.onmessage = function onmessage(message) {
75 |
76 | postMessage(`it works, ${message.data}!`);
77 |
78 | };
79 |
80 | });
81 | worker.onmessage = (message) => {
82 |
83 | assert.strictEqual(message.data, 'it works, foo!');
84 | worker.terminate();
85 | done();
86 |
87 | };
88 | worker.postMessage(originalMessage);
89 |
90 | });
91 |
92 | QUnit.test('imports scripts relative to the current url', function(assert) {
93 |
94 | const done = assert.async();
95 | const originalMessage = 'foo';
96 | const worker = WorkerBox.create(() => {
97 |
98 | self.importScripts('/tests/fixtures/define-env.js');
99 | self.importScripts('./fixtures/environment-worker.js');
100 |
101 | });
102 | worker.onmessage = (message) => {
103 |
104 | assert.deepEqual(message.data, {
105 | environment: {
106 | from: 'define-env',
107 | },
108 | message: 'foo',
109 | });
110 | worker.terminate();
111 | done();
112 |
113 | };
114 | worker.postMessage(originalMessage);
115 |
116 | });
117 |
118 | });
119 |
120 | QUnit.module('stub', function(nestedHooks) {
121 |
122 | nestedHooks.beforeEach(function() {
123 |
124 | this.baseWorker = new Worker('/tests/fixtures/simple-worker.js');
125 |
126 | });
127 |
128 | nestedHooks.afterEach(function() {
129 |
130 | this.baseWorker.terminate();
131 |
132 | });
133 |
134 | QUnit.test('replaces the specified script with a no-op', function(assert) {
135 |
136 | assert.expect(0);
137 |
138 | WorkerBox.setup();
139 | WorkerBox.stub('/tests/fixtures/simple-worker.js');
140 |
141 | const originalMessage = 'foo';
142 | const worker = new Worker('/tests/fixtures/simple-worker.js');
143 | worker.onmessage = () => assert.ok(false);
144 | worker.postMessage(originalMessage);
145 |
146 | const done = assert.async();
147 | this.baseWorker.onmessage = done;
148 | this.baseWorker.postMessage(originalMessage);
149 |
150 | });
151 |
152 | QUnit.test('replaces the specified script with the specified code', function(assert) {
153 |
154 | WorkerBox.setup();
155 | WorkerBox.stub('/tests/fixtures/simple-worker.js', {
156 | code() {
157 |
158 | self.onmessage = function onmessage(message) {
159 |
160 | postMessage(`stubbed ${message.data}`);
161 |
162 | };
163 |
164 | },
165 | });
166 |
167 | const done = assert.async();
168 | const originalMessage = 'foo';
169 | const worker = new Worker('/tests/fixtures/simple-worker.js');
170 | worker.onmessage = (message) => {
171 |
172 | assert.equal(message.data, `stubbed ${originalMessage}`);
173 | done();
174 |
175 | };
176 | worker.postMessage(originalMessage);
177 |
178 | });
179 |
180 | QUnit.test('replaces the specified script with the specified code and imports before it executes', function(assert) {
181 |
182 | WorkerBox.setup();
183 | WorkerBox.stub('/tests/fixtures/simple-worker.js', {
184 | importScripts: ['/tests/fixtures/define-env.js'],
185 | code() {
186 |
187 | self.onmessage = function onmessage() {
188 |
189 | postMessage(self.env);
190 |
191 | };
192 |
193 | },
194 | });
195 |
196 | const done = assert.async();
197 | const originalMessage = 'foo';
198 | const worker = new Worker('/tests/fixtures/simple-worker.js');
199 | worker.onmessage = (message) => {
200 |
201 | assert.deepEqual(message.data, { from: 'define-env' });
202 | done();
203 |
204 | };
205 | worker.postMessage(originalMessage);
206 |
207 | });
208 |
209 | QUnit.test('throws an error if script has already been registered', function(assert) {
210 |
211 | WorkerBox.setup();
212 | WorkerBox.stub('/tests/fixtures/simple-worker.js');
213 | assert.throws(() => WorkerBox.stub('/tests/fixtures/simple-worker.js'), /The Worker script "\/tests\/fixtures\/simple-worker.js" has already been registered with "stub"/);
214 |
215 | });
216 |
217 | QUnit.test('throws an error if script has already been registered with a different relative path', function(assert) {
218 |
219 | WorkerBox.setup();
220 | WorkerBox.stub('/tests/fixtures/simple-worker.js');
221 | assert.throws(() => WorkerBox.stub('../../tests/fixtures/simple-worker.js'), /The Worker script "..\/..\/tests\/fixtures\/simple-worker.js" has already been registered with "stub"/);
222 |
223 | });
224 |
225 | QUnit.test('imported scripts are resolved relative to the current path', function(assert) {
226 |
227 | WorkerBox.setup();
228 | WorkerBox.stub('/tests/fixtures/simple-worker.js', {
229 | importScripts: ['../../tests/fixtures/define-env.js'],
230 | code() {
231 |
232 | self.importScripts('../../tests/fixtures/define-env-2.js');
233 | self.onmessage = function onmessage() {
234 |
235 | postMessage(self.env);
236 |
237 | };
238 |
239 | },
240 | });
241 |
242 | const done = assert.async();
243 | const originalMessage = 'foo';
244 | const worker = new Worker('/tests/fixtures/simple-worker.js');
245 | worker.onmessage = (message) => {
246 |
247 | assert.deepEqual(message.data, {
248 | from: 'define-env',
249 | again: 'define-env-2',
250 | });
251 | done();
252 |
253 | };
254 | worker.postMessage(originalMessage);
255 |
256 | });
257 |
258 | });
259 |
260 | QUnit.module('prepend', function() {
261 |
262 | QUnit.test('prepends the specified code to the specified script', function(assert) {
263 |
264 | WorkerBox.setup();
265 | WorkerBox.prepend('/tests/fixtures/environment-worker.js', {
266 | code() {
267 |
268 | self.env = 'derp;herp';
269 |
270 | },
271 | });
272 |
273 | const done = assert.async();
274 | const originalMessage = 'foo';
275 | const worker = new Worker('/tests/fixtures/environment-worker.js');
276 | worker.onmessage = (message) => {
277 |
278 | assert.deepEqual(message.data, {
279 | message: originalMessage,
280 | environment: 'derp;herp',
281 | });
282 | worker.terminate();
283 | done();
284 |
285 | };
286 | worker.postMessage(originalMessage);
287 |
288 | });
289 |
290 | QUnit.test('prepends the specified imports to the specified script', function(assert) {
291 |
292 | WorkerBox.setup();
293 | WorkerBox.prepend('/tests/fixtures/environment-worker.js', {
294 | importScripts: ['/tests/fixtures/define-env.js'],
295 | });
296 |
297 | const done = assert.async();
298 | const originalMessage = 'foo';
299 | const worker = new Worker('/tests/fixtures/environment-worker.js');
300 | worker.onmessage = (message) => {
301 |
302 | assert.deepEqual(message.data, {
303 | message: originalMessage,
304 | environment: {
305 | from: 'define-env',
306 | },
307 | });
308 | worker.terminate();
309 | done();
310 |
311 | };
312 | worker.postMessage(originalMessage);
313 |
314 | });
315 |
316 | QUnit.test('prepends the specified code and imports to the specified script', function(assert) {
317 |
318 | WorkerBox.setup();
319 | WorkerBox.prepend('/tests/fixtures/environment-worker.js', {
320 | importScripts: ['/tests/fixtures/define-env.js'],
321 | code() {
322 |
323 | self.env = Object.assign(self.env, { prepend: 'derp;herp' });
324 |
325 | },
326 | });
327 |
328 | const done = assert.async();
329 | const originalMessage = 'foo';
330 | const worker = new Worker('/tests/fixtures/environment-worker.js');
331 | worker.onmessage = (message) => {
332 |
333 | assert.deepEqual(message.data, {
334 | message: originalMessage,
335 | environment: {
336 | from: 'define-env',
337 | prepend: 'derp;herp',
338 | },
339 | });
340 | worker.terminate();
341 | done();
342 |
343 | };
344 | worker.postMessage(originalMessage);
345 |
346 | });
347 |
348 | QUnit.test('throws an error if script has already been registered', function(assert) {
349 |
350 | WorkerBox.setup();
351 | WorkerBox.prepend('/tests/fixtures/simple-worker.js');
352 | assert.throws(() => WorkerBox.prepend('/tests/fixtures/simple-worker.js'), /The Worker script "\/tests\/fixtures\/simple-worker.js" has already been registered with "prepend"/);
353 |
354 | });
355 |
356 | QUnit.test('throws an error if script has already been registered with a different relative path', function(assert) {
357 |
358 | WorkerBox.setup();
359 | WorkerBox.prepend('/tests/fixtures/simple-worker.js');
360 | assert.throws(() => WorkerBox.prepend('../../tests/fixtures/simple-worker.js'), /The Worker script "..\/..\/tests\/fixtures\/simple-worker.js" has already been registered with "prepend"/);
361 |
362 | });
363 |
364 | QUnit.test('imported scripts are resolved relative to the current path', function(assert) {
365 |
366 | WorkerBox.setup();
367 | WorkerBox.prepend('/tests/fixtures/environment-worker.js', {
368 | importScripts: ['../../tests/fixtures/define-env.js'],
369 | code() {
370 |
371 | self.importScripts('../../tests/fixtures/define-env-2.js');
372 |
373 | },
374 | });
375 |
376 | const done = assert.async();
377 | const originalMessage = 'foo';
378 | const worker = new Worker('/tests/fixtures/environment-worker.js');
379 | worker.onmessage = (message) => {
380 |
381 | assert.deepEqual(message.data, {
382 | message: originalMessage,
383 | environment: {
384 | from: 'define-env',
385 | again: 'define-env-2',
386 | },
387 | });
388 | worker.terminate();
389 | done();
390 |
391 | };
392 | worker.postMessage(originalMessage);
393 |
394 | });
395 |
396 | QUnit.test('imported scripts within original worker are resolved relative to the worker\'s path', function(assert) {
397 |
398 | WorkerBox.setup();
399 | WorkerBox.prepend('/tests/fixtures/import-worker.js');
400 |
401 | const done = assert.async();
402 | const originalMessage = 'foo';
403 | const worker = new Worker('/tests/fixtures/import-worker.js');
404 | worker.onmessage = (message) => {
405 |
406 | assert.deepEqual(message.data, {
407 | message: originalMessage,
408 | environment: {
409 | from: 'define-env',
410 | },
411 | });
412 | worker.terminate();
413 | done();
414 |
415 | };
416 | worker.postMessage(originalMessage);
417 |
418 | });
419 |
420 | });
421 |
422 | QUnit.module('unregister', function() {
423 |
424 | QUnit.test('allows you to re-prepend a worker', function(assert) {
425 |
426 | WorkerBox.setup();
427 |
428 | WorkerBox.prepend('/tests/fixtures/simple-worker.js');
429 | assert.throws(() => WorkerBox.prepend('/tests/fixtures/simple-worker.js'), /The Worker script "\/tests\/fixtures\/simple-worker.js" has already been registered with "prepend"/);
430 |
431 | WorkerBox.unregister('/tests/fixtures/simple-worker.js');
432 | WorkerBox.prepend('/tests/fixtures/simple-worker.js');
433 |
434 | });
435 |
436 | QUnit.test('allows you to re-stub a worker', function(assert) {
437 |
438 | WorkerBox.setup();
439 |
440 | WorkerBox.stub('/tests/fixtures/simple-worker.js');
441 | assert.throws(() => WorkerBox.stub('/tests/fixtures/simple-worker.js'), /The Worker script "\/tests\/fixtures\/simple-worker.js" has already been registered with "stub"/);
442 |
443 | WorkerBox.unregister('/tests/fixtures/simple-worker.js');
444 | WorkerBox.stub('/tests/fixtures/simple-worker.js');
445 |
446 | });
447 |
448 | QUnit.test('works with different relative paths', function(assert) {
449 |
450 | WorkerBox.setup();
451 |
452 | WorkerBox.stub('/tests/fixtures/simple-worker.js');
453 | assert.throws(() => WorkerBox.stub('/tests/fixtures/simple-worker.js'), /The Worker script "\/tests\/fixtures\/simple-worker.js" has already been registered with "stub"/);
454 |
455 | WorkerBox.unregister('../../tests/fixtures/simple-worker.js');
456 | WorkerBox.stub('/tests/fixtures/simple-worker.js');
457 |
458 | });
459 |
460 | });
461 |
462 | });
463 |
--------------------------------------------------------------------------------