From 5161720a155f9561884d3b4e4e48e8e9e34ff704 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 28 Oct 2017 20:22:45 +0200 Subject: [PATCH 1/6] Add `testLocationInResults` option Fixes #4775 --- CHANGELOG.md | 1 + docs/CLI.md | 13 ++++++++ .../__tests__/location_in_results.test.js | 33 +++++++++++++++++++ .../location_in_results/__tests__/test.js | 17 ++++++++++ .../location_in_results/package.json | 5 +++ packages/jest-cli/src/cli/args.js | 5 +++ packages/jest-config/src/defaults.js | 1 + packages/jest-config/src/index.js | 1 + packages/jest-config/src/normalize.js | 1 + packages/jest-config/src/valid_config.js | 1 + packages/jest-jasmine2/package.json | 1 + packages/jest-jasmine2/src/index.js | 13 ++++++++ packages/jest-jasmine2/src/reporter.js | 9 +++++ packages/jest-util/src/format_test_results.js | 1 + test_utils.js | 1 + types/Config.js | 3 ++ types/TestResult.js | 7 ++++ 17 files changed, 113 insertions(+) create mode 100644 integration_tests/__tests__/location_in_results.test.js create mode 100644 integration_tests/location_in_results/__tests__/test.js create mode 100644 integration_tests/location_in_results/package.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 013b611055fe..388812dd9532 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ * `[jest-runtime]` Support sourcemaps in transformers ([#3458](https://github.com/facebook/jest/pull/3458)) * `[jest-snapshot]` Add a serializer for `jest.fn` to allow a snapshot of a jest mock ([#4668](https://github.com/facebook/jest/pull/4668)) * `[jest-worker]` Initial version of parallel worker abstraction, say hello! ([#4497](https://github.com/facebook/jest/pull/4497)) +* `[jest-jasmine2]` Add `testLocationInResults` flag to add location information per spec to test results (TBD) ### Chore & Maintenance * `[*]` [**BREAKING**] Drop support for Node.js version 4 diff --git a/docs/CLI.md b/docs/CLI.md index f8c954ddf83a..716948ee24d8 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -189,6 +189,19 @@ Prevent tests from printing messages through the console. Alias: `-t`. Run only tests and test suites with a name that matches the regex. For example, suppose you want to run only tests related to authorization which will have names like `"GET /api/posts with auth"`, then you can use `jest -t=auth`. +### `--testLocationInResults` + +Adds a `location` field to test results. Useful if you want to report the location of a test in a reporter. + +Note that `column` is 0-indexed while `line` is not. + +```json +{ + "column": 4, + "line": 5 +} +``` + ### `--testPathPattern=` A regexp pattern string that is matched against all tests paths before executing the test. diff --git a/integration_tests/__tests__/location_in_results.test.js b/integration_tests/__tests__/location_in_results.test.js new file mode 100644 index 000000000000..d4903234a669 --- /dev/null +++ b/integration_tests/__tests__/location_in_results.test.js @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. 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. + * + * @flow + */ +'use strict'; + +const runJest = require('../runJest'); + +it('defaults to null for location', () => { + const result = runJest.json('location_in_results').json; + + const assertions = result.testResults[0].assertionResults; + expect(result.success).toBe(true); + expect(result.numTotalTests).toBe(2); + expect(assertions[0].location).toBeNull(); + expect(assertions[1].location).toBeNull(); +}); + +it('adds correct location info when provided with flag', () => { + const result = runJest.json('location_in_results', [ + '--testLocationInResults', + ]).json; + + const assertions = result.testResults[0].assertionResults; + expect(result.success).toBe(true); + expect(result.numTotalTests).toBe(2); + expect(assertions[0].location).toEqual({column: 1, line: 9}); + expect(assertions[1].location).toEqual({column: 3, line: 14}); +}); diff --git a/integration_tests/location_in_results/__tests__/test.js b/integration_tests/location_in_results/__tests__/test.js new file mode 100644 index 000000000000..55c08de1379c --- /dev/null +++ b/integration_tests/location_in_results/__tests__/test.js @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. 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. + */ +'use strict'; + +it('no ancestors', () => { + expect(true).toBeTruthy(); +}); + +describe('nested', () => { + it('also works', () => { + expect(true).toBeTruthy(); + }); +}); diff --git a/integration_tests/location_in_results/package.json b/integration_tests/location_in_results/package.json new file mode 100644 index 000000000000..148788b25446 --- /dev/null +++ b/integration_tests/location_in_results/package.json @@ -0,0 +1,5 @@ +{ + "jest": { + "testEnvironment": "node" + } +} diff --git a/packages/jest-cli/src/cli/args.js b/packages/jest-cli/src/cli/args.js index 018b7cbd619d..8bb204f23872 100644 --- a/packages/jest-cli/src/cli/args.js +++ b/packages/jest-cli/src/cli/args.js @@ -451,6 +451,11 @@ export const options = { description: 'Exit code of `jest` command if the test run failed', type: 'string', // number }, + testLocationInResults: { + default: false, + description: 'Add `location` information the the test results', + type: 'boolean', + }, testMatch: { description: 'The glob patterns Jest uses to detect test files.', type: 'array', diff --git a/packages/jest-config/src/defaults.js b/packages/jest-config/src/defaults.js index ddf03c198094..2f35093d98ec 100644 --- a/packages/jest-config/src/defaults.js +++ b/packages/jest-config/src/defaults.js @@ -56,6 +56,7 @@ export default ({ snapshotSerializers: [], testEnvironment: 'jest-environment-jsdom', testFailureExitCode: 1, + testLocationInResults: false, testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)(spec|test).js?(x)'], testPathIgnorePatterns: [NODE_MODULES_REGEXP], testRegex: '', diff --git a/packages/jest-config/src/index.js b/packages/jest-config/src/index.js index 5f75a03a233d..c90124aba4cd 100644 --- a/packages/jest-config/src/index.js +++ b/packages/jest-config/src/index.js @@ -143,6 +143,7 @@ const getConfigs = ( skipNodeResolution: options.skipNodeResolution, snapshotSerializers: options.snapshotSerializers, testEnvironment: options.testEnvironment, + testLocationInResults: options.testLocationInResults, testMatch: options.testMatch, testPathIgnorePatterns: options.testPathIgnorePatterns, testRegex: options.testRegex, diff --git a/packages/jest-config/src/normalize.js b/packages/jest-config/src/normalize.js index f12e7d20e9c1..65e6b3304f8d 100644 --- a/packages/jest-config/src/normalize.js +++ b/packages/jest-config/src/normalize.js @@ -480,6 +480,7 @@ export default function normalize(options: InitialOptions, argv: Argv) { case 'skipNodeResolution': case 'testEnvironment': case 'testFailureExitCode': + case 'testLocationInResults': case 'testNamePattern': case 'testRegex': case 'testURL': diff --git a/packages/jest-config/src/valid_config.js b/packages/jest-config/src/valid_config.js index 8652041494bf..c0f8b924916f 100644 --- a/packages/jest-config/src/valid_config.js +++ b/packages/jest-config/src/valid_config.js @@ -78,6 +78,7 @@ export default ({ snapshotSerializers: ['my-serializer-module'], testEnvironment: 'jest-environment-jsdom', testFailureExitCode: 1, + testLocationInResults: false, testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)(spec|test).js?(x)'], testNamePattern: 'test signature', testPathIgnorePatterns: [NODE_MODULES_REGEXP], diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index 9dba0d52e551..317b9d22e646 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -8,6 +8,7 @@ "license": "MIT", "main": "build/index.js", "dependencies": { + "callsites": "^2.0.0", "chalk": "^2.0.1", "expect": "^21.2.1", "graceful-fs": "^4.1.11", diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 2c070a7886d0..eb2e146c03e8 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -16,6 +16,7 @@ import type Runtime from 'jest-runtime'; import path from 'path'; import fs from 'fs'; +import callsites from 'callsites'; import JasmineReporter from './reporter'; import {install as jasmineAsyncInstall} from './jasmine_async'; @@ -44,6 +45,18 @@ async function jasmine2( Object.assign(environment.global, jasmineInterface); env.addReporter(jasmineInterface.jsApiReporter); + if (config.testLocationInResults === true) { + const originalIt = environment.global.it; + environment.global.it = (...args) => { + const stack = callsites()[1]; + const it = originalIt(...args); + + it.result.__callsite = stack; + + return it; + }; + } + jasmineAsyncInstall(environment.global); environment.global.test = environment.global.it; diff --git a/packages/jest-jasmine2/src/reporter.js b/packages/jest-jasmine2/src/reporter.js index 38b06e949f02..05ef55dc3d24 100644 --- a/packages/jest-jasmine2/src/reporter.js +++ b/packages/jest-jasmine2/src/reporter.js @@ -24,6 +24,7 @@ type Suite = { }; type SpecResult = { + __callsite?: Object, description: string, duration?: Milliseconds, failedExpectations: Array, @@ -150,11 +151,19 @@ export default class Jasmine2Reporter { const duration = start ? Date.now() - start : undefined; const status = specResult.status === 'disabled' ? 'pending' : specResult.status; + const location = specResult.__callsite + ? { + column: specResult.__callsite.getColumnNumber(), + // $FlowFixMe: https://github.com/facebook/flow/issues/5213 + line: specResult.__callsite.getLineNumber(), + } + : null; const results = { ancestorTitles, duration, failureMessages: [], fullName: specResult.fullName, + location, numPassingAsserts: 0, // Jasmine2 only returns an array of failed asserts. status, title: specResult.description, diff --git a/packages/jest-util/src/format_test_results.js b/packages/jest-util/src/format_test_results.js index bbb44737e33c..95c41c8a43e0 100644 --- a/packages/jest-util/src/format_test_results.js +++ b/packages/jest-util/src/format_test_results.js @@ -62,6 +62,7 @@ function formatTestAssertion( ancestorTitles: assertion.ancestorTitles, failureMessages: null, fullName: assertion.fullName, + location: assertion.location, status: assertion.status, title: assertion.title, }; diff --git a/test_utils.js b/test_utils.js index 53ad9e0acb99..e659422f3ca9 100644 --- a/test_utils.js +++ b/test_utils.js @@ -85,6 +85,7 @@ const DEFAULT_PROJECT_CONFIG: ProjectConfig = { skipNodeResolution: false, snapshotSerializers: [], testEnvironment: 'node', + testLocationInResults: false, testMatch: [], testPathIgnorePatterns: [], testRegex: '.test.js$', diff --git a/types/Config.js b/types/Config.js index c62d9449dea8..ed2a19cb950b 100644 --- a/types/Config.js +++ b/types/Config.js @@ -48,6 +48,7 @@ export type DefaultOptions = {| snapshotSerializers: Array, testEnvironment: string, testFailureExitCode: string | number, + testLocationInResults: boolean, testMatch: Array, testPathIgnorePatterns: Array, testRegex: string, @@ -119,6 +120,7 @@ export type InitialOptions = { snapshotSerializers?: Array, testEnvironment?: string, testFailureExitCode?: string | number, + testLocationInResults?: boolean, testMatch?: Array, testNamePattern?: string, testPathDirs?: Array, @@ -215,6 +217,7 @@ export type ProjectConfig = {| snapshotSerializers: Array, testEnvironment: string, testMatch: Array, + testLocationInResults: boolean, testPathIgnorePatterns: Array, testRegex: string, testRunner: string, diff --git a/types/TestResult.js b/types/TestResult.js index 00afe2747357..ccd568c0f402 100644 --- a/types/TestResult.js +++ b/types/TestResult.js @@ -83,11 +83,17 @@ export type Status = 'passed' | 'failed' | 'skipped' | 'pending'; export type Bytes = number; export type Milliseconds = number; +type Callsite = {| + column: number, + line: number, +|} + export type AssertionResult = {| ancestorTitles: Array, duration?: ?Milliseconds, failureMessages: Array, fullName: string, + location: ?Callsite, numPassingAsserts: number, status: Status, title: string, @@ -96,6 +102,7 @@ export type AssertionResult = {| export type FormattedAssertionResult = { failureMessages: Array | null, fullName: string, + location: ?Callsite, status: Status, title: string, }; From 4955e8aa2ef53cc6437142db4aff567b3072d3fb Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 28 Oct 2017 20:35:35 +0200 Subject: [PATCH 2/6] Update snapshot --- .../__tests__/__snapshots__/show_config.test.js.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/integration_tests/__tests__/__snapshots__/show_config.test.js.snap b/integration_tests/__tests__/__snapshots__/show_config.test.js.snap index 57d4aaf6dd63..224fad308596 100644 --- a/integration_tests/__tests__/__snapshots__/show_config.test.js.snap +++ b/integration_tests/__tests__/__snapshots__/show_config.test.js.snap @@ -38,6 +38,7 @@ exports[`--showConfig outputs config info and exits 1`] = ` \\"setupFiles\\": [], \\"snapshotSerializers\\": [], \\"testEnvironment\\": \\"jest-environment-jsdom\\", + \\"testLocationInResults\\": false, \\"testMatch\\": [ \\"**/__tests__/**/*.js?(x)\\", \\"**/?(*.)(spec|test).js?(x)\\" From 1c99973391cdc0916d7b64a54eb501a5f9fd0f91 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 28 Oct 2017 20:36:05 +0200 Subject: [PATCH 3/6] Update changelog with link to PR --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 388812dd9532..e147eb8cde03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,7 @@ * `[jest-runtime]` Support sourcemaps in transformers ([#3458](https://github.com/facebook/jest/pull/3458)) * `[jest-snapshot]` Add a serializer for `jest.fn` to allow a snapshot of a jest mock ([#4668](https://github.com/facebook/jest/pull/4668)) * `[jest-worker]` Initial version of parallel worker abstraction, say hello! ([#4497](https://github.com/facebook/jest/pull/4497)) -* `[jest-jasmine2]` Add `testLocationInResults` flag to add location information per spec to test results (TBD) +* `[jest-jasmine2]` Add `testLocationInResults` flag to add location information per spec to test results ([#4782](https://github.com/facebook/jest/pull/4782)) ### Chore & Maintenance * `[*]` [**BREAKING**] Drop support for Node.js version 4 From d0da55e2396ddd24b8381a71f2894bbe9c10df43 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 28 Oct 2017 20:36:48 +0200 Subject: [PATCH 4/6] Fix typo in docs --- packages/jest-cli/src/cli/args.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-cli/src/cli/args.js b/packages/jest-cli/src/cli/args.js index 8bb204f23872..3576edea56c0 100644 --- a/packages/jest-cli/src/cli/args.js +++ b/packages/jest-cli/src/cli/args.js @@ -453,7 +453,7 @@ export const options = { }, testLocationInResults: { default: false, - description: 'Add `location` information the the test results', + description: 'Add `location` information to the test results', type: 'boolean', }, testMatch: { From b743f7eb3617fe96f37281bebff4ceb7702ebea6 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 1 Nov 2017 21:19:40 +0100 Subject: [PATCH 5/6] Update Configuration.md --- docs/Configuration.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index 6c8e88d18ce4..d4f2adc8fb51 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -591,7 +591,11 @@ This option allows the use of a custom results processor. This processor must be "status": "failed" | "pending" | "passed", "ancestorTitles": [string (message in describe blocks)], "failureMessages": [string], - "numPassingAsserts": number + "numPassingAsserts": number, + "location": { + "column": number, + "line": number + } }, ... ], From 7cec947613d846f4e207dce61b137f7a863031c9 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Fri, 3 Nov 2017 19:13:52 +0100 Subject: [PATCH 6/6] Update index.js --- packages/jest-jasmine2/src/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index eb2e146c03e8..bd084ac2d9a9 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -45,6 +45,8 @@ async function jasmine2( Object.assign(environment.global, jasmineInterface); env.addReporter(jasmineInterface.jsApiReporter); + // TODO: Remove config option if V8 exposes some way of getting location of caller + // in a future version if (config.testLocationInResults === true) { const originalIt = environment.global.it; environment.global.it = (...args) => {