Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: fix broken test in circus #8009

Merged
merged 1 commit into from Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/__tests__/detectOpenHandles.ts
Expand Up @@ -22,7 +22,7 @@ try {
}
}

function getTextAfterTest(stderr) {
function getTextAfterTest(stderr: string) {
return (stderr.split(/Ran all test suites(.*)\n/)[2] || '').trim();
}

Expand Down
133 changes: 68 additions & 65 deletions packages/jest-circus/src/utils.ts
Expand Up @@ -157,89 +157,92 @@ function checkIsError(error: any): error is Error {
return !!(error && (error as Error).message && (error as Error).stack);
}

export const callAsyncCircusFn = async (
export const callAsyncCircusFn = (
fn: AsyncFn,
testContext: TestContext | undefined,
{isHook, timeout}: {isHook?: boolean | null; timeout: number},
): Promise<any> => {
let timeoutID: NodeJS.Timeout | undefined;
let timeoutID: NodeJS.Timeout;
let completed = false;

try {
return await new Promise((resolve, reject) => {
timeoutID = setTimeout(
() => reject(_makeTimeoutMessage(timeout, !!isHook)),
timeout,
);

// If this fn accepts `done` callback we return a promise that fulfills as
// soon as `done` called.
if (fn.length) {
const done = (reason?: Error | string): void => {
const errorAsErrorObject = checkIsError(reason)
? reason
: new Error(`Failed: ${prettyFormat(reason, {maxDepth: 3})}`);

// Consider always throwing, regardless if `reason` is set or not
if (completed && reason) {
errorAsErrorObject.message =
'Caught error after test environment was torn down\n\n' +
errorAsErrorObject.message;

throw errorAsErrorObject;
}
return new Promise((resolve, reject) => {
timeoutID = setTimeout(
() => reject(_makeTimeoutMessage(timeout, !!isHook)),
timeout,
);

// If this fn accepts `done` callback we return a promise that fulfills as
// soon as `done` called.
if (fn.length) {
const done = (reason?: Error | string): void => {
const errorAsErrorObject = checkIsError(reason)
? reason
: new Error(`Failed: ${prettyFormat(reason, {maxDepth: 3})}`);

// Consider always throwing, regardless if `reason` is set or not
if (completed && reason) {
errorAsErrorObject.message =
'Caught error after test environment was torn down\n\n' +
errorAsErrorObject.message;

throw errorAsErrorObject;
}

return reason ? reject(errorAsErrorObject) : resolve();
};
return reason ? reject(errorAsErrorObject) : resolve();
};

return fn.call(testContext, done);
}
return fn.call(testContext, done);
}

let returnedValue;
if (isGeneratorFn(fn)) {
returnedValue = co.wrap(fn).call({});
} else {
try {
returnedValue = fn.call(testContext);
} catch (error) {
return reject(error);
}
let returnedValue;
if (isGeneratorFn(fn)) {
returnedValue = co.wrap(fn).call({});
} else {
try {
returnedValue = fn.call(testContext);
} catch (error) {
return reject(error);
}
}

// If it's a Promise, return it. Test for an object with a `then` function
// to support custom Promise implementations.
if (
typeof returnedValue === 'object' &&
returnedValue !== null &&
typeof returnedValue.then === 'function'
) {
return returnedValue.then(resolve, reject);
}
// If it's a Promise, return it. Test for an object with a `then` function
// to support custom Promise implementations.
if (
typeof returnedValue === 'object' &&
returnedValue !== null &&
typeof returnedValue.then === 'function'
) {
return returnedValue.then(resolve, reject);
}

if (!isHook && returnedValue !== void 0) {
return reject(
new Error(
`
if (!isHook && returnedValue !== void 0) {
return reject(
new Error(
`
test functions can only return Promise or undefined.
Returned value: ${String(returnedValue)}
`,
),
);
}
),
);
}

// Otherwise this test is synchronous, and if it didn't throw it means
// it passed.
return resolve();
});
} finally {
completed = true;
// If timeout is not cleared/unrefed the node process won't exit until
// it's resolved.
if (timeoutID) {
// Otherwise this test is synchronous, and if it didn't throw it means
// it passed.
return resolve();
})
.then(() => {
completed = true;
// If timeout is not cleared/unrefed the node process won't exit until
// it's resolved.
timeoutID.unref && timeoutID.unref();
clearTimeout(timeoutID);
}
}
})
.catch(error => {
completed = true;
timeoutID.unref && timeoutID.unref();
clearTimeout(timeoutID);
throw error;
});
};

export const getTestDuration = (test: TestEntry): number | null => {
Expand Down