Skip to content
This repository was archived by the owner on Sep 1, 2024. It is now read-only.

Commit 05f810b

Browse files
committed
[jest] Verify numbers of test/spec runs in integration tests
1 parent 253cb34 commit 05f810b

File tree

11 files changed

+1072
-909
lines changed

11 files changed

+1072
-909
lines changed

package.json

-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
"packageManager": "[email protected]",
33
"private": true,
44
"devDependencies": {
5-
"@babel/core": "^7.21.5",
6-
"@babel/preset-env": "^7.21.5",
7-
"@babel/preset-typescript": "^7.21.5",
85
"@types/debug": "^4.1.7",
96
"@types/js-yaml": "^4.0.5",
107
"@types/node": "^14.18.43",

packages/cypress-plugin/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"rimraf": "^5.0.1",
8787
"rollup": "^3.21.1",
8888
"rollup-plugin-dts": "^5.3.0",
89+
"ts-jest": "^29.1.0",
8990
"typescript": "^4.9.5",
9091
"widest-line": "3.1.0"
9192
},

babel.config.js packages/jest-plugin/test/babel.config.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) 2022-2023 Developer Innovations, LLC
22

33
/* eslint-env node */
4+
5+
/** @type {import('@babel/core').ConfigFunction} */
46
module.exports = (api) => {
57
api.cache.using(() => process.env.NODE_ENV);
68
return {

packages/jest-plugin/test/integration-input/jest.config.js

+1-5
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
module.exports = {
44
clearMocks: true,
55
maxWorkers: 2,
6-
// The /dist path is required until https://github.com/facebook/jest/pull/11961 is fixed, which
7-
// appears not to be until Jest 28.x.
8-
reporters: ["@unflakable/jest-plugin/dist/reporter"],
9-
runner: "@unflakable/jest-plugin/dist/runner",
106

117
// Default changed in Jest 29 (see
128
// https://github.com/facebook/jest/blob/94c06ef0aa9b327f3c400610b861e7308b29ee0d/docs/UpgradingToJest29.md).
@@ -21,7 +17,7 @@ module.exports = {
2117
"^.+\\.[jt]sx?$": [
2218
"babel-jest",
2319
{
24-
configFile: "../../../../babel.config.js",
20+
configFile: "../babel.config.js",
2521
},
2622
],
2723
},

packages/jest-plugin/test/integration-input/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"@unflakable/js-api": "workspace:^",
77
"jest": "25.1.0 - 29",
88
"jest-each": "25.1.0 - 29",
9-
"jest-environment-node": "25.1.0 - 29"
9+
"jest-environment-node": "25.1.0 - 29",
10+
"typescript": "^4.9.5"
1011
},
1112
"scripts": {
1213
"test": "jest",

packages/jest-plugin/test/integration/jest.config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// Copyright (c) 2022-2023 Developer Innovations, LLC
22

33
module.exports = {
4+
setupFilesAfterEnv: ["./src/matchers.ts"],
45
testEnvironment: "node",
56

67
transform: {
78
"^.+\\.[jt]s$": [
89
"babel-jest",
910
{
10-
configFile: "../../../../babel.config.js",
11+
configFile: "../babel.config.js",
1112
},
1213
],
1314
},

packages/jest-plugin/test/integration/package.json

+8
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,22 @@
22
"name": "jest-integration",
33
"private": true,
44
"devDependencies": {
5+
"@babel/core": "^7.22.9",
6+
"@babel/preset-env": "^7.22.9",
7+
"@babel/preset-typescript": "^7.22.5",
8+
"@jest/expect-utils": "25.1.0 - 29",
59
"@types/temp": "^0.9.1",
610
"@unflakable/jest-plugin": "workspace:^",
711
"@unflakable/js-api": "workspace:^",
812
"escape-string-regexp": "^4.0.0",
13+
"expect": "25.1.0 - 29",
914
"jest": "25.1.0 - 29",
1015
"jest-environment-node": "25.1.0 - 29",
16+
"jest-get-type": "25.1.0 - 29",
17+
"jest-matcher-utils": "25.1.0 - 29",
1118
"mockttp": "^3.7.5",
1219
"temp": "^0.9.4",
20+
"typescript": "^4.9.5",
1321
"unflakable-test-common": "workspace:^"
1422
},
1523
"scripts": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright (c) 2023 Developer Innovations, LLC
2+
3+
import {
4+
MatcherHintOptions,
5+
matcherErrorMessage,
6+
matcherHint,
7+
RECEIVED_COLOR,
8+
printWithType,
9+
printReceived,
10+
getLabelPrinter,
11+
printExpected,
12+
INVERTED_COLOR,
13+
stringify,
14+
} from "jest-matcher-utils";
15+
import type { SyncExpectationResult } from "expect";
16+
import { equals, iterableEquality } from "@jest/expect-utils";
17+
import * as getType from "jest-get-type";
18+
19+
function toContainEqualTimes(
20+
this: jest.MatcherContext,
21+
received: Array<unknown> | Set<unknown>,
22+
expected: unknown,
23+
times: number
24+
): SyncExpectationResult {
25+
const matcherName = "toContainEqualTimes";
26+
const isNot = this.isNot;
27+
const options: MatcherHintOptions = {
28+
comment: "deep equality",
29+
isNot,
30+
promise: this.promise,
31+
};
32+
33+
if (received === null) {
34+
throw new Error(
35+
matcherErrorMessage(
36+
matcherHint(matcherName, undefined, undefined, options),
37+
`${RECEIVED_COLOR("received")} value must not be null nor undefined`,
38+
printWithType("Received", received, printReceived)
39+
)
40+
);
41+
}
42+
43+
const matchIndices = Array.from(received).reduce(
44+
(matchIndices: number[], item: unknown, index: number) =>
45+
equals(item, expected, [...(this.customTesters ?? []), iterableEquality])
46+
? [...matchIndices, index]
47+
: matchIndices,
48+
[]
49+
);
50+
51+
const pass = matchIndices.length === times;
52+
53+
const message = (): string => {
54+
const labelExpected = `Expected value ${times} time${
55+
times !== 1 ? "s" : ""
56+
}`;
57+
const labelReceived = `Received ${(getType.getType ?? getType)(
58+
received
59+
)} with ${matchIndices.length} match${
60+
matchIndices.length !== 1 ? "es" : ""
61+
}`;
62+
const printLabel = getLabelPrinter(labelExpected, labelReceived);
63+
64+
return (
65+
matcherHint(matcherName, undefined, undefined, options) +
66+
"\n\n" +
67+
`${printLabel(labelExpected)}${
68+
isNot === true ? "not " : ""
69+
}${printExpected(expected)}\n` +
70+
`${printLabel(labelReceived)}${isNot === true ? " " : ""}${
71+
isNot === true && Array.isArray(received)
72+
? RECEIVED_COLOR(
73+
`[${received
74+
.map((item, i) => {
75+
const stringified = stringify(item);
76+
return matchIndices.includes(i)
77+
? INVERTED_COLOR(stringified)
78+
: stringified;
79+
})
80+
.join(", ")}]`
81+
)
82+
: printReceived(received)
83+
}`
84+
);
85+
};
86+
87+
return { message, pass };
88+
}
89+
90+
expect.extend({
91+
toContainEqualTimes,
92+
});
93+
94+
declare global {
95+
// eslint-disable-next-line @typescript-eslint/no-namespace
96+
namespace jest {
97+
interface Matchers<R> {
98+
toContainEqualTimes(expected: unknown, times: number): R;
99+
}
100+
}
101+
}

0 commit comments

Comments
 (0)