Skip to content

Commit

Permalink
Merge branch 'master' into ts-jest-core
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Feb 28, 2019
2 parents 6110e0b + de52b48 commit 75a28e6
Show file tree
Hide file tree
Showing 27 changed files with 383 additions and 172 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,8 @@
- `[expect]`: Improve report when matcher fails, part 10 ([#7960](https://github.com/facebook/jest/pull/7960))
- `[pretty-format]` Support `React.memo` ([#7891](https://github.com/facebook/jest/pull/7891))
- `[jest-config]` Print error information on preset normalization error ([#7935](https://github.com/facebook/jest/pull/7935))
- `[jest-haste-map]` Add `skipPackageJson` option ([#7778](https://github.com/facebook/jest/pull/7778))
- `[jest-get-type]` Add `isPrimitive` function ([#7708](https://github.com/facebook/jest/pull/7708))

### Fixes

Expand All @@ -22,10 +24,14 @@
- `[jest-transform]` Normalize config and remove unecessary checks, convert `TestUtils.js` to TypeScript ([#7801](https://github.com/facebook/jest/pull/7801))
- `[jest-worker]` Fix `jest-worker` when using pre-allocated jobs ([#7934](https://github.com/facebook/jest/pull/7934))
- `[jest-changed-files]` Fix `getChangedFilesFromRoots` to not return parts of the commit messages as if they were files, when the commit messages contained multiple paragraphs ([#7961](https://github.com/facebook/jest/pull/7961))
- `[jest-haste-map]` Enforce uniqueness in names (mocks and haste ids) ([#8002](https://github.com/facebook/jest/pull/8002))
- `[static]` Remove console log '-' on the front page
- `[jest-jasmine2]`: Throw explicit error when errors happen after test is considered complete ([#8005](https://github.com/facebook/jest/pull/8005))
- `[jest-circus]`: Throw explicit error when errors happen after test is considered complete ([#8005](https://github.com/facebook/jest/pull/8005))

### Chore & Maintenance

- `[jest-environment-jsdom]`: Migrate to TypeScript ([#7985](https://github.com/facebook/jest/pull/8003))
- `[jest-environment-node]`: Migrate to TypeScript ([#7985](https://github.com/facebook/jest/pull/7985))
- `[*]`: Setup building, linting and testing of TypeScript ([#7808](https://github.com/facebook/jest/pull/7808), [#7855](https://github.com/facebook/jest/pull/7855), [#7951](https://github.com/facebook/jest/pull/7951))
- `[pretty-format]`: Migrate to TypeScript ([#7809](https://github.com/facebook/jest/pull/7809), [#7809](https://github.com/facebook/jest/pull/7972))
Expand Down Expand Up @@ -62,6 +68,7 @@
- `[jest-runner]`: Migrate to TypeScript ([#7968](https://github.com/facebook/jest/pull/7968))
- `[jest-runtime]`: Migrate to TypeScript ([#7964](https://github.com/facebook/jest/pull/7964), [#7988](https://github.com/facebook/jest/pull/7988))
- `[@jest/fake-timers]`: Extract FakeTimers class from `jest-util` into a new separate package ([#7987](https://github.com/facebook/jest/pull/7987))
- `[jest-repl]`: Migrate to TypeScript ([#8000](https://github.com/facebook/jest/pull/8000))
- `[@jest/core]`: Migrate to TypeScript ([#7998](https://github.com/facebook/jest/pull/7998))

### Performance
Expand Down Expand Up @@ -93,6 +100,7 @@
- `[jest-runtime]` Exclude setup/teardown files from coverage report ([#7790](https://github.com/facebook/jest/pull/7790)
- `[babel-jest]` Throw an error if `babel-jest` tries to transform a file ignored by Babel ([#7797](https://github.com/facebook/jest/pull/7797))
- `[babel-plugin-jest-hoist]` Ignore TS type references when looking for out-of-scope references ([#7799](https://github.com/facebook/jest/pull/7799)
- `[expect]` fixed asymmetrical equality of cyclic objects ([#7730](https://github.com/facebook/jest/pull/7730))

### Chore & Maintenance

Expand Down
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
13 changes: 11 additions & 2 deletions e2e/__tests__/failures.test.ts
Expand Up @@ -12,9 +12,9 @@ import runJest from '../runJest';

const dir = path.resolve(__dirname, '../failures');

const normalizeDots = text => text.replace(/\.{1,}$/gm, '.');
const normalizeDots = (text: string) => text.replace(/\.{1,}$/gm, '.');

function cleanStderr(stderr) {
function cleanStderr(stderr: string) {
const {rest} = extractSummary(stderr);
return rest
.replace(/.*(jest-jasmine2|jest-circus).*\n/g, '')
Expand Down Expand Up @@ -182,3 +182,12 @@ test('works with named snapshot failures', () => {
wrap(result.substring(0, result.indexOf('Snapshot Summary'))),
).toMatchSnapshot();
});

test('errors after test has completed', () => {
const {stderr} = runJest(dir, ['errorAfterTestComplete.test.js']);

expect(stderr).toMatch(
/Error: Caught error after test environment was torn down/,
);
expect(stderr).toMatch(/Failed: "fail async"/);
});
14 changes: 14 additions & 0 deletions e2e/failures/__tests__/errorAfterTestComplete.test.js
@@ -0,0 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails oncall+jsinfra
*/
'use strict';

test('a failing test', done => {
setTimeout(() => done('fail async'), 5);
done();
});
53 changes: 53 additions & 0 deletions packages/expect/src/__tests__/matchers.test.js
Expand Up @@ -606,6 +606,59 @@ describe('.toEqual()', () => {
});
expect(actual).toEqual({x: 3});
});

describe('cyclic object equality', () => {
test('properties with the same circularity are equal', () => {
const a = {};
a.x = a;
const b = {};
b.x = b;
expect(a).toEqual(b);
expect(b).toEqual(a);

const c = {};
c.x = a;
const d = {};
d.x = b;
expect(c).toEqual(d);
expect(d).toEqual(c);
});

test('properties with different circularity are not equal', () => {
const a = {};
a.x = {y: a};
const b = {};
const bx = {};
b.x = bx;
bx.y = bx;
expect(a).not.toEqual(b);
expect(b).not.toEqual(a);

const c = {};
c.x = a;
const d = {};
d.x = b;
expect(c).not.toEqual(d);
expect(d).not.toEqual(c);
});

test('are not equal if circularity is not on the same property', () => {
const a = {};
const b = {};
a.a = a;
b.a = {};
b.a.a = a;
expect(a).not.toEqual(b);
expect(b).not.toEqual(a);

const c = {};
c.x = {x: c};
const d = {};
d.x = d;
expect(c).not.toEqual(d);
expect(d).not.toEqual(c);
});
});
});

describe('.toBeInstanceOf()', () => {
Expand Down
17 changes: 10 additions & 7 deletions packages/expect/src/jasmineUtils.ts
Expand Up @@ -64,9 +64,9 @@ function asymmetricMatch(a: any, b: any) {
function eq(
a: any,
b: any,
aStack: any,
bStack: any,
customTesters: any,
aStack: Array<unknown>,
bStack: Array<unknown>,
customTesters: Array<Tester>,
hasKey: any,
): boolean {
var result = true;
Expand Down Expand Up @@ -149,14 +149,17 @@ function eq(
return false;
}

// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Used to detect circular references.
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] == a) {
return bStack[length] == b;
// circular references at same depth are equal
// circular reference is not equal to non-circular one
if (aStack[length] === a) {
return bStack[length] === b;
} else if (bStack[length] === b) {
return false;
}
}
// Add the first object to the stack of traversed objects.
Expand Down
30 changes: 21 additions & 9 deletions packages/jest-circus/src/utils.ts
Expand Up @@ -153,12 +153,17 @@ const _makeTimeoutMessage = (timeout: number, isHook: boolean) =>
// the original values in the variables before we require any files.
const {setTimeout, clearTimeout} = global;

function checkIsError(error: any): error is Error {
return !!(error && (error as Error).message && (error as Error).stack);
}

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

return new Promise((resolve, reject) => {
timeoutID = setTimeout(
Expand All @@ -170,15 +175,20 @@ export const callAsyncCircusFn = (
// soon as `done` called.
if (fn.length) {
const done = (reason?: Error | string): void => {
const isError =
reason && (reason as Error).message && (reason as Error).stack;
return reason
? reject(
isError
? reason
: new Error(`Failed: ${prettyFormat(reason, {maxDepth: 3})}`),
)
: resolve();
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 fn.call(testContext, done);
Expand Down Expand Up @@ -221,12 +231,14 @@ export const callAsyncCircusFn = (
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;
Expand Down
6 changes: 3 additions & 3 deletions packages/jest-config/tsconfig.json
Expand Up @@ -4,10 +4,10 @@
"rootDir": "src",
"outDir": "build"
},
// TODO: This is missing `jest-validate`, in addition to
// `jest-environment-jsdom` and `jest-jasmine2`, but those are just
// `require.resolve`d, so no real use for their types
// TODO: This is missing `jest-validate`, in addition to and `jest-jasmine2`,
// but those are just `require.resolve`d, so no real use for their types
"references": [
{"path": "../jest-environment-jsdom"},
{"path": "../jest-environment-node"},
{"path": "../jest-get-type"},
{"path": "../jest-regex-util"},
Expand Down
14 changes: 3 additions & 11 deletions packages/jest-each/src/bind.js
Expand Up @@ -10,7 +10,7 @@
import util from 'util';
import chalk from 'chalk';
import pretty from 'pretty-format';
import getType from 'jest-get-type';
import {isPrimitive} from 'jest-get-type';
import {ErrorWithStack} from 'jest-util';

type Table = Array<Array<any>>;
Expand All @@ -24,13 +24,6 @@ const RECEIVED_COLOR = chalk.red;
const SUPPORTED_PLACEHOLDERS = /%[sdifjoOp%]/g;
const PRETTY_PLACEHOLDER = '%p';
const INDEX_PLACEHOLDER = '%#';
const PRIMITIVES = new Set([
'string',
'number',
'boolean',
'null',
'undefined',
]);

export default (cb: Function, supportsDone: boolean = true) => (...args: any) =>
function eachBind(title: string, test: Function, timeout: number): void {
Expand Down Expand Up @@ -203,10 +196,9 @@ const getMatchingKeyPaths = title => (matches, key) =>
const replaceKeyPathWithValue = data => (title, match) => {
const keyPath = match.replace('$', '').split('.');
const value = getPath(data, keyPath);
const valueType = getType(value);

if (PRIMITIVES.has(valueType)) {
return title.replace(match, value);
if (isPrimitive(value)) {
return title.replace(match, String(value));
}
return title.replace(match, pretty(value, {maxDepth: 1, min: true}));
};
Expand Down
5 changes: 4 additions & 1 deletion packages/jest-environment-jsdom/package.json
Expand Up @@ -8,13 +8,16 @@
},
"license": "MIT",
"main": "build/index.js",
"types": "build/index.d.ts",
"dependencies": {
"@jest/environment": "^24.1.0",
"@jest/fake-timers": "^24.1.0",
"@jest/types": "^24.1.0",
"jest-mock": "^24.0.0",
"jest-util": "^24.0.0",
"jsdom": "^11.5.1"
},
"devDependencies": {
"devDependencies": {
"@types/jsdom": "^11.12.0"
},
"engines": {
Expand Down
Expand Up @@ -8,24 +8,27 @@

const vm = jest.requireActual('vm');

const JSDOMEnvironment = jest.genMockFromModule('../index');
const JSDOMEnvironment = jest.genMockFromModule('../index') as jest.Mock;

JSDOMEnvironment.mockImplementation(function(config) {
// @ts-ignore
this.global = {
JSON,
console: {},
};

const globalValues = {...config.globals};
for (const customGlobalKey in globalValues) {
// @ts-ignore
this.global[customGlobalKey] = globalValues[customGlobalKey];
}
});

JSDOMEnvironment.prototype.runSourceText.mockImplementation(function(
sourceText,
filename,
sourceText: string,
filename: string,
) {
// @ts-ignore
return vm.runInNewContext(sourceText, this.global, {
displayErrors: false,
filename,
Expand Down

0 comments on commit 75a28e6

Please sign in to comment.