aboutsummaryrefslogtreecommitdiff
path: root/node_modules/@jest/test-sequencer
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@jest/test-sequencer')
-rw-r--r--node_modules/@jest/test-sequencer/LICENSE21
-rw-r--r--node_modules/@jest/test-sequencer/build/index.d.ts51
-rw-r--r--node_modules/@jest/test-sequencer/build/index.js237
-rw-r--r--node_modules/@jest/test-sequencer/package.json35
4 files changed, 344 insertions, 0 deletions
diff --git a/node_modules/@jest/test-sequencer/LICENSE b/node_modules/@jest/test-sequencer/LICENSE
new file mode 100644
index 0000000..b96dcb0
--- /dev/null
+++ b/node_modules/@jest/test-sequencer/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Facebook, Inc. and its affiliates.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/@jest/test-sequencer/build/index.d.ts b/node_modules/@jest/test-sequencer/build/index.d.ts
new file mode 100644
index 0000000..7b48a2b
--- /dev/null
+++ b/node_modules/@jest/test-sequencer/build/index.d.ts
@@ -0,0 +1,51 @@
+/**
+ * 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.
+ */
+import type { AggregatedResult, Test } from '@jest/test-result';
+import type { Context } from 'jest-runtime';
+declare type Cache = {
+ [key: string]: [0 | 1, number];
+};
+/**
+ * The TestSequencer will ultimately decide which tests should run first.
+ * It is responsible for storing and reading from a local cache
+ * map that stores context information for a given test, such as how long it
+ * took to run during the last run and if it has failed or not.
+ * Such information is used on:
+ * TestSequencer.sort(tests: Array<Test>)
+ * to sort the order of the provided tests.
+ *
+ * After the results are collected,
+ * TestSequencer.cacheResults(tests: Array<Test>, results: AggregatedResult)
+ * is called to store/update this information on the cache map.
+ */
+export default class TestSequencer {
+ private _cache;
+ _getCachePath(context: Context): string;
+ _getCache(test: Test): Cache;
+ /**
+ * Sorting tests is very important because it has a great impact on the
+ * user-perceived responsiveness and speed of the test run.
+ *
+ * If such information is on cache, tests are sorted based on:
+ * -> Has it failed during the last run ?
+ * Since it's important to provide the most expected feedback as quickly
+ * as possible.
+ * -> How long it took to run ?
+ * Because running long tests first is an effort to minimize worker idle
+ * time at the end of a long test run.
+ * And if that information is not available they are sorted based on file size
+ * since big test files usually take longer to complete.
+ *
+ * Note that a possible improvement would be to analyse other information
+ * from the file other than its size.
+ *
+ */
+ sort(tests: Array<Test>): Array<Test>;
+ allFailedTests(tests: Array<Test>): Array<Test>;
+ cacheResults(tests: Array<Test>, results: AggregatedResult): void;
+}
+export {};
diff --git a/node_modules/@jest/test-sequencer/build/index.js b/node_modules/@jest/test-sequencer/build/index.js
new file mode 100644
index 0000000..29fd68c
--- /dev/null
+++ b/node_modules/@jest/test-sequencer/build/index.js
@@ -0,0 +1,237 @@
+'use strict';
+
+Object.defineProperty(exports, '__esModule', {
+ value: true
+});
+exports.default = void 0;
+
+function fs() {
+ const data = _interopRequireWildcard(require('graceful-fs'));
+
+ fs = function () {
+ return data;
+ };
+
+ return data;
+}
+
+function _jestHasteMap() {
+ const data = _interopRequireDefault(require('jest-haste-map'));
+
+ _jestHasteMap = function () {
+ return data;
+ };
+
+ return data;
+}
+
+function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {default: obj};
+}
+
+function _getRequireWildcardCache(nodeInterop) {
+ if (typeof WeakMap !== 'function') return null;
+ var cacheBabelInterop = new WeakMap();
+ var cacheNodeInterop = new WeakMap();
+ return (_getRequireWildcardCache = function (nodeInterop) {
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
+ })(nodeInterop);
+}
+
+function _interopRequireWildcard(obj, nodeInterop) {
+ if (!nodeInterop && obj && obj.__esModule) {
+ return obj;
+ }
+ if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
+ return {default: obj};
+ }
+ var cache = _getRequireWildcardCache(nodeInterop);
+ if (cache && cache.has(obj)) {
+ return cache.get(obj);
+ }
+ var newObj = {};
+ var hasPropertyDescriptor =
+ Object.defineProperty && Object.getOwnPropertyDescriptor;
+ for (var key in obj) {
+ if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
+ var desc = hasPropertyDescriptor
+ ? Object.getOwnPropertyDescriptor(obj, key)
+ : null;
+ if (desc && (desc.get || desc.set)) {
+ Object.defineProperty(newObj, key, desc);
+ } else {
+ newObj[key] = obj[key];
+ }
+ }
+ }
+ newObj.default = obj;
+ if (cache) {
+ cache.set(obj, newObj);
+ }
+ return newObj;
+}
+
+function _defineProperty(obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value: value,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ } else {
+ obj[key] = value;
+ }
+ return obj;
+}
+
+const FAIL = 0;
+const SUCCESS = 1;
+
+/**
+ * The TestSequencer will ultimately decide which tests should run first.
+ * It is responsible for storing and reading from a local cache
+ * map that stores context information for a given test, such as how long it
+ * took to run during the last run and if it has failed or not.
+ * Such information is used on:
+ * TestSequencer.sort(tests: Array<Test>)
+ * to sort the order of the provided tests.
+ *
+ * After the results are collected,
+ * TestSequencer.cacheResults(tests: Array<Test>, results: AggregatedResult)
+ * is called to store/update this information on the cache map.
+ */
+class TestSequencer {
+ constructor() {
+ _defineProperty(this, '_cache', new Map());
+ }
+
+ _getCachePath(context) {
+ const {config} = context;
+
+ const HasteMapClass = _jestHasteMap().default.getStatic(config);
+
+ return HasteMapClass.getCacheFilePath(
+ config.cacheDirectory,
+ 'perf-cache-' + config.name
+ );
+ }
+
+ _getCache(test) {
+ const {context} = test;
+
+ if (!this._cache.has(context) && context.config.cache) {
+ const cachePath = this._getCachePath(context);
+
+ if (fs().existsSync(cachePath)) {
+ try {
+ this._cache.set(
+ context,
+ JSON.parse(fs().readFileSync(cachePath, 'utf8'))
+ );
+ } catch {}
+ }
+ }
+
+ let cache = this._cache.get(context);
+
+ if (!cache) {
+ cache = {};
+
+ this._cache.set(context, cache);
+ }
+
+ return cache;
+ }
+ /**
+ * Sorting tests is very important because it has a great impact on the
+ * user-perceived responsiveness and speed of the test run.
+ *
+ * If such information is on cache, tests are sorted based on:
+ * -> Has it failed during the last run ?
+ * Since it's important to provide the most expected feedback as quickly
+ * as possible.
+ * -> How long it took to run ?
+ * Because running long tests first is an effort to minimize worker idle
+ * time at the end of a long test run.
+ * And if that information is not available they are sorted based on file size
+ * since big test files usually take longer to complete.
+ *
+ * Note that a possible improvement would be to analyse other information
+ * from the file other than its size.
+ *
+ */
+
+ sort(tests) {
+ const stats = {};
+
+ const fileSize = ({path, context: {hasteFS}}) =>
+ stats[path] || (stats[path] = hasteFS.getSize(path) || 0);
+
+ const hasFailed = (cache, test) =>
+ cache[test.path] && cache[test.path][0] === FAIL;
+
+ const time = (cache, test) => cache[test.path] && cache[test.path][1];
+
+ tests.forEach(test => (test.duration = time(this._getCache(test), test)));
+ return tests.sort((testA, testB) => {
+ const cacheA = this._getCache(testA);
+
+ const cacheB = this._getCache(testB);
+
+ const failedA = hasFailed(cacheA, testA);
+ const failedB = hasFailed(cacheB, testB);
+ const hasTimeA = testA.duration != null;
+
+ if (failedA !== failedB) {
+ return failedA ? -1 : 1;
+ } else if (hasTimeA != (testB.duration != null)) {
+ // If only one of two tests has timing information, run it last
+ return hasTimeA ? 1 : -1;
+ } else if (testA.duration != null && testB.duration != null) {
+ return testA.duration < testB.duration ? 1 : -1;
+ } else {
+ return fileSize(testA) < fileSize(testB) ? 1 : -1;
+ }
+ });
+ }
+
+ allFailedTests(tests) {
+ const hasFailed = (cache, test) => {
+ var _cache$test$path;
+
+ return (
+ ((_cache$test$path = cache[test.path]) === null ||
+ _cache$test$path === void 0
+ ? void 0
+ : _cache$test$path[0]) === FAIL
+ );
+ };
+
+ return this.sort(
+ tests.filter(test => hasFailed(this._getCache(test), test))
+ );
+ }
+
+ cacheResults(tests, results) {
+ const map = Object.create(null);
+ tests.forEach(test => (map[test.path] = test));
+ results.testResults.forEach(testResult => {
+ if (testResult && map[testResult.testFilePath] && !testResult.skipped) {
+ const cache = this._getCache(map[testResult.testFilePath]);
+
+ const perf = testResult.perfStats;
+ cache[testResult.testFilePath] = [
+ testResult.numFailingTests ? FAIL : SUCCESS,
+ perf.runtime || 0
+ ];
+ }
+ });
+
+ this._cache.forEach((cache, context) =>
+ fs().writeFileSync(this._getCachePath(context), JSON.stringify(cache))
+ );
+ }
+}
+
+exports.default = TestSequencer;
diff --git a/node_modules/@jest/test-sequencer/package.json b/node_modules/@jest/test-sequencer/package.json
new file mode 100644
index 0000000..f4eb2c3
--- /dev/null
+++ b/node_modules/@jest/test-sequencer/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "@jest/test-sequencer",
+ "version": "27.5.1",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/facebook/jest.git",
+ "directory": "packages/jest-test-sequencer"
+ },
+ "license": "MIT",
+ "main": "./build/index.js",
+ "types": "./build/index.d.ts",
+ "exports": {
+ ".": {
+ "types": "./build/index.d.ts",
+ "default": "./build/index.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "dependencies": {
+ "@jest/test-result": "^27.5.1",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^27.5.1",
+ "jest-runtime": "^27.5.1"
+ },
+ "devDependencies": {
+ "@types/graceful-fs": "^4.1.3"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "gitHead": "67c1aa20c5fec31366d733e901fee2b981cb1850"
+}