Add a real test!

This commit is contained in:
Timothy Farrell 2016-12-27 22:07:25 -06:00
parent 2034139846
commit 342c46df6f
3 changed files with 97 additions and 24 deletions

View File

@ -15,7 +15,8 @@
"build:umd:gzip":
"npm run build:umd:min && gzip -c9 dist/worker-portal.min.js > dist/worker-portal.min.js.gz",
"build": "npm run build:umd:gzip && ls -l dist/",
"prepublish": "npm run clean && npm run build"
"prepublish": "npm run clean && npm run build",
"test": "npm run build:lib && ava --verbose"
},
"repository": {
"type": "git",
@ -29,6 +30,7 @@
},
"homepage": "https://gitlab.com/explorigin/worker-portal",
"devDependencies": {
"ava": "^0.17.0",
"babel-cli": "6.18.0",
"babel-core": "6.21.0",
"babel-eslint": "7.1.1",

View File

@ -12,14 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
export function isWorker() {
try {
return self !== window;
} catch (e) {
return true;
}
}
function tryJSON(type, destination, id, data) {
const packet = [type, destination, id, data];
try {
@ -29,7 +21,7 @@ function tryJSON(type, destination, id, data) {
}
}
export function WorkerPortal(context, worker, serialize) {
export function WorkerPortal(context, worker, isSlave, serialize) {
const responseMap = new Map();
const _worker = worker || self;
const contextIndex = Object.keys(context);
@ -84,29 +76,25 @@ export function WorkerPortal(context, worker, serialize) {
}
function injectionPointFactory(fnId, callbackFactory) {
return () =>
new Promise((resolve, reject) => {
if (!enabled) {
return function(...args) {
return new Promise((resolve, reject) => {
if (!enabled && fnId !== 0) {
reject(new Error('Portal disabled'));
}
const id = callCount;
callCount += 1;
responseMap.set(id, [callbackFactory ? callbackFactory(resolve) : resolve, reject]);
post(0, id, fnId, Array.from(arguments));
post(0, id, fnId, args);
});
};
}
function resolveExternalInterfaceFactory(resolve) {
return linkedFunctionNames => {
return (linkedFunctionNames, ...rest) => {
const externalInterface = {};
linkedFunctionNames.forEach((fnName, index) => {
externalInterface[fnName] = injectionPointFactory(index);
});
if (!isWorker()) {
externalInterface._cleanup = injectionPointFactory(linkedFunctionNames.length, resolve =>
resolve(cleanup())
);
}
enabled = true;
resolve(externalInterface);
return contextIndex;
@ -125,13 +113,16 @@ export function WorkerPortal(context, worker, serialize) {
_worker.addEventListener('message', dispatcher);
if (isWorker()) {
if (isSlave) {
return new Promise(resolve => {
contextIndex.splice(0, 0, '__init', '__cleanup');
contextIndex.splice(0, 0, '__init', '__cleanupSlave');
context.__init = resolveExternalInterfaceFactory(resolve);
context.__cleanup = cleanup;
context.__cleanupSlave = cleanup;
});
}
return injectionPointFactory(0, resolveExternalInterfaceFactory)(contextIndex);
return injectionPointFactory(0, resolveExternalInterfaceFactory)(contextIndex).then(api => ({
...api,
_cleanup: injectionPointFactory(1, resolve => resolve(cleanup()))
}));
}

80
packages/portal/test.js Normal file
View File

@ -0,0 +1,80 @@
import test from 'ava';
import { WorkerPortal } from './lib';
function FakeWorkerPair() {
let cbA = null;
let cbB = null;
const objA = {
postMessage: data => {
cbB({ data: data });
},
addEventListener: (eventName, fn) => {
cbA = (...r) => {
fn(...r);
};
},
removeEventListener: (eventName, fn) => {
cbA = null;
}
};
const objB = {
postMessage: data => {
cbA({ data: data });
},
addEventListener: (eventName, fn) => {
cbB = (...r) => {
fn(...r);
};
},
removeEventListener: (eventName, fn) => {
cbB = null;
}
};
return [objA, objB];
}
test('Workers can call and respond equally', async t => {
const [a, b] = FakeWorkerPair();
const slave = WorkerPortal(
{
slaveAdd: (a, b) => a + b
},
a,
true
);
const master = WorkerPortal(
{
masterSubtract: (a, b) => a - b
},
b,
false
);
const masterApi = await master;
const slaveApi = await slave;
t.deepEqual(Object.keys(masterApi), ['__init', '__cleanupSlave', 'slaveAdd', '_cleanup']);
t.deepEqual(Object.keys(slaveApi), ['masterSubtract']);
t.is(await slaveApi.masterSubtract(9, 2), 7);
t.is(await masterApi.slaveAdd(9, 2), 11);
t.is(await masterApi.slaveAdd(5, 2), 7);
t.is(await slaveApi.masterSubtract(2, 2), 0);
await masterApi._cleanup();
return masterApi
.slaveAdd(9, 2)
.then(e => {
t.fail('Expected rejection');
})
.catch(e => {
t.is(e.message, 'Portal disabled');
});
});