mirror of https://github.com/facebook/jest.git
chore: enable a bunch more lint rules (#14794)
This commit is contained in:
parent
175665ec49
commit
0469b4c698
|
@ -35,13 +35,19 @@ module.exports = {
|
||||||
'plugin:eslint-comments/recommended',
|
'plugin:eslint-comments/recommended',
|
||||||
'plugin:prettier/recommended',
|
'plugin:prettier/recommended',
|
||||||
'plugin:unicorn/recommended',
|
'plugin:unicorn/recommended',
|
||||||
|
'plugin:promise/recommended',
|
||||||
],
|
],
|
||||||
globals: {
|
globals: {
|
||||||
console: 'readonly',
|
console: 'readonly',
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
extends: ['plugin:@typescript-eslint/strict', 'plugin:import/typescript'],
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/eslint-recommended',
|
||||||
|
'plugin:@typescript-eslint/strict',
|
||||||
|
'plugin:@typescript-eslint/stylistic',
|
||||||
|
'plugin:import/typescript',
|
||||||
|
],
|
||||||
files: ['*.ts', '*.tsx'],
|
files: ['*.ts', '*.tsx'],
|
||||||
plugins: ['@typescript-eslint/eslint-plugin', 'local'],
|
plugins: ['@typescript-eslint/eslint-plugin', 'local'],
|
||||||
rules: {
|
rules: {
|
||||||
|
@ -59,6 +65,7 @@ module.exports = {
|
||||||
],
|
],
|
||||||
'@typescript-eslint/prefer-ts-expect-error': 'error',
|
'@typescript-eslint/prefer-ts-expect-error': 'error',
|
||||||
'@typescript-eslint/no-var-requires': 'off',
|
'@typescript-eslint/no-var-requires': 'off',
|
||||||
|
'@typescript-eslint/consistent-indexed-object-style': 'off',
|
||||||
// TS verifies these
|
// TS verifies these
|
||||||
'consistent-return': 'off',
|
'consistent-return': 'off',
|
||||||
'no-dupe-class-members': 'off',
|
'no-dupe-class-members': 'off',
|
||||||
|
@ -68,10 +75,7 @@ module.exports = {
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||||
'@typescript-eslint/no-invalid-void-type': 'off',
|
'@typescript-eslint/no-invalid-void-type': 'off',
|
||||||
|
'@typescript-eslint/consistent-type-definitions': 'off',
|
||||||
// TODO: part of "stylistic" rules, remove explicit activation when that lands
|
|
||||||
'@typescript-eslint/no-empty-function': 'error',
|
|
||||||
'@typescript-eslint/no-empty-interface': 'error',
|
|
||||||
|
|
||||||
// not needed to be enforced for TS
|
// not needed to be enforced for TS
|
||||||
'import/namespace': 'off',
|
'import/namespace': 'off',
|
||||||
|
@ -326,6 +330,7 @@ module.exports = {
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/ban-ts-comment': 'off',
|
'@typescript-eslint/ban-ts-comment': 'off',
|
||||||
'@typescript-eslint/no-empty-function': 'off',
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
|
'@typescript-eslint/class-literal-property-style': 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -427,6 +432,12 @@ module.exports = {
|
||||||
'unicorn/no-static-only-class': 'off',
|
'unicorn/no-static-only-class': 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: '**/*.mjs',
|
||||||
|
rules: {
|
||||||
|
'unicorn/prefer-top-level-await': 'error',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
|
@ -617,6 +628,11 @@ module.exports = {
|
||||||
'prefer-arrow-callback': ['error', {allowNamedFunctions: true}],
|
'prefer-arrow-callback': ['error', {allowNamedFunctions: true}],
|
||||||
'prefer-const': 'error',
|
'prefer-const': 'error',
|
||||||
'prefer-template': 'error',
|
'prefer-template': 'error',
|
||||||
|
|
||||||
|
'promise/always-return': 'off',
|
||||||
|
'promise/catch-or-return': 'off',
|
||||||
|
'promise/no-callback-in-promise': 'off',
|
||||||
|
|
||||||
quotes: [
|
quotes: [
|
||||||
'error',
|
'error',
|
||||||
'single',
|
'single',
|
||||||
|
@ -655,10 +671,8 @@ module.exports = {
|
||||||
'unicorn/prefer-event-target': 'off',
|
'unicorn/prefer-event-target': 'off',
|
||||||
'unicorn/prefer-switch': 'off',
|
'unicorn/prefer-switch': 'off',
|
||||||
'unicorn/prefer-ternary': 'off',
|
'unicorn/prefer-ternary': 'off',
|
||||||
'unicorn/switch-case-braces': 'off',
|
|
||||||
|
|
||||||
// TODO: enable for `.mjs` files
|
|
||||||
'unicorn/prefer-top-level-await': 'off',
|
'unicorn/prefer-top-level-await': 'off',
|
||||||
|
'unicorn/switch-case-braces': 'off',
|
||||||
|
|
||||||
// TODO: decide whether or not we want these
|
// TODO: decide whether or not we want these
|
||||||
'unicorn/filename-case': 'off',
|
'unicorn/filename-case': 'off',
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
it.concurrent('Good Test', async () => {
|
it.concurrent('Good Test', async () => {
|
||||||
await new Promise(r => setTimeout(r, 100));
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
});
|
});
|
||||||
|
|
||||||
it.concurrent('Bad Test', async () => {
|
it.concurrent('Bad Test', async () => {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const sleep = ms => new Promise(r => setTimeout(r, ms));
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
|
||||||
describe('A', () => {
|
describe('A', () => {
|
||||||
it.concurrent('a', async () => {
|
it.concurrent('a', async () => {
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
"eslint-plugin-local": "link:./.eslintplugin",
|
"eslint-plugin-local": "link:./.eslintplugin",
|
||||||
"eslint-plugin-markdown": "^3.0.0",
|
"eslint-plugin-markdown": "^3.0.0",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
|
"eslint-plugin-promise": "^6.1.1",
|
||||||
"eslint-plugin-unicorn": "^50.0.0",
|
"eslint-plugin-unicorn": "^50.0.0",
|
||||||
"execa": "^5.0.0",
|
"execa": "^5.0.0",
|
||||||
"find-process": "^1.4.1",
|
"find-process": "^1.4.1",
|
||||||
|
|
|
@ -133,7 +133,7 @@ FUNCTIONS.mock = args => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ids: Set<NodePath<Identifier>> = new Set();
|
const ids = new Set<NodePath<Identifier>>();
|
||||||
const parentScope = moduleFactory.parentPath.scope;
|
const parentScope = moduleFactory.parentPath.scope;
|
||||||
// @ts-expect-error: ReferencedIdentifier and denylist are not known on visitors
|
// @ts-expect-error: ReferencedIdentifier and denylist are not known on visitors
|
||||||
moduleFactory.traverse(IDVisitor, {ids});
|
moduleFactory.traverse(IDVisitor, {ids});
|
||||||
|
|
|
@ -76,13 +76,8 @@ function eq(
|
||||||
}
|
}
|
||||||
|
|
||||||
const testerContext: TesterContext = {equals};
|
const testerContext: TesterContext = {equals};
|
||||||
for (let i = 0; i < customTesters.length; i++) {
|
for (const item of customTesters) {
|
||||||
const customTesterResult = customTesters[i].call(
|
const customTesterResult = item.call(testerContext, a, b, customTesters);
|
||||||
testerContext,
|
|
||||||
a,
|
|
||||||
b,
|
|
||||||
customTesters,
|
|
||||||
);
|
|
||||||
if (customTesterResult !== undefined) {
|
if (customTesterResult !== undefined) {
|
||||||
return customTesterResult;
|
return customTesterResult;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,7 @@ const makeResolveMatcher =
|
||||||
)}\n\n` +
|
)}\n\n` +
|
||||||
'Received promise rejected instead of resolved\n' +
|
'Received promise rejected instead of resolved\n' +
|
||||||
`Rejected to value: ${matcherUtils.printReceived(reason)}`;
|
`Rejected to value: ${matcherUtils.printReceived(reason)}`;
|
||||||
return Promise.reject(outerErr);
|
throw outerErr;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -254,7 +254,7 @@ const makeRejectMatcher =
|
||||||
)}\n\n` +
|
)}\n\n` +
|
||||||
'Received promise resolved instead of rejected\n' +
|
'Received promise resolved instead of rejected\n' +
|
||||||
`Resolved to value: ${matcherUtils.printReceived(result)}`;
|
`Resolved to value: ${matcherUtils.printReceived(result)}`;
|
||||||
return Promise.reject(outerErr);
|
throw outerErr;
|
||||||
},
|
},
|
||||||
reason =>
|
reason =>
|
||||||
makeThrowingMatcher(matcher, isNot, 'rejects', reason, innerErr).apply(
|
makeThrowingMatcher(matcher, isNot, 'rejects', reason, innerErr).apply(
|
||||||
|
|
|
@ -98,11 +98,10 @@ export interface BaseExpect {
|
||||||
setState(state: Partial<MatcherState>): void;
|
setState(state: Partial<MatcherState>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Expect = {
|
export type Expect = (<T = unknown>(
|
||||||
<T = unknown>(
|
actual: T,
|
||||||
actual: T,
|
) => Matchers<void, T> & Inverse<Matchers<void, T>> & PromiseMatchers<T>) &
|
||||||
): Matchers<void, T> & Inverse<Matchers<void, T>> & PromiseMatchers<T>;
|
BaseExpect &
|
||||||
} & BaseExpect &
|
|
||||||
AsymmetricMatchers &
|
AsymmetricMatchers &
|
||||||
Inverse<Omit<AsymmetricMatchers, 'any' | 'anything'>>;
|
Inverse<Omit<AsymmetricMatchers, 'any' | 'anything'>>;
|
||||||
|
|
||||||
|
|
|
@ -113,8 +113,8 @@ describe('collectHandles', () => {
|
||||||
const server = http.createServer((_, response) => response.end('ok'));
|
const server = http.createServer((_, response) => response.end('ok'));
|
||||||
|
|
||||||
// Start and stop server.
|
// Start and stop server.
|
||||||
await new Promise(r => server.listen(0, r));
|
await new Promise(resolve => server.listen(0, resolve));
|
||||||
await new Promise(r => server.close(r));
|
await new Promise(resolve => server.close(resolve));
|
||||||
|
|
||||||
const openHandles = await handleCollector();
|
const openHandles = await handleCollector();
|
||||||
expect(openHandles).toHaveLength(0);
|
expect(openHandles).toHaveLength(0);
|
||||||
|
@ -130,11 +130,13 @@ describe('collectHandles', () => {
|
||||||
// creates a long-lived `TCPSERVERWRAP` resource. We want to make sure we
|
// creates a long-lived `TCPSERVERWRAP` resource. We want to make sure we
|
||||||
// capture that long-lived resource.
|
// capture that long-lived resource.
|
||||||
const server = new http.Server();
|
const server = new http.Server();
|
||||||
await new Promise(r => server.listen({host: 'localhost', port: 0}, r));
|
await new Promise(resolve =>
|
||||||
|
server.listen({host: 'localhost', port: 0}, resolve),
|
||||||
|
);
|
||||||
|
|
||||||
const openHandles = await handleCollector();
|
const openHandles = await handleCollector();
|
||||||
|
|
||||||
await new Promise(r => server.close(r));
|
await new Promise(resolve => server.close(resolve));
|
||||||
|
|
||||||
expect(openHandles).toContainEqual(
|
expect(openHandles).toContainEqual(
|
||||||
expect.objectContaining({message: 'TCPSERVERWRAP'}),
|
expect.objectContaining({message: 'TCPSERVERWRAP'}),
|
||||||
|
|
|
@ -88,7 +88,7 @@ const regularUpdateGlobalConfig = require('../lib/updateGlobalConfig').default;
|
||||||
const updateGlobalConfig = jest.fn(regularUpdateGlobalConfig);
|
const updateGlobalConfig = jest.fn(regularUpdateGlobalConfig);
|
||||||
jest.doMock('../lib/updateGlobalConfig', () => updateGlobalConfig);
|
jest.doMock('../lib/updateGlobalConfig', () => updateGlobalConfig);
|
||||||
|
|
||||||
const nextTick = () => new Promise(res => process.nextTick(res));
|
const nextTick = () => new Promise(resolve => process.nextTick(resolve));
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
jest.spyOn(process, 'on').mockImplementation(() => {});
|
jest.spyOn(process, 'on').mockImplementation(() => {});
|
||||||
|
@ -771,7 +771,9 @@ describe('Watch mode flows', () => {
|
||||||
|
|
||||||
it('prevents Jest from handling keys when active and returns control when end is called', async () => {
|
it('prevents Jest from handling keys when active and returns control when end is called', async () => {
|
||||||
let resolveShowPrompt;
|
let resolveShowPrompt;
|
||||||
const run = jest.fn(() => new Promise(res => (resolveShowPrompt = res)));
|
const run = jest.fn(
|
||||||
|
() => new Promise(resolve => (resolveShowPrompt = resolve)),
|
||||||
|
);
|
||||||
const pluginPath = `${__dirname}/__fixtures__/plugin_path_1`;
|
const pluginPath = `${__dirname}/__fixtures__/plugin_path_1`;
|
||||||
jest.doMock(
|
jest.doMock(
|
||||||
pluginPath,
|
pluginPath,
|
||||||
|
|
|
@ -68,7 +68,7 @@ jest.doMock(
|
||||||
|
|
||||||
const watch = require('../watch').default;
|
const watch = require('../watch').default;
|
||||||
|
|
||||||
const nextTick = () => new Promise(res => process.nextTick(res));
|
const nextTick = () => new Promise(resolve => process.nextTick(resolve));
|
||||||
|
|
||||||
const globalConfig = {
|
const globalConfig = {
|
||||||
rootDir: '',
|
rootDir: '',
|
||||||
|
|
|
@ -41,7 +41,7 @@ class TestNamePatternPlugin extends BaseWatchPlugin {
|
||||||
globalConfig: Config.GlobalConfig,
|
globalConfig: Config.GlobalConfig,
|
||||||
updateConfigAndRun: UpdateConfigCallback,
|
updateConfigAndRun: UpdateConfigCallback,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((resolve, reject) => {
|
||||||
const testNamePatternPrompt = new TestNamePatternPrompt(
|
const testNamePatternPrompt = new TestNamePatternPrompt(
|
||||||
this._stdout,
|
this._stdout,
|
||||||
this._prompt,
|
this._prompt,
|
||||||
|
@ -50,9 +50,9 @@ class TestNamePatternPlugin extends BaseWatchPlugin {
|
||||||
testNamePatternPrompt.run(
|
testNamePatternPrompt.run(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
updateConfigAndRun({mode: 'watch', testNamePattern: value});
|
updateConfigAndRun({mode: 'watch', testNamePattern: value});
|
||||||
res();
|
resolve();
|
||||||
},
|
},
|
||||||
rej,
|
reject,
|
||||||
{
|
{
|
||||||
header: activeFilters(globalConfig),
|
header: activeFilters(globalConfig),
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,7 +41,7 @@ class TestPathPatternPlugin extends BaseWatchPlugin {
|
||||||
globalConfig: Config.GlobalConfig,
|
globalConfig: Config.GlobalConfig,
|
||||||
updateConfigAndRun: UpdateConfigCallback,
|
updateConfigAndRun: UpdateConfigCallback,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((resolve, reject) => {
|
||||||
const testPathPatternPrompt = new TestPathPatternPrompt(
|
const testPathPatternPrompt = new TestPathPatternPrompt(
|
||||||
this._stdout,
|
this._stdout,
|
||||||
this._prompt,
|
this._prompt,
|
||||||
|
@ -50,9 +50,9 @@ class TestPathPatternPlugin extends BaseWatchPlugin {
|
||||||
testPathPatternPrompt.run(
|
testPathPatternPrompt.run(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
updateConfigAndRun({mode: 'watch', testPathPatterns: [value]});
|
updateConfigAndRun({mode: 'watch', testPathPatterns: [value]});
|
||||||
res();
|
resolve();
|
||||||
},
|
},
|
||||||
rej,
|
reject,
|
||||||
{
|
{
|
||||||
header: activeFilters(globalConfig),
|
header: activeFilters(globalConfig),
|
||||||
},
|
},
|
||||||
|
|
|
@ -67,7 +67,7 @@ class UpdateSnapshotInteractivePlugin extends BaseWatchPlugin {
|
||||||
updateConfigAndRun: Function,
|
updateConfigAndRun: Function,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (this._failedSnapshotTestAssertions.length > 0) {
|
if (this._failedSnapshotTestAssertions.length > 0) {
|
||||||
return new Promise(res => {
|
return new Promise(resolve => {
|
||||||
this._snapshotInteractiveMode.run(
|
this._snapshotInteractiveMode.run(
|
||||||
this._failedSnapshotTestAssertions,
|
this._failedSnapshotTestAssertions,
|
||||||
(assertion, shouldUpdateSnapshot) => {
|
(assertion, shouldUpdateSnapshot) => {
|
||||||
|
@ -79,7 +79,7 @@ class UpdateSnapshotInteractivePlugin extends BaseWatchPlugin {
|
||||||
updateSnapshot: shouldUpdateSnapshot ? 'all' : 'none',
|
updateSnapshot: shouldUpdateSnapshot ? 'all' : 'none',
|
||||||
});
|
});
|
||||||
if (!this._snapshotInteractiveMode.isActive()) {
|
if (!this._snapshotInteractiveMode.isActive()) {
|
||||||
res();
|
resolve();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,8 +27,9 @@ export function extract(contents: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function strip(contents: string): string {
|
export function strip(contents: string): string {
|
||||||
const match = contents.match(docblockRe);
|
const matchResult = contents.match(docblockRe);
|
||||||
return match && match[0] ? contents.slice(match[0].length) : contents;
|
const match = matchResult?.[0];
|
||||||
|
return match == null ? contents : contents.slice(match.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parse(docblock: string): Pragmas {
|
export function parse(docblock: string): Pragmas {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
//
|
//
|
||||||
// Feel free to add any extensions that cannot be a Haste module.
|
// Feel free to add any extensions that cannot be a Haste module.
|
||||||
|
|
||||||
const extensions: Set<string> = new Set([
|
const extensions = new Set<string>([
|
||||||
// JSONs are never haste modules, except for "package.json", which is handled.
|
// JSONs are never haste modules, except for "package.json", which is handled.
|
||||||
'.json',
|
'.json',
|
||||||
|
|
||||||
|
|
|
@ -71,9 +71,9 @@ class CallTracker {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.allArgs = function () {
|
this.allArgs = function () {
|
||||||
const callArgs = [];
|
const callArgs: Array<unknown> = [];
|
||||||
for (let i = 0; i < calls.length; i++) {
|
for (const call of calls) {
|
||||||
callArgs.push(calls[i].args);
|
callArgs.push(call.args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return callArgs;
|
return callArgs;
|
||||||
|
|
|
@ -56,8 +56,7 @@ export default class ReportDispatcher implements Reporter {
|
||||||
constructor(methods: Array<keyof Reporter>) {
|
constructor(methods: Array<keyof Reporter>) {
|
||||||
const dispatchedMethods = methods || [];
|
const dispatchedMethods = methods || [];
|
||||||
|
|
||||||
for (let i = 0; i < dispatchedMethods.length; i++) {
|
for (const method of dispatchedMethods) {
|
||||||
const method = dispatchedMethods[i];
|
|
||||||
this[method] = (function (m) {
|
this[method] = (function (m) {
|
||||||
return function () {
|
return function () {
|
||||||
dispatch(m, arguments);
|
dispatch(m, arguments);
|
||||||
|
@ -86,8 +85,7 @@ export default class ReportDispatcher implements Reporter {
|
||||||
if (reporters.length === 0 && fallbackReporter !== null) {
|
if (reporters.length === 0 && fallbackReporter !== null) {
|
||||||
reporters.push(fallbackReporter);
|
reporters.push(fallbackReporter);
|
||||||
}
|
}
|
||||||
for (let i = 0; i < reporters.length; i++) {
|
for (const reporter of reporters) {
|
||||||
const reporter = reporters[i];
|
|
||||||
if (reporter[method]) {
|
if (reporter[method]) {
|
||||||
// @ts-expect-error: wrong context
|
// @ts-expect-error: wrong context
|
||||||
reporter[method].apply(reporter, args);
|
reporter[method].apply(reporter, args);
|
||||||
|
|
|
@ -190,8 +190,7 @@ export default class Suite {
|
||||||
};
|
};
|
||||||
this.result.failedExpectations.push(expectationResultFactory(data));
|
this.result.failedExpectations.push(expectationResultFactory(data));
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < this.children.length; i++) {
|
for (const child of this.children) {
|
||||||
const child = this.children[i];
|
|
||||||
child.onException.apply(child, args);
|
child.onException.apply(child, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,8 +204,7 @@ export default class Suite {
|
||||||
throw new ExpectationFailed();
|
throw new ExpectationFailed();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < this.children.length; i++) {
|
for (const child of this.children) {
|
||||||
const child = this.children[i];
|
|
||||||
try {
|
try {
|
||||||
child.addExpectationResult.apply(child, args);
|
child.addExpectationResult.apply(child, args);
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
@ -36,7 +36,7 @@ const isMap = (value: any): value is Map<unknown, unknown> =>
|
||||||
|
|
||||||
export default function deepCyclicCopyReplaceable<T>(
|
export default function deepCyclicCopyReplaceable<T>(
|
||||||
value: T,
|
value: T,
|
||||||
cycles: WeakMap<any, any> = new WeakMap(),
|
cycles = new WeakMap<any, any>(),
|
||||||
): T {
|
): T {
|
||||||
if (typeof value !== 'object' || value === null) {
|
if (typeof value !== 'object' || value === null) {
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -101,9 +101,7 @@ interface SomeFunctionObject {
|
||||||
one: {
|
one: {
|
||||||
(oneA: number, oneB?: boolean): boolean;
|
(oneA: number, oneB?: boolean): boolean;
|
||||||
more: {
|
more: {
|
||||||
time: {
|
time: (time: number) => void;
|
||||||
(time: number): void;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ export type MockMetadata<T, MetadataType = MockMetadataType> = {
|
||||||
length?: number;
|
length?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ClassLike = {new (...args: any): any};
|
export type ClassLike = new (...args: any) => any;
|
||||||
export type FunctionLike = (...args: any) => any;
|
export type FunctionLike = (...args: any) => any;
|
||||||
|
|
||||||
export type ConstructorLikeKeys<T> = keyof {
|
export type ConstructorLikeKeys<T> = keyof {
|
||||||
|
@ -91,7 +91,7 @@ export type MockedShallow<T> = T extends ClassLike
|
||||||
: T;
|
: T;
|
||||||
|
|
||||||
export type UnknownFunction = (...args: Array<unknown>) => unknown;
|
export type UnknownFunction = (...args: Array<unknown>) => unknown;
|
||||||
export type UnknownClass = {new (...args: Array<unknown>): unknown};
|
export type UnknownClass = new (...args: Array<unknown>) => unknown;
|
||||||
|
|
||||||
export type SpiedClass<T extends ClassLike = UnknownClass> = MockInstance<
|
export type SpiedClass<T extends ClassLike = UnknownClass> = MockInstance<
|
||||||
(...args: ConstructorParameters<T>) => InstanceType<T>
|
(...args: ConstructorParameters<T>) => InstanceType<T>
|
||||||
|
@ -533,9 +533,7 @@ export class ModuleMocker {
|
||||||
) {
|
) {
|
||||||
const ownNames = Object.getOwnPropertyNames(object);
|
const ownNames = Object.getOwnPropertyNames(object);
|
||||||
|
|
||||||
for (let i = 0; i < ownNames.length; i++) {
|
for (const prop of ownNames) {
|
||||||
const prop = ownNames[i];
|
|
||||||
|
|
||||||
if (!isReadonlyProp(object, prop)) {
|
if (!isReadonlyProp(object, prop)) {
|
||||||
const propDesc = Object.getOwnPropertyDescriptor(object, prop);
|
const propDesc = Object.getOwnPropertyDescriptor(object, prop);
|
||||||
if ((propDesc !== undefined && !propDesc.get) || object.__esModule) {
|
if ((propDesc !== undefined && !propDesc.get) || object.__esModule) {
|
||||||
|
|
|
@ -75,10 +75,10 @@ const isRecoverableError = (error: unknown) => {
|
||||||
|
|
||||||
if (jestProjectConfig.transform) {
|
if (jestProjectConfig.transform) {
|
||||||
let transformerPath = null;
|
let transformerPath = null;
|
||||||
for (let i = 0; i < jestProjectConfig.transform.length; i++) {
|
for (const transform of jestProjectConfig.transform) {
|
||||||
if (new RegExp(jestProjectConfig.transform[i][0]).test('foobar.js')) {
|
if (new RegExp(transform[0]).test('foobar.js')) {
|
||||||
transformerPath = jestProjectConfig.transform[i][1];
|
transformerPath = transform[1];
|
||||||
transformerConfig = jestProjectConfig.transform[i][2];
|
transformerConfig = transform[2];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,11 @@ export async function run(
|
||||||
if (cliArgv) {
|
if (cliArgv) {
|
||||||
argv = cliArgv;
|
argv = cliArgv;
|
||||||
} else {
|
} else {
|
||||||
argv = <Config.Argv>(
|
argv = yargs
|
||||||
yargs.usage(args.usage).help(false).version(false).options(args.options)
|
.usage(args.usage)
|
||||||
.argv
|
.help(false)
|
||||||
);
|
.version(false)
|
||||||
|
.options(args.options).argv as Config.Argv;
|
||||||
|
|
||||||
validateCLIOptions(argv, {...args.options, deprecationEntries});
|
validateCLIOptions(argv, {...args.options, deprecationEntries});
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,10 +231,8 @@ export default class GitHubActionsReporter extends BaseReporter {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let alreadyInserted = false;
|
let alreadyInserted = false;
|
||||||
for (let index = 0; index < branches.length; index++) {
|
for (const branch of branches) {
|
||||||
if (
|
if (this.arrayEqual(branch, element.ancestorTitles.slice(0, 1))) {
|
||||||
this.arrayEqual(branches[index], element.ancestorTitles.slice(0, 1))
|
|
||||||
) {
|
|
||||||
alreadyInserted = true;
|
alreadyInserted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -286,10 +284,10 @@ export default class GitHubActionsReporter extends BaseReporter {
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
let alreadyInserted = false;
|
let alreadyInserted = false;
|
||||||
for (let index = 0; index < branches.length; index++) {
|
for (const branch of branches) {
|
||||||
if (
|
if (
|
||||||
this.arrayEqual(
|
this.arrayEqual(
|
||||||
branches[index],
|
branch,
|
||||||
element.ancestorTitles.slice(0, ancestors.length + 1),
|
element.ancestorTitles.slice(0, ancestors.length + 1),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -192,8 +192,8 @@ export default class Status {
|
||||||
|
|
||||||
let height = 0;
|
let height = 0;
|
||||||
|
|
||||||
for (let i = 0; i < content.length; i++) {
|
for (const char of content) {
|
||||||
if (content[i] === '\n') {
|
if (char === '\n') {
|
||||||
height++;
|
height++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ export class DependencyResolver {
|
||||||
};
|
};
|
||||||
|
|
||||||
const relatedPaths = new Set<string>();
|
const relatedPaths = new Set<string>();
|
||||||
const changed: Set<string> = new Set();
|
const changed = new Set<string>();
|
||||||
for (const path of paths) {
|
for (const path of paths) {
|
||||||
if (this._hasteFS.exists(path)) {
|
if (this._hasteFS.exists(path)) {
|
||||||
const modulePath = isSnapshotPath(path)
|
const modulePath = isSnapshotPath(path)
|
||||||
|
|
|
@ -102,7 +102,7 @@ export default class TestRunner extends EmittingTestRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
async #createParallelTestRun(tests: Array<Test>, watcher: TestWatcher) {
|
async #createParallelTestRun(tests: Array<Test>, watcher: TestWatcher) {
|
||||||
const resolvers: Map<string, SerializableResolver> = new Map();
|
const resolvers = new Map<string, SerializableResolver>();
|
||||||
for (const test of tests) {
|
for (const test of tests) {
|
||||||
if (!resolvers.has(test.context.config.id)) {
|
if (!resolvers.has(test.context.config.id)) {
|
||||||
resolvers.set(test.context.config.id, {
|
resolvers.set(test.context.config.id, {
|
||||||
|
@ -167,7 +167,7 @@ export default class TestRunner extends EmittingTestRunner {
|
||||||
return promise;
|
return promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
const onInterrupt = new Promise((_, reject) => {
|
const onInterrupt = new Promise((_resolve, reject) => {
|
||||||
watcher.on('change', state => {
|
watcher.on('change', state => {
|
||||||
if (state.interrupted) {
|
if (state.interrupted) {
|
||||||
reject(new CancelRun());
|
reject(new CancelRun());
|
||||||
|
|
|
@ -254,8 +254,8 @@ class ScriptTransformer {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < transformEntry.length; i++) {
|
for (const item of transformEntry) {
|
||||||
const [transformRegExp, transformPath] = transformEntry[i];
|
const [transformRegExp, transformPath] = item;
|
||||||
if (transformRegExp.test(filename)) {
|
if (transformRegExp.test(filename)) {
|
||||||
return [transformRegExp.source, transformPath];
|
return [transformRegExp.source, transformPath];
|
||||||
}
|
}
|
||||||
|
@ -1017,12 +1017,8 @@ const calcTransformRegExp = (config: Config.ProjectConfig) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const transformRegexp: Array<[RegExp, string, Record<string, unknown>]> = [];
|
const transformRegexp: Array<[RegExp, string, Record<string, unknown>]> = [];
|
||||||
for (let i = 0; i < config.transform.length; i++) {
|
for (const item of config.transform) {
|
||||||
transformRegexp.push([
|
transformRegexp.push([new RegExp(item[0]), item[1], item[2]]);
|
||||||
new RegExp(config.transform[i][0]),
|
|
||||||
config.transform[i][1],
|
|
||||||
config.transform[i][2],
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return transformRegexp;
|
return transformRegexp;
|
||||||
|
|
|
@ -113,9 +113,7 @@ interface Each<EachFn extends TestFn | BlockFn> {
|
||||||
) => void;
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HookBase {
|
export type HookBase = (fn: HookFn, timeout?: number) => void;
|
||||||
(fn: HookFn, timeout?: number): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Failing<T extends TestFn> {
|
export interface Failing<T extends TestFn> {
|
||||||
(testName: TestNameLike, fn: T, timeout?: number): void;
|
(testName: TestNameLike, fn: T, timeout?: number): void;
|
||||||
|
|
|
@ -15,7 +15,7 @@ export type DeepCyclicCopyOptions = {
|
||||||
export default function deepCyclicCopy<T>(
|
export default function deepCyclicCopy<T>(
|
||||||
value: T,
|
value: T,
|
||||||
options: DeepCyclicCopyOptions = {blacklist: EMPTY, keepPrototype: false},
|
options: DeepCyclicCopyOptions = {blacklist: EMPTY, keepPrototype: false},
|
||||||
cycles: WeakMap<any, any> = new WeakMap(),
|
cycles = new WeakMap<any, any>(),
|
||||||
): T {
|
): T {
|
||||||
if (typeof value !== 'object' || value === null || Buffer.isBuffer(value)) {
|
if (typeof value !== 'object' || value === null || Buffer.isBuffer(value)) {
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -63,8 +63,8 @@ export default function globsToMatcher(globs: Array<string>): Matcher {
|
||||||
let kept = undefined;
|
let kept = undefined;
|
||||||
let negatives = 0;
|
let negatives = 0;
|
||||||
|
|
||||||
for (let i = 0; i < matchers.length; i++) {
|
for (const matcher of matchers) {
|
||||||
const {isMatch, negated} = matchers[i];
|
const {isMatch, negated} = matcher;
|
||||||
|
|
||||||
if (negated) {
|
if (negated) {
|
||||||
negatives++;
|
negatives++;
|
||||||
|
|
|
@ -42,7 +42,7 @@ export function validationCondition(
|
||||||
export function multipleValidOptions<T extends Array<unknown>>(
|
export function multipleValidOptions<T extends Array<unknown>>(
|
||||||
...args: T
|
...args: T
|
||||||
): T[number] {
|
): T[number] {
|
||||||
const options = <T>[...args];
|
const options = [...args] as T;
|
||||||
// @ts-expect-error: no index signature
|
// @ts-expect-error: no index signature
|
||||||
options[MULTIPLE_VALID_OPTIONS_SYMBOL] = true;
|
options[MULTIPLE_VALID_OPTIONS_SYMBOL] = true;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ export default abstract class PatternPrompt {
|
||||||
this._pipe.write(ansiEscapes.cursorHide);
|
this._pipe.write(ansiEscapes.cursorHide);
|
||||||
this._pipe.write(CLEAR);
|
this._pipe.write(CLEAR);
|
||||||
|
|
||||||
if (options && options.header) {
|
if (typeof options?.header === 'string' && options.header) {
|
||||||
this._pipe.write(`${options.header}\n`);
|
this._pipe.write(`${options.header}\n`);
|
||||||
this._currentUsageRows = usageRows + options.header.split('\n').length;
|
this._currentUsageRows = usageRows + options.header.split('\n').length;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -81,13 +81,11 @@ export interface WatchPlugin {
|
||||||
updateConfigAndRun: UpdateConfigCallback,
|
updateConfigAndRun: UpdateConfigCallback,
|
||||||
) => Promise<void | boolean>;
|
) => Promise<void | boolean>;
|
||||||
}
|
}
|
||||||
export interface WatchPluginClass {
|
export type WatchPluginClass = new (options: {
|
||||||
new (options: {
|
config: Record<string, unknown>;
|
||||||
config: Record<string, unknown>;
|
stdin: ReadStream;
|
||||||
stdin: ReadStream;
|
stdout: WriteStream;
|
||||||
stdout: WriteStream;
|
}) => WatchPlugin;
|
||||||
}): WatchPlugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ScrollOptions = {
|
export type ScrollOptions = {
|
||||||
offset: number;
|
offset: number;
|
||||||
|
|
|
@ -342,10 +342,10 @@ function printPlugin(
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPlugin(plugins: Plugins, val: unknown) {
|
function findPlugin(plugins: Plugins, val: unknown) {
|
||||||
for (let p = 0; p < plugins.length; p++) {
|
for (const plugin of plugins) {
|
||||||
try {
|
try {
|
||||||
if (plugins[p].test(val)) {
|
if (plugin.test(val)) {
|
||||||
return plugins[p];
|
return plugin;
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw new PrettyFormatPluginError(error.message, error.stack);
|
throw new PrettyFormatPluginError(error.message, error.stack);
|
||||||
|
|
|
@ -93,7 +93,10 @@ async function buildNodePackages() {
|
||||||
process.stdout.write(`${OK}\n`);
|
process.stdout.write(`${OK}\n`);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildNodePackages().catch(error => {
|
try {
|
||||||
|
await buildNodePackages();
|
||||||
|
} catch (error) {
|
||||||
|
process.stderr.write(`${ERROR}\n`);
|
||||||
console.error(error);
|
console.error(error);
|
||||||
process.exitCode = 1;
|
process.exitCode = 1;
|
||||||
});
|
}
|
||||||
|
|
|
@ -85,7 +85,10 @@ try {
|
||||||
fix,
|
fix,
|
||||||
fixTypes: ['problem', 'suggestion', 'layout'],
|
fixTypes: ['problem', 'suggestion', 'layout'],
|
||||||
overrideConfig: {
|
overrideConfig: {
|
||||||
extends: ['plugin:@typescript-eslint/recommended-type-checked'],
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/recommended-type-checked',
|
||||||
|
'plugin:@typescript-eslint/stylistic-type-checked',
|
||||||
|
],
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: ['**/__tests__/**'],
|
files: ['**/__tests__/**'],
|
||||||
|
@ -97,6 +100,15 @@ try {
|
||||||
'jest/unbound-method': 'error',
|
'jest/unbound-method': 'error',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: 'packages/jest-types/src/Circus.ts',
|
||||||
|
rules: {
|
||||||
|
// We're faking nominal types
|
||||||
|
'@typescript-eslint/no-duplicate-type-constituents': 'off',
|
||||||
|
// this file has `Exception`, which is `unknown`
|
||||||
|
'@typescript-eslint/no-redundant-type-constituents': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
|
@ -109,6 +121,14 @@ try {
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/consistent-type-exports': 'error',
|
'@typescript-eslint/consistent-type-exports': 'error',
|
||||||
'@typescript-eslint/dot-notation': 'error',
|
'@typescript-eslint/dot-notation': 'error',
|
||||||
|
'@typescript-eslint/no-base-to-string': [
|
||||||
|
'error',
|
||||||
|
// https://github.com/typescript-eslint/typescript-eslint/issues/1655#issuecomment-593639305
|
||||||
|
{ignoredTypeNames: ['AssertionError', 'Error']},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-duplicate-type-constituents': 'error',
|
||||||
|
'@typescript-eslint/no-redundant-type-constituents': 'error',
|
||||||
|
'@typescript-eslint/no-useless-template-literals': 'error',
|
||||||
'@typescript-eslint/non-nullable-type-assertion-style': 'error',
|
'@typescript-eslint/non-nullable-type-assertion-style': 'error',
|
||||||
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
||||||
'@typescript-eslint/prefer-readonly': 'error',
|
'@typescript-eslint/prefer-readonly': 'error',
|
||||||
|
@ -119,18 +139,17 @@ try {
|
||||||
'@typescript-eslint/strict-boolean-expressions': 'error',
|
'@typescript-eslint/strict-boolean-expressions': 'error',
|
||||||
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
||||||
|
|
||||||
// TODO: enable these
|
// TODO: enable this
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
'@typescript-eslint/no-redundant-type-constituents': 'off',
|
|
||||||
'@typescript-eslint/no-duplicate-type-constituents': 'off',
|
|
||||||
'@typescript-eslint/no-base-to-string': 'off',
|
|
||||||
|
|
||||||
// disable the ones we disable in main config
|
// disable the ones we disable in main config
|
||||||
'@typescript-eslint/no-invalid-void-type': 'off',
|
'@typescript-eslint/no-invalid-void-type': 'off',
|
||||||
'@typescript-eslint/no-dynamic-delete': 'off',
|
'@typescript-eslint/no-dynamic-delete': 'off',
|
||||||
'@typescript-eslint/no-var-requires': 'off',
|
'@typescript-eslint/no-var-requires': 'off',
|
||||||
|
'@typescript-eslint/consistent-type-definitions': 'off',
|
||||||
|
|
||||||
// nah
|
// nah
|
||||||
|
'@typescript-eslint/consistent-indexed-object-style': 'off',
|
||||||
'@typescript-eslint/require-await': 'off',
|
'@typescript-eslint/require-await': 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -3040,6 +3040,7 @@ __metadata:
|
||||||
eslint-plugin-local: "link:./.eslintplugin"
|
eslint-plugin-local: "link:./.eslintplugin"
|
||||||
eslint-plugin-markdown: ^3.0.0
|
eslint-plugin-markdown: ^3.0.0
|
||||||
eslint-plugin-prettier: ^5.0.0
|
eslint-plugin-prettier: ^5.0.0
|
||||||
|
eslint-plugin-promise: ^6.1.1
|
||||||
eslint-plugin-unicorn: ^50.0.0
|
eslint-plugin-unicorn: ^50.0.0
|
||||||
execa: ^5.0.0
|
execa: ^5.0.0
|
||||||
find-process: ^1.4.1
|
find-process: ^1.4.1
|
||||||
|
@ -9647,6 +9648,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"eslint-plugin-promise@npm:^6.1.1":
|
||||||
|
version: 6.1.1
|
||||||
|
resolution: "eslint-plugin-promise@npm:6.1.1"
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^7.0.0 || ^8.0.0
|
||||||
|
checksum: 46b9a4f79dae5539987922afc27cc17cbccdecf4f0ba19c0ccbf911b0e31853e9f39d9959eefb9637461b52772afa1a482f1f87ff16c1ba38bdb6fcf21897e9a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"eslint-plugin-unicorn@npm:^50.0.0":
|
"eslint-plugin-unicorn@npm:^50.0.0":
|
||||||
version: 50.0.1
|
version: 50.0.1
|
||||||
resolution: "eslint-plugin-unicorn@npm:50.0.1"
|
resolution: "eslint-plugin-unicorn@npm:50.0.1"
|
||||||
|
|
Loading…
Reference in New Issue