Skip to content

Commit

Permalink
refactor: cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
krisselden committed Jun 12, 2020
1 parent 8401859 commit 681b58b
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 57 deletions.
18 changes: 18 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,16 @@ module.exports = {
mocha: true,
es6: true,
},
parserOptions: {
project: "./tsconfig.json",
// allows eslint from any dir
tsconfigRootDir: __dirname + "/tests",
sourceType: "module",
},
files: ["tests/**/*.js"],
extends: [
"plugin:@typescript-eslint/recommended-requiring-type-checking",
],
rules: {
"no-undef": "off",
"@typescript-eslint/no-var-requires": "off",
Expand All @@ -72,6 +81,15 @@ module.exports = {
node: true,
es6: true,
},
parserOptions: {
project: "./tsconfig.json",
// allows eslint from any dir
tsconfigRootDir: __dirname + "/examples",
sourceType: "module",
},
extends: [
"plugin:@typescript-eslint/recommended-requiring-type-checking",
],
files: ["examples/**/*.js"],
rules: {
"@typescript-eslint/no-var-requires": "off",
Expand Down
4 changes: 2 additions & 2 deletions examples/ctrl-c.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const [raceCancellation, cancel] = cancellableRace();

process.on("SIGINT", cancel);

main();
void main();

/**
* Cancellable async main with graceful termination on cancel.
Expand All @@ -17,7 +17,7 @@ async function main() {
});
console.log(`main done: ${result}`);
} catch (e) {
console.error(e.stack);
console.error("%o", e);
// let node exit naturally
process.exitCode = 1;
} finally {
Expand Down
2 changes: 1 addition & 1 deletion tests/cancellableRaceTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe("cancellableRace", () => {
await raceCancellation(task);
assert.fail("expected failure");
} catch (e) {
assert.equal(e.message, "failed task");
assert.equal(e instanceof Error && e.message, "failed task");
}
});
});
16 changes: 9 additions & 7 deletions tests/combineRaceTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe("combineRace", () => {
const [step, steps] = createSteps();
const { runTest, cancelA, cancelB } = createTest(step);

const expected = new Date();
const expected = new Date().toString();
await runTest({
taskStart(deferred) {
deferred.resolve(expected);
Expand All @@ -52,7 +52,7 @@ describe("combineRace", () => {
const [step, steps] = createSteps();
const { runTest, cancelA, cancelB } = createTest(step);

const expected = new Date();
const expected = new Date().toString();
await runTest({
taskStart(deferred) {
deferred.reject(expected);
Expand Down Expand Up @@ -242,13 +242,15 @@ function createTest(step) {
step("begin await");
const res = await combinedRace(() => {
step("task started");
return new Promise((resolve, reject) => {
delegate.taskStart({ resolve, reject });
});
return /** @type {Promise<unknown>} */ (new Promise(
(resolve, reject) => {
delegate.taskStart({ resolve, reject });
}
));
});
step(`await returned: ${res}`);
step(`await returned: ${String(res)}`);
} catch (e) {
step(`await threw: ${e}`);
step(`await threw: ${String(e)}`);
}
}

Expand Down
10 changes: 6 additions & 4 deletions tests/disposablePromiseTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ const { disposablePromise } = require("./helper");
describe("disposablePromise", () => {
it("works without passing a raceCancellation arg", async () => {
const expected = new Date();
const actual = await disposablePromise((resolve) => {
resolve(expected);
return () => void 0;
});
const actual = await /** @type {Promise<unknown>} */ (disposablePromise(
(resolve) => {
resolve(expected);
return () => void 0;
}
));
assert.equal(actual, expected);
});
});
90 changes: 58 additions & 32 deletions tests/helper.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,79 @@
/** @type {import("race-cancellation")} */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */

/*
This helper module allows us to import from the module under test
while using the package conditional exports of "import" if supported
or falling back to package "main" if not supported.
Which lets us run the same test suite on both exports to ensure that
it works on Node < 12.17.0 or newer node using require or import.
*/

/** @type {{[prop: string]: unknown}} */
let raceCancellation;

async function loadModule() {
try {
return (raceCancellation = await import("race-cancellation"));
} catch {
} catch (e) {
const [major, minor] = process.versions.node.split(".", 2).map(Number);
if (major > 12 || (major === 12 && minor >= 17)) {
// modules were enabled by default version >= 12.17
// so if this failed there is a problem with the modules
// most likely something didn't include the .js on the
// import specifier.
throw e;
}
// fallback to require export
return (raceCancellation = require("race-cancellation"));
}
}

// load test module and register before hook to wait for it
const promise = loadModule();

before(() => promise);

/** @type {any} */
const proxy = new Proxy(promise, {
get(target, prop) {
const value = target[/** @type {keyof typeof target} */ (prop)];
if (typeof value === "function") {
return value.bind(target);
}
if (value !== undefined) {
// proxy through to promise of module
// mocha loadFilesAsync awaits module.exports
if (prop in target) {
const value = target[/** @type {keyof typeof target} */ (prop)];
if (typeof value === "function") {
// bind then, catch etc
return value.bind(target);
}
return value;
}
// if raceCancellation isn't loaded return a function
// that will invoke it when it is
if (raceCancellation === undefined) {
return (/** @type {any[]} */ ...args) => {
if (raceCancellation === undefined) {
throw new Error(`race-cancellation not loaded yet`);
}

if (prop in raceCancellation) {
/** @type {any} */
const fn =
raceCancellation[
/** @type {keyof typeof raceCancellation} */ (prop)
];
return fn(...args);
}
};
}
if (prop in raceCancellation) {
return raceCancellation[
/** @type {keyof typeof raceCancellation} */ (prop)
];
// if possible export name then proxy to module
if (typeof prop === "string") {
// if not loaded return a function that will call it when invoked
if (raceCancellation === undefined) {
return (/** @type {any[]} */ ...args) => {
if (raceCancellation === undefined) {
// the before hook should have run unless this was called
// outside of a test which isn't supported
throw new Error(
`race-cancellation not loaded yet, this function can only be inside of a test`
);
}
const fn = raceCancellation[prop];
if (typeof fn === "function") {
return fn(...args);
} else if (fn === undefined) {
throw new Error(`${prop} is not exported by race-cancellation`);
} else {
throw new Error(`${prop} is not a function`);
}
};
}
// if loaded just return its value
return raceCancellation[prop];
}
return value;
},
});

module.exports = /** @type {typeof import("race-cancellation")} */ (proxy);
// export proxy
module.exports = /** @type {import("race-cancellation")} */ (proxy);
10 changes: 5 additions & 5 deletions tests/withRaceSettledTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe("withRaceSettled", () => {
it("resolves with the result of the task", async () => {
const expected = { result: "result" };

const task = withRaceSettled(async () => expected);
const task = withRaceSettled(() => Promise.resolve(expected));

/** @type {unknown} */
const actual = await task();
Expand All @@ -20,14 +20,14 @@ describe("withRaceSettled", () => {
});

it("rejects if task function rejects", async () => {
const task = withRaceSettled(async () => {
const task = withRaceSettled(() => {
throw Error("some error");
});
try {
await task();
assert.ok(false, "did not reject with task error");
} catch (e) {
assert.equal(e.message, "some error");
assert.equal(e instanceof Error && e.message, "some error");
}
});

Expand All @@ -49,7 +49,7 @@ describe("withRaceSettled", () => {
);
step("subtask: unreachable");
} catch (e) {
step(`subtask: error: ${e}`);
step(`subtask: error: ${String(e)}`);
} finally {
step("subtask: finally");
}
Expand All @@ -69,7 +69,7 @@ describe("withRaceSettled", () => {
step(`await runTask`);
await task();
} catch (e) {
step(`error: ${e}`);
step(`error: ${String(e)}`);
}

// raceExit should finish out pending
Expand Down
12 changes: 6 additions & 6 deletions tests/withRaceTimeoutTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe("withRaceTimeout", () => {
const [step, steps] = createSteps();
const { runTest } = createTimeoutTest(step);

const expected = new Date();
const expected = new Date().toString();
await runTest({
taskStart({ resolve }) {
resolve(expected);
Expand All @@ -25,7 +25,7 @@ describe("withRaceTimeout", () => {
const [step, steps] = createSteps();
const { runTest } = createTimeoutTest(step);

const expected = new Date();
const expected = new Date().toString();
await runTest({
taskStart({ reject }) {
reject(expected);
Expand Down Expand Up @@ -124,13 +124,13 @@ function createTimeoutTest(step) {

step("begin await");
try {
const res = await withRaceTimeout(
const res = await /** @type {Promise<unknown>} */ (withRaceTimeout(
(innerRace) => innerRace(task),
10
)(raceCancellation);
step(`await returned: ${res}`);
)(raceCancellation));
step(`await returned: ${String(res)}`);
} catch (e) {
step(`await threw: ${e}`);
step(`await threw: ${String(e)}`);
}
}

Expand Down

0 comments on commit 681b58b

Please sign in to comment.