Skip to content

Commit b42d9ed

Browse files
authored
Merge pull request #14 from alexrecuenco/feature/upgrade
Feature/upgrade
2 parents a044242 + 537e964 commit b42d9ed

16 files changed

+2204
-6340
lines changed

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ node_modules/
77
coverage/
88
!.eslintrc.js
99
!.prettierrc.js
10+
!*.js
11+
!*.ts
1012
!.vscode/*.json

.eslintrc.js

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,124 @@
1+
// @ts-check
2+
const stylistic = require('@stylistic/eslint-plugin');
3+
14
const off = 'off';
25

36
const warn = 'warn';
47

58
const error = 'error';
69

710
const TEST_ONLY_IMPORTS = ['fast-check', 'jest', 'eslint', 'prettier'];
11+
const customized = stylistic.configs.customize({
12+
// the following options are the default values
13+
semi: true,
14+
blockSpacing: true,
15+
});
16+
17+
/**
18+
* set of typescript-eslint any rules
19+
* @param {string} level
20+
* @returns
21+
*/
22+
const any_rules = (level) => {
23+
return {
24+
'@typescript-eslint/no-unsafe-return': level,
25+
'@typescript-eslint/no-var-requires': level,
26+
'@typescript-eslint/no-unsafe-member-access': level,
27+
'@typescript-eslint/no-unsafe-argument': level,
28+
'@typescript-eslint/no-unsafe-call': level,
29+
'@typescript-eslint/no-explicit-any': level,
30+
};
31+
};
832

933
module.exports = {
1034
extends: [
1135
'eslint:recommended',
1236
'plugin:@typescript-eslint/eslint-recommended',
1337
'plugin:@typescript-eslint/recommended',
1438
'plugin:@typescript-eslint/recommended-requiring-type-checking',
15-
'plugin:prettier/recommended',
1639
'plugin:import/errors',
1740
'plugin:import/warnings',
1841
'plugin:import/typescript',
42+
// 'plugin:prettier/recommended',
43+
// 'prettier',
1944
],
2045
env: {
2146
node: true,
2247
},
23-
plugins: ['@typescript-eslint/eslint-plugin'],
48+
plugins: [
49+
'@typescript-eslint/eslint-plugin',
50+
'@stylistic', // stylistic rules were migrated here
51+
],
2452
parser: '@typescript-eslint/parser',
2553
parserOptions: {
26-
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
27-
sourceType: 'module', // Allows for the use of imports
54+
ecmaVersion: 2022,
55+
sourceType: 'module',
2856
tsconfigRootDir: __dirname,
29-
project: ['./tsconfig.eslint.json'],
57+
project: [
58+
'./tsconfig.eslint.json',
59+
'./tsconfig.json',
60+
'/tsconfig.prod.json',
61+
],
3062
},
3163
rules: {
32-
'import/no-extraneous-dependencies': warn,
33-
34-
// Temporal?
35-
'no-console': warn,
36-
'no-return-await': warn,
64+
...customized.rules,
65+
'import/no-extraneous-dependencies': error,
66+
'no-console': error,
67+
'@typescript-eslint/return-await': ['error', 'always'],
3768
'no-unused-vars': off,
38-
'@typescript-eslint/no-unused-vars': off,
39-
eqeqeq: [error, 'smart'],
69+
'@typescript-eslint/no-unused-vars': error,
70+
'eqeqeq': [error, 'smart'],
4071
'no-else-return': [
4172
error,
4273
{
4374
allowElseIf: true,
4475
},
4576
],
77+
'@typescript-eslint/require-await': error,
4678
'@typescript-eslint/unbound-method': [
4779
error,
4880
{
4981
ignoreStatic: true,
5082
},
5183
],
84+
// See https://github.com/orgs/react-hook-form/discussions/8622#discussioncomment-4060570
85+
'@typescript-eslint/no-misused-promises': [
86+
error,
87+
{
88+
checksVoidReturn: {
89+
attributes: false,
90+
},
91+
},
92+
],
5293
'no-restricted-imports': [
5394
'error',
5495
{
5596
paths: TEST_ONLY_IMPORTS.map((name) => {
5697
return { name, message: `${name} is only available during testing` };
5798
}),
58-
patterns: TEST_ONLY_IMPORTS.map((dep) => `${dep}/*`),
99+
patterns: TEST_ONLY_IMPORTS.map(dep => `${dep}/*`),
59100
},
60101
],
61-
camelcase: off,
62-
'@typescript-eslint/camelcase': off,
63-
'require-await': off,
64-
'@typescript-eslint/require-await': off,
65-
'@typescript-eslint/indent': off,
66102
'@typescript-eslint/explicit-member-accessibility': warn,
67-
'@typescript-eslint/no-explicit-any': off,
68-
'@typescript-eslint/no-unsafe-argument': off,
69-
'@typescript-eslint/no-unsafe-return': off,
70-
'@typescript-eslint/no-unsafe-assignment': off,
103+
'@typescript-eslint/no-explicit-any': warn,
71104
'@typescript-eslint/explicit-function-return-type': off,
72-
'@typescript-eslint/no-var-requires': off,
105+
// '@typescript-eslint/no-var-requires': off,
106+
73107
'@typescript-eslint/no-empty-function': off,
74-
'@typescript-eslint/no-object-literal-type-assertion': off,
108+
75109
'@typescript-eslint/no-floating-promises': error,
76110
},
77111
overrides: [
78112
{
79-
files: ['*.ts', '*.tsx'],
80-
rules: {},
113+
files: ['.*.js', '.*.cjs', '*.config.cjs', '*.config.js', '*.config.ts'],
114+
env: {
115+
node: true,
116+
},
117+
rules: {
118+
'no-restricted-imports': off,
119+
// Consider if this is too leanient for tests
120+
...any_rules('off'),
121+
},
81122
},
82123
{
83124
// TESTING CONFIGURATION
@@ -90,24 +131,26 @@ module.exports = {
90131
'tests/**/*.ts',
91132
'__tests__/**/*.js',
92133
'__tests__/**/*.ts',
93-
'jest.setup.js',
134+
'jest.*.js',
135+
'jest.*.ts',
94136
],
95137

96138
// https://eslint.org/docs/user-guide/configuring#specifying-environments
97139
env: {
98140
jest: true,
99141
},
100142

101-
// Can't extend in overrides: https://github.com/eslint/eslint/issues/8813
102-
// "extends": ["plugin:jest/recommended"]
143+
extends: ['plugin:jest/recommended'],
103144
plugins: ['jest'],
104145
rules: {
105146
'no-restricted-imports': off,
106-
'jest/no-disabled-tests': warn,
107-
'jest/no-focused-tests': error,
108-
'jest/no-identical-title': error,
109-
'jest/prefer-to-have-length': warn,
110-
'jest/valid-expect': error,
147+
'jest/expect-expect': [
148+
error,
149+
{
150+
assertFunctionNames: ['expect', 'fc.assert'],
151+
},
152+
],
153+
...any_rules('off'),
111154
},
112155
},
113156
],

.github/workflows/main.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ jobs:
99
strategy:
1010
matrix:
1111
# Current versions not in maintainance
12-
node-version: [16.x, 18.x, 20.x]
12+
node-version: [18.x, 20.x]
1313

1414
steps:
15-
- uses: actions/checkout@v2
15+
- uses: actions/checkout@v4
1616
- name: Use Node.js ${{ matrix.node-version }}
17-
uses: actions/setup-node@v1
17+
uses: actions/setup-node@v4
1818
with:
1919
node-version: ${{ matrix.node-version }}
20+
cache: 'npm'
2021
- run: npm ci
2122
- run: npm test
2223
- run: npm run lint

.pre-commit-config.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,3 @@ repos: #The order matters, we want prospector to run after all the sorting was d
1919
# File normalization
2020
- id: end-of-file-fixer
2121
- id: trailing-whitespace
22-
- repo: https://github.com/prettier/prettier
23-
rev: '6b22977cb56127cc10e04425b0eca7c5eb304e6e' # Use the sha or tag you want to point at
24-
hooks:
25-
- id: prettier

.prettierrc.js

Lines changed: 0 additions & 18 deletions
This file was deleted.

.vscode/extensions.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"recommendations": [
33
"dbaeumer.vscode-eslint",
4-
"esbenp.prettier-vscode",
54
"ghmcadams.lintlens",
65
"visualstudioexptteam.vscodeintellicode",
76
"wix.vscode-import-cost",

.vscode/settings.json

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
{
2-
"eslint.validate": ["typescript", "typescriptreact"],
2+
"eslint.validate": [
3+
"typescript",
4+
"typescriptreact"
5+
],
36
"editor.formatOnSave": true,
4-
"editor.defaultFormatter": "esbenp.prettier-vscode",
5-
"[javascript]": {
6-
"editor.defaultFormatter": "esbenp.prettier-vscode"
7+
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
8+
"[javascript,typescript]": {
9+
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
10+
},
11+
"jest.jestCommandLine": "npm test -- ",
12+
"jest.runMode": {
13+
"type": "on-demand"
714
}
815
}

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@ Example of typescript, eslint, and jest with property based testing.
55
Possibly, you might want to delete the `.pre-commit-config.yaml` file if you are not using python anywhere.
66

77
This is only tested with certain versions of node and npm, it might work with others, disable the `engine-strict=true` in the `.npmrc` file at your discretion.
8+
9+
10+
## Check upgrades
11+
12+
```bash
13+
npx npm-check -u
14+
```

__tests__/replace.test.ts

Lines changed: 61 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,57 +6,84 @@ const EachSimpleType = [
66
['integers', fc.integer()],
77
] as const;
88

9-
describe.each(EachSimpleType)('Simple replacements works for %p', (_, arb: Arbitrary<any>) => {
10-
test('Should replace simple types', () => {
11-
fc.assert(
12-
fc.property(arb, fc.func(arb), (s, f) => {
13-
return replace(f, (t: string): t is any => true)(s) === f(s);
14-
}),
15-
);
16-
});
17-
});
9+
describe.each(EachSimpleType)(
10+
'Simple replacements works for %p',
11+
(_, arb: Arbitrary<any>) => {
12+
test('Should replace simple types', () => {
13+
fc.assert(
14+
fc.property(arb, fc.func(arb), (s, f) => {
15+
return replace(f, (t: string): t is any => true)(s) === f(s);
16+
}),
17+
);
18+
});
19+
},
20+
);
1821

19-
describe.each(EachSimpleType)('Simple replacements works for arrays of %p', (_, arb: Arbitrary<any>) => {
20-
test('Should replace only elements', () => {
21-
fc.assert(
22-
fc.property(fc.array(arb), fc.func(arb), (arr, f) => {
23-
const obtainedResult = replace(f, (t): t is any => !Array.isArray(t))(arr);
24-
const realResult = arr.map((v) => f(v));
25-
expect(obtainedResult).toStrictEqual(realResult);
26-
}),
27-
);
28-
});
29-
});
22+
describe.each(EachSimpleType)(
23+
'Simple replacements works for arrays of %p',
24+
(_, arb: Arbitrary<any>) => {
25+
test('Should replace only elements', () => {
26+
fc.assert(
27+
fc.property(fc.array(arb), fc.func(arb), (arr, f) => {
28+
const obtainedResult = replace(
29+
f,
30+
(t): t is any => !Array.isArray(t),
31+
)(arr);
32+
const realResult = arr.map(v => f(v));
33+
expect(obtainedResult).toStrictEqual(realResult);
34+
}),
35+
);
36+
});
37+
},
38+
);
3039

31-
describe.each(EachSimpleType)('Simple replacements works for objects of %p', (_, arb: Arbitrary<any>) => {
32-
test('Should replace only properties', () => {
33-
fc.assert(
34-
fc.property(fc.dictionary(fc.string(), arb), fc.func(arb), (obj, f) => {
35-
const realResult = Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, f(v)]));
36-
const obtainedResult = replace(f, (t): t is any => !Array.isArray(t) && typeof t !== 'object')(obj);
40+
describe.each(EachSimpleType)(
41+
'Simple replacements works for objects of %p',
42+
(_, arb: Arbitrary<any>) => {
43+
test('Should replace only properties', () => {
44+
fc.assert(
45+
fc.property(fc.dictionary(fc.string(), arb), fc.func(arb), (obj, f) => {
46+
const realResult = Object.fromEntries(
47+
Object.entries(obj).map(([k, v]) => [k, f(v)]),
48+
);
49+
const obtainedResult = replace(
50+
f,
51+
(t): t is any => !Array.isArray(t) && typeof t !== 'object',
52+
)(obj);
3753

38-
expect(obtainedResult).toStrictEqual(realResult);
39-
}),
40-
);
41-
});
42-
});
54+
expect(obtainedResult).toStrictEqual(realResult);
55+
}),
56+
);
57+
});
58+
},
59+
);
4360

4461
describe('Ignoring values', () => {
62+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
4563
const f = (v: any) => {
4664
throw new Error();
4765
};
4866
test('should leave json objects alone', () => {
4967
const throwOnReplace = replace(f, (t): t is any => false);
5068
fc.assert(
5169
fc.property(fc.json(), (json) => {
52-
expect(() => expect(throwOnReplace(json)).toStrictEqual(json)).not.toThrow();
70+
expect(() =>
71+
expect(throwOnReplace(json)).toStrictEqual(json),
72+
).not.toThrow();
5373
}),
5474
);
5575
});
5676

5777
test('Should leave numbers unchanged when searching for strings', () => {
58-
const throwOnReplace = replace(f, (t): t is string => typeof t === 'string');
59-
const objectArbitrary = fc.object({ maxDepth: 4, withTypedArray: true, values: [fc.integer()] });
78+
const throwOnReplace = replace(
79+
f,
80+
(t): t is string => typeof t === 'string',
81+
);
82+
const objectArbitrary = fc.object({
83+
maxDepth: 4,
84+
withTypedArray: true,
85+
values: [fc.integer()],
86+
});
6087
fc.assert(
6188
fc.property(objectArbitrary, (obj) => {
6289
expect(() => throwOnReplace(obj)).not.toThrow();

0 commit comments

Comments
 (0)