@servicetitan/startup 31.5.1 → 32.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/build.d.ts +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/bundle-package.d.ts +1 -1
- package/dist/cli/commands/bundle-package.d.ts.map +1 -1
- package/dist/cli/commands/bundle-package.js.map +1 -1
- package/dist/cli/commands/eslint.d.ts +1 -1
- package/dist/cli/commands/eslint.d.ts.map +1 -1
- package/dist/cli/commands/eslint.js.map +1 -1
- package/dist/cli/commands/get-command.js +2 -2
- package/dist/cli/commands/get-command.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +3 -2
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +24 -43
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/install.d.ts +4 -0
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +91 -3
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/lint.d.ts +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/mfe-package-clean.d.ts.map +1 -1
- package/dist/cli/commands/mfe-package-clean.js +5 -7
- package/dist/cli/commands/mfe-package-clean.js.map +1 -1
- package/dist/cli/commands/mfe-package-publish.d.ts.map +1 -1
- package/dist/cli/commands/mfe-package-publish.js +11 -15
- package/dist/cli/commands/mfe-package-publish.js.map +1 -1
- package/dist/cli/commands/mfe-publish.d.ts +1 -1
- package/dist/cli/commands/mfe-publish.d.ts.map +1 -1
- package/dist/cli/commands/mfe-publish.js.map +1 -1
- package/dist/cli/commands/prepare-package.d.ts +1 -1
- package/dist/cli/commands/prepare-package.d.ts.map +1 -1
- package/dist/cli/commands/prepare-package.js.map +1 -1
- package/dist/cli/commands/review/rules/index.d.ts.map +1 -1
- package/dist/cli/commands/review/rules/index.js +4 -0
- package/dist/cli/commands/review/rules/index.js.map +1 -1
- package/dist/cli/commands/review/rules/require-all-react-dependencies.d.ts +14 -0
- package/dist/cli/commands/review/rules/require-all-react-dependencies.d.ts.map +1 -0
- package/dist/cli/commands/review/rules/require-all-react-dependencies.js +64 -0
- package/dist/cli/commands/review/rules/require-all-react-dependencies.js.map +1 -0
- package/dist/cli/commands/review/rules/require-one-react-version.d.ts +5 -0
- package/dist/cli/commands/review/rules/require-one-react-version.d.ts.map +1 -0
- package/dist/cli/commands/review/rules/require-one-react-version.js +25 -0
- package/dist/cli/commands/review/rules/require-one-react-version.js.map +1 -0
- package/dist/cli/commands/review/rules/require-one-uikit-version.d.ts.map +1 -1
- package/dist/cli/commands/review/rules/require-one-uikit-version.js +1 -0
- package/dist/cli/commands/review/rules/require-one-uikit-version.js.map +1 -1
- package/dist/cli/commands/review/utils/format-depends-on.d.ts +1 -0
- package/dist/cli/commands/review/utils/format-depends-on.d.ts.map +1 -1
- package/dist/cli/commands/review/utils/format-depends-on.js +15 -8
- package/dist/cli/commands/review/utils/format-depends-on.js.map +1 -1
- package/dist/cli/commands/review/utils/set-version.d.ts +2 -1
- package/dist/cli/commands/review/utils/set-version.d.ts.map +1 -1
- package/dist/cli/commands/review/utils/set-version.js +4 -2
- package/dist/cli/commands/review/utils/set-version.js.map +1 -1
- package/dist/cli/commands/start.d.ts +1 -1
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/test/index.d.ts +2 -0
- package/dist/cli/commands/test/index.d.ts.map +1 -0
- package/dist/cli/commands/test/index.js +20 -0
- package/dist/cli/commands/test/index.js.map +1 -0
- package/dist/cli/commands/test/runners/index.d.ts +3 -0
- package/dist/cli/commands/test/runners/index.d.ts.map +1 -0
- package/dist/cli/commands/test/runners/index.js +21 -0
- package/dist/cli/commands/test/runners/index.js.map +1 -0
- package/dist/cli/commands/test/runners/jest.d.ts +7 -0
- package/dist/cli/commands/test/runners/jest.d.ts.map +1 -0
- package/dist/cli/commands/test/runners/jest.js +43 -0
- package/dist/cli/commands/test/runners/jest.js.map +1 -0
- package/dist/cli/commands/test/runners/vitest.d.ts +4 -0
- package/dist/cli/commands/test/runners/vitest.d.ts.map +1 -0
- package/dist/cli/commands/test/runners/vitest.js +86 -0
- package/dist/cli/commands/test/runners/vitest.js.map +1 -0
- package/dist/cli/commands/test/tests.d.ts +18 -0
- package/dist/cli/commands/test/tests.d.ts.map +1 -0
- package/dist/cli/commands/{tests.js → test/tests.js} +10 -9
- package/dist/cli/commands/test/tests.js.map +1 -0
- package/dist/cli/commands/upload-sourcemaps.d.ts.map +1 -1
- package/dist/cli/commands/upload-sourcemaps.js +1 -1
- package/dist/cli/commands/upload-sourcemaps.js.map +1 -1
- package/dist/cli/index.js +1 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/bundle.d.ts.map +1 -1
- package/dist/cli/utils/bundle.js +7 -4
- package/dist/cli/utils/bundle.js.map +1 -1
- package/dist/cli/utils/cli-git.d.ts +11 -2
- package/dist/cli/utils/cli-git.d.ts.map +1 -1
- package/dist/cli/utils/cli-git.js +60 -4
- package/dist/cli/utils/cli-git.js.map +1 -1
- package/dist/cli/utils/index.d.ts +6 -0
- package/dist/cli/utils/index.d.ts.map +1 -1
- package/dist/cli/utils/index.js +6 -0
- package/dist/cli/utils/index.js.map +1 -1
- package/dist/cli/utils/is-ci.d.ts +2 -0
- package/dist/cli/utils/is-ci.d.ts.map +1 -0
- package/dist/cli/utils/is-ci.js +15 -0
- package/dist/cli/utils/is-ci.js.map +1 -0
- package/dist/cli/utils/lerna-exec.d.ts.map +1 -1
- package/dist/cli/utils/lerna-exec.js +2 -1
- package/dist/cli/utils/lerna-exec.js.map +1 -1
- package/dist/cli/utils/set-node-options.d.ts.map +1 -1
- package/dist/cli/utils/set-node-options.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/get-branch-configs.d.ts +1 -1
- package/dist/utils/get-branch-configs.d.ts.map +1 -1
- package/dist/utils/get-branch-configs.js +2 -2
- package/dist/utils/get-branch-configs.js.map +1 -1
- package/dist/utils/get-configuration.d.ts +8 -2
- package/dist/utils/get-configuration.d.ts.map +1 -1
- package/dist/utils/get-configuration.js +10 -2
- package/dist/utils/get-configuration.js.map +1 -1
- package/dist/utils/get-jest-config.d.ts +1 -7
- package/dist/utils/get-jest-config.d.ts.map +1 -1
- package/dist/utils/get-jest-config.js +49 -58
- package/dist/utils/get-jest-config.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/webpack/utils/testing/get-compiler.js.map +1 -1
- package/package.json +16 -14
- package/src/cli/commands/__tests__/init.test.ts +21 -87
- package/src/cli/commands/__tests__/install.test.ts +174 -12
- package/src/cli/commands/__tests__/mfe-package-clean.test.ts +3 -6
- package/src/cli/commands/__tests__/mfe-package-publish.test.ts +6 -8
- package/src/cli/commands/__tests__/upload-sourcemaps.test.ts +7 -3
- package/src/cli/commands/build.ts +1 -1
- package/src/cli/commands/bundle-package.ts +1 -1
- package/src/cli/commands/eslint.ts +1 -1
- package/src/cli/commands/get-command.ts +1 -1
- package/src/cli/commands/index.ts +1 -1
- package/src/cli/commands/init.ts +18 -38
- package/src/cli/commands/install.ts +95 -6
- package/src/cli/commands/lint.ts +1 -1
- package/src/cli/commands/mfe-package-clean.ts +2 -4
- package/src/cli/commands/mfe-package-publish.ts +18 -6
- package/src/cli/commands/mfe-publish.ts +1 -1
- package/src/cli/commands/prepare-package.ts +1 -1
- package/src/cli/commands/review/rules/__tests__/require-all-react-dependencies.test.ts +132 -0
- package/src/cli/commands/review/rules/__tests__/require-one-package-version.test.ts +0 -1
- package/src/cli/commands/review/rules/__tests__/require-one-react-version.test.ts +22 -0
- package/src/cli/commands/review/rules/__tests__/{require-one-uikit-version.ts → require-one-uikit-version.test.ts} +1 -0
- package/src/cli/commands/review/rules/index.ts +4 -0
- package/src/cli/commands/review/rules/require-all-react-dependencies.ts +53 -0
- package/src/cli/commands/review/rules/require-one-react-version.ts +9 -0
- package/src/cli/commands/review/rules/require-one-uikit-version.ts +1 -0
- package/src/cli/commands/review/utils/__tests__/set-version.test.ts +18 -8
- package/src/cli/commands/review/utils/format-depends-on.ts +8 -5
- package/src/cli/commands/review/utils/set-version.ts +10 -2
- package/src/cli/commands/start.ts +1 -1
- package/src/cli/commands/test/__tests__/tests.test.ts +78 -0
- package/src/cli/commands/test/index.ts +1 -0
- package/src/cli/commands/{__tests__/tests.test.ts → test/runners/__tests__/jest.test.ts} +10 -13
- package/src/cli/commands/test/runners/__tests__/vitest.test.ts +150 -0
- package/src/cli/commands/test/runners/index.ts +2 -0
- package/src/cli/commands/{tests.ts → test/runners/jest.ts} +5 -16
- package/src/cli/commands/test/runners/vitest.ts +70 -0
- package/src/cli/commands/test/tests.ts +34 -0
- package/src/cli/commands/upload-sourcemaps.ts +2 -2
- package/src/cli/index.ts +1 -2
- package/src/cli/utils/__tests__/bundle.test.ts +1 -1
- package/src/cli/utils/__tests__/cli-git.test.ts +142 -6
- package/src/cli/utils/__tests__/eslint.test.ts +3 -2
- package/src/cli/utils/__tests__/is-ci.test.ts +40 -0
- package/src/cli/utils/__tests__/lerna-exec.test.ts +6 -3
- package/src/cli/utils/bundle.ts +8 -3
- package/src/cli/utils/cli-git.ts +55 -5
- package/src/cli/utils/index.ts +6 -0
- package/src/cli/utils/is-ci.ts +3 -0
- package/src/cli/utils/lerna-exec.ts +2 -1
- package/src/cli/utils/set-node-options.ts +2 -2
- package/src/index.ts +0 -1
- package/src/utils/__tests__/get-configuration.test.ts +48 -11
- package/src/utils/__tests__/get-jest-config.test.ts +35 -61
- package/src/utils/get-branch-configs.ts +1 -1
- package/src/utils/get-configuration.ts +14 -3
- package/src/utils/get-jest-config.ts +39 -47
- package/src/utils/index.ts +1 -0
- package/src/webpack/__tests__/create-webpack-config-shared-dependencies.test.ts +1 -1
- package/src/webpack/__tests__/create-webpack-config-web-component.test.ts +1 -1
- package/src/webpack/__tests__/create-webpack-config.test.ts +1 -1
- package/src/webpack/utils/testing/get-compiler.ts +1 -1
- package/dist/cli/commands/tests.d.ts +0 -13
- package/dist/cli/commands/tests.d.ts.map +0 -1
- package/dist/cli/commands/tests.js.map +0 -1
- package/dist/jest/index.d.ts +0 -2
- package/dist/jest/index.d.ts.map +0 -1
- package/dist/jest/index.js +0 -16
- package/dist/jest/index.js.map +0 -1
- package/src/jest/index.ts +0 -5
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { FixCategory, Project, ReviewConfiguration } from '../../types';
|
|
2
|
+
import { setVersion } from '../../utils';
|
|
3
|
+
import { mockConfig, mockPackages, mockProject } from '../__mocks__';
|
|
4
|
+
|
|
5
|
+
import { RequireAllReactDependencies } from '../require-all-react-dependencies';
|
|
6
|
+
|
|
7
|
+
jest.mock('../../utils', () => ({
|
|
8
|
+
...jest.requireActual('../../utils'),
|
|
9
|
+
setVersion: jest.fn(),
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
describe(`[startup] Review ${RequireAllReactDependencies.name}`, () => {
|
|
13
|
+
const id = 'require-all-react-dependencies';
|
|
14
|
+
const rule = new RequireAllReactDependencies();
|
|
15
|
+
let config: ReviewConfiguration;
|
|
16
|
+
let dependencies: Project['dependencies'];
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
config = {};
|
|
20
|
+
dependencies = {};
|
|
21
|
+
jest.clearAllMocks();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const project = () =>
|
|
25
|
+
mockProject({ config, dependencies, packages: mockPackages(dependencies) });
|
|
26
|
+
|
|
27
|
+
const subject = () => rule.run(project());
|
|
28
|
+
|
|
29
|
+
const fixSubject = () => {
|
|
30
|
+
const testProject = project();
|
|
31
|
+
rule.fix(rule.run(testProject)[0], testProject);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function itReturnsError({
|
|
35
|
+
packageName,
|
|
36
|
+
present,
|
|
37
|
+
absent,
|
|
38
|
+
}: {
|
|
39
|
+
packageName: string;
|
|
40
|
+
present: string;
|
|
41
|
+
absent: string;
|
|
42
|
+
}) {
|
|
43
|
+
test('returns error', () => {
|
|
44
|
+
expect(subject()).toEqual([
|
|
45
|
+
expect.objectContaining({
|
|
46
|
+
id,
|
|
47
|
+
message: `package "${packageName}" depends on ${present} but not on ${absent}`,
|
|
48
|
+
fixable: FixCategory.isolated,
|
|
49
|
+
}),
|
|
50
|
+
]);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function itReturnsNothing() {
|
|
55
|
+
test(`returns nothing`, () => {
|
|
56
|
+
expect(subject()).toEqual([]);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
itReturnsNothing();
|
|
61
|
+
|
|
62
|
+
describe('when package depends only on "react"', () => {
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
dependencies = {
|
|
65
|
+
react: { '^18': ['lib'] },
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
itReturnsError({ packageName: 'lib', present: 'react', absent: 'react-dom' });
|
|
70
|
+
|
|
71
|
+
test('fixes error', () => {
|
|
72
|
+
fixSubject();
|
|
73
|
+
|
|
74
|
+
expect(setVersion).toHaveBeenCalledWith({
|
|
75
|
+
project: project(),
|
|
76
|
+
packageName: 'lib',
|
|
77
|
+
dependency: 'react-dom',
|
|
78
|
+
version: '^18',
|
|
79
|
+
key: 'dependencies',
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('ignores invalid error', () => {
|
|
84
|
+
rule.fix({} as any, project());
|
|
85
|
+
|
|
86
|
+
expect(setVersion).not.toHaveBeenCalled();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('when config excludes package', () => {
|
|
90
|
+
beforeEach(() => (config = mockConfig({ id, exclude: 'lib' })));
|
|
91
|
+
|
|
92
|
+
itReturnsNothing();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('when package depends only on "react-dom"', () => {
|
|
97
|
+
beforeEach(() => {
|
|
98
|
+
dependencies = {
|
|
99
|
+
'react-dom': { '^18': ['lib'] },
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
itReturnsError({ packageName: 'lib', present: 'react-dom', absent: 'react' });
|
|
104
|
+
|
|
105
|
+
test('fixes error', () => {
|
|
106
|
+
fixSubject();
|
|
107
|
+
|
|
108
|
+
expect(setVersion).toHaveBeenCalledWith({
|
|
109
|
+
project: project(),
|
|
110
|
+
packageName: 'lib',
|
|
111
|
+
dependency: 'react',
|
|
112
|
+
version: '^18',
|
|
113
|
+
key: 'dependencies',
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('when package depends on both "react" and "react-dom"', () => {
|
|
119
|
+
beforeEach(() => {
|
|
120
|
+
dependencies = {
|
|
121
|
+
'react': { '^18': ['lib'] },
|
|
122
|
+
'react-dom': { '^18': ['lib'] },
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
itReturnsNothing();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('returns nothing when package has no dependencies', () => {
|
|
130
|
+
expect(rule.run(mockProject({ packages: [{ name: 'foo' } as any] }))).toEqual([]);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -6,7 +6,6 @@ import { mockConfig, mockPackages, mockProject } from '../__mocks__';
|
|
|
6
6
|
|
|
7
7
|
import { RequireOnePackageVersion } from '../require-one-package-version';
|
|
8
8
|
|
|
9
|
-
jest.mock('child_process', () => ({ execSync: jest.fn() }));
|
|
10
9
|
jest.mock('../../utils', () => ({
|
|
11
10
|
...jest.requireActual('../../utils'),
|
|
12
11
|
setVersion: jest.fn(),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RequireOneCollectionVersion } from '../require-one-collection-version';
|
|
2
|
+
|
|
3
|
+
import { RequireOneReactVersion } from '../require-one-react-version';
|
|
4
|
+
|
|
5
|
+
jest.mock('../require-one-collection-version');
|
|
6
|
+
|
|
7
|
+
describe(`[startup] Review ${RequireOneReactVersion.name}`, () => {
|
|
8
|
+
const reactPackages = ['react', 'react-dom'];
|
|
9
|
+
|
|
10
|
+
beforeEach(() => jest.clearAllMocks());
|
|
11
|
+
|
|
12
|
+
const subject = () => new RequireOneReactVersion();
|
|
13
|
+
|
|
14
|
+
test('calls RequireOneCollectionVersion with react packages', () => {
|
|
15
|
+
subject();
|
|
16
|
+
|
|
17
|
+
expect(RequireOneCollectionVersion).toHaveBeenCalledWith({
|
|
18
|
+
name: 'react',
|
|
19
|
+
packages: reactPackages,
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -7,6 +7,7 @@ jest.mock('../require-one-collection-version');
|
|
|
7
7
|
describe(`[startup] Review ${RequireOneUikitVersion.name}`, () => {
|
|
8
8
|
const uikitPackages = [
|
|
9
9
|
'@servicetitan/ajax-handlers',
|
|
10
|
+
'@servicetitan/datadog-rum',
|
|
10
11
|
'@servicetitan/error-boundary',
|
|
11
12
|
'@servicetitan/eslint-config',
|
|
12
13
|
'@servicetitan/eslint-plugin',
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { PackageRule } from '../types';
|
|
2
2
|
import { NoTypescriptEntryPoint } from './no-typescript-entry-point';
|
|
3
|
+
import { RequireAllReactDependencies } from './require-all-react-dependencies';
|
|
3
4
|
import { RequireExplicitSideEffects } from './require-explicit-side-effects';
|
|
4
5
|
import { RequireNpmrc } from './require-npmrc';
|
|
5
6
|
import { RequireOneAnvilUikitContribVersion } from './require-one-anvil-uikit-contrib-version';
|
|
6
7
|
import { RequireOnePackageVersion } from './require-one-package-version';
|
|
8
|
+
import { RequireOneReactVersion } from './require-one-react-version';
|
|
7
9
|
import { RequireOneUikitVersion } from './require-one-uikit-version';
|
|
8
10
|
import { RequireProjectVersionInRootNodeModules } from './require-project-version-in-root-node-modules';
|
|
9
11
|
import { RequireServiceTitanScope } from './require-servicetitan-scope';
|
|
10
12
|
|
|
11
13
|
export const rules: PackageRule[] = [
|
|
12
14
|
new RequireOnePackageVersion(),
|
|
15
|
+
new RequireAllReactDependencies(),
|
|
13
16
|
new RequireOneUikitVersion(),
|
|
14
17
|
new RequireOneAnvilUikitContribVersion(),
|
|
18
|
+
new RequireOneReactVersion(),
|
|
15
19
|
new RequireProjectVersionInRootNodeModules(),
|
|
16
20
|
new NoTypescriptEntryPoint(),
|
|
17
21
|
new RequireServiceTitanScope(),
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { FixCategory, Package, PackageError, PackageRule, Project } from '../types';
|
|
2
|
+
import { applyFilter, formatList, getMaxVersion, setVersion } from '../utils';
|
|
3
|
+
|
|
4
|
+
const REACT_DEPENDENCIES = ['react', 'react-dom'];
|
|
5
|
+
|
|
6
|
+
interface ErrorData {
|
|
7
|
+
missing: string[];
|
|
8
|
+
packageName: string;
|
|
9
|
+
version: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class RequireAllReactDependencies implements PackageRule {
|
|
13
|
+
get id() {
|
|
14
|
+
return 'require-all-react-dependencies';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
run({ config, packages }: Project) {
|
|
18
|
+
const ruleConfig = config.rules?.[this.id];
|
|
19
|
+
return applyFilter(ruleConfig, packages, ({ name }) => name)
|
|
20
|
+
.map(pkg => this.checkDependencies(pkg))
|
|
21
|
+
.filter(error => !!error);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fix({ data }: PackageError<ErrorData>, project: Project) {
|
|
25
|
+
const { missing, packageName, version } = data ?? {};
|
|
26
|
+
if (!(missing?.length && packageName && version)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
missing.forEach(dependency => {
|
|
31
|
+
setVersion({ project, packageName, dependency, version, key: 'dependencies' });
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private checkDependencies(pkg: Package): PackageError<ErrorData> | undefined {
|
|
36
|
+
const { dependencies = {}, name } = pkg;
|
|
37
|
+
const present = REACT_DEPENDENCIES.filter(name => !!dependencies[name]);
|
|
38
|
+
if (present.length === 0 || present.length === REACT_DEPENDENCIES.length) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const missing = REACT_DEPENDENCIES.filter(name => !dependencies[name]);
|
|
43
|
+
const message = `package "${name}" depends on ${present[0]} but not on ${formatList(missing)}`;
|
|
44
|
+
const version = getMaxVersion(present.map(name => dependencies[name]));
|
|
45
|
+
return {
|
|
46
|
+
id: this.id,
|
|
47
|
+
message,
|
|
48
|
+
location: pkg.location,
|
|
49
|
+
fixable: FixCategory.isolated,
|
|
50
|
+
data: { missing, packageName: name, version },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RequireOneCollectionVersion } from './require-one-collection-version';
|
|
2
|
+
|
|
3
|
+
const REACT_PACKAGES = ['react', 'react-dom'];
|
|
4
|
+
|
|
5
|
+
export class RequireOneReactVersion extends RequireOneCollectionVersion {
|
|
6
|
+
constructor() {
|
|
7
|
+
super({ name: 'react', packages: REACT_PACKAGES });
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -2,6 +2,7 @@ import { RequireOneCollectionVersion } from './require-one-collection-version';
|
|
|
2
2
|
|
|
3
3
|
const UIKIT_PACKAGES = [
|
|
4
4
|
'@servicetitan/ajax-handlers',
|
|
5
|
+
'@servicetitan/datadog-rum',
|
|
5
6
|
'@servicetitan/error-boundary',
|
|
6
7
|
'@servicetitan/eslint-config',
|
|
7
8
|
'@servicetitan/eslint-plugin',
|
|
@@ -7,25 +7,23 @@ import { setVersion } from '../set-version';
|
|
|
7
7
|
jest.mock('child_process', () => ({ execSync: jest.fn() }));
|
|
8
8
|
|
|
9
9
|
describe(`[startup] Review ${setVersion.name}`, () => {
|
|
10
|
+
const packageName = 'lib1';
|
|
11
|
+
const dependency = 'foo';
|
|
12
|
+
const version = '2.0.0';
|
|
10
13
|
let pkg: Package;
|
|
11
|
-
let
|
|
12
|
-
let dependency: string;
|
|
13
|
-
let version: string;
|
|
14
|
+
let params: Parameters<typeof setVersion>[0];
|
|
14
15
|
|
|
15
16
|
beforeEach(() => {
|
|
16
|
-
packageName = 'lib1';
|
|
17
|
-
dependency = 'foo';
|
|
18
|
-
version = '2.0.0';
|
|
19
17
|
pkg = {
|
|
20
18
|
name: packageName,
|
|
21
19
|
location: path.normalize(`packages/${packageName}`),
|
|
22
20
|
dependencies: { [dependency]: '1.0.0' },
|
|
23
21
|
};
|
|
22
|
+
params = { project: { packages: [pkg] } as any, packageName, dependency, version };
|
|
24
23
|
jest.clearAllMocks();
|
|
25
24
|
});
|
|
26
25
|
|
|
27
|
-
const subject = () =>
|
|
28
|
-
setVersion({ project: { packages: [pkg] } as any, packageName, dependency, version });
|
|
26
|
+
const subject = () => setVersion(params);
|
|
29
27
|
|
|
30
28
|
function itDoesNothing() {
|
|
31
29
|
test('does nothing', () => {
|
|
@@ -74,6 +72,18 @@ describe(`[startup] Review ${setVersion.name}`, () => {
|
|
|
74
72
|
beforeEach(() => delete pkg.dependencies);
|
|
75
73
|
|
|
76
74
|
itDoesNothing();
|
|
75
|
+
|
|
76
|
+
describe('when key is specified', () => {
|
|
77
|
+
beforeEach(() => (params.key = 'dependencies'));
|
|
78
|
+
|
|
79
|
+
test('sets dependency version', () => {
|
|
80
|
+
subject();
|
|
81
|
+
|
|
82
|
+
expect(execSync).toHaveBeenCalledWith(
|
|
83
|
+
`npm pkg set ${params.key}["${dependency}"]="${version}" -w ${pkg.location}`
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
77
87
|
});
|
|
78
88
|
|
|
79
89
|
describe('when package is missing', () => {
|
|
@@ -2,10 +2,13 @@ const collator = new Intl.Collator();
|
|
|
2
2
|
|
|
3
3
|
export function formatDependsOn(dependents: string[], dependency: string) {
|
|
4
4
|
const { length } = dependents;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
return length === 1
|
|
6
|
+
? `${dependents[0]} depends on ${dependency}`
|
|
7
|
+
: `${formatList(dependents.toSorted((a, b) => collator.compare(a, b)))} depend on ${dependency}`;
|
|
8
|
+
}
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
return
|
|
10
|
+
export function formatList(items: string[]) {
|
|
11
|
+
return items.length > 1
|
|
12
|
+
? `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`
|
|
13
|
+
: items[0];
|
|
11
14
|
}
|
|
@@ -8,14 +8,22 @@ interface Params {
|
|
|
8
8
|
packageName: string;
|
|
9
9
|
dependency: string;
|
|
10
10
|
version: string;
|
|
11
|
+
key?: string;
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
|
|
14
|
+
export function setVersion(params: Params) {
|
|
15
|
+
const {
|
|
16
|
+
project: { packages },
|
|
17
|
+
packageName,
|
|
18
|
+
dependency,
|
|
19
|
+
version,
|
|
20
|
+
} = params;
|
|
13
21
|
const pkg = packages.find(({ name }) => name === packageName);
|
|
14
22
|
if (!pkg) {
|
|
15
23
|
return;
|
|
16
24
|
}
|
|
17
25
|
|
|
18
|
-
const key = getKey(pkg, dependency);
|
|
26
|
+
const key = params.key ?? getKey(pkg, dependency);
|
|
19
27
|
if (!key) {
|
|
20
28
|
return;
|
|
21
29
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { getConfiguration } from '../../../../utils';
|
|
2
|
+
import { Jest, Vitest } from '../runners';
|
|
3
|
+
import { Tests } from '../tests';
|
|
4
|
+
|
|
5
|
+
jest.mock('../runners');
|
|
6
|
+
jest.mock('../../../../utils', () => ({
|
|
7
|
+
...jest.requireActual('../../../../utils'),
|
|
8
|
+
getConfiguration: jest.fn(),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
type TestArgs = ConstructorParameters<typeof Tests>[0];
|
|
12
|
+
|
|
13
|
+
describe(`[startup] ${Tests.name}`, () => {
|
|
14
|
+
let args: TestArgs;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
18
|
+
args = { _: ['foo'], $0: 'bar' };
|
|
19
|
+
jest.mocked(getConfiguration).mockReturnValue({});
|
|
20
|
+
jest.clearAllMocks();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const subject = async () => new Tests(args).execute();
|
|
24
|
+
|
|
25
|
+
test('command is greedy', () => {
|
|
26
|
+
expect(new Tests(args).greedy).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function itRunsJest() {
|
|
30
|
+
test('runs Jest', async () => {
|
|
31
|
+
await subject();
|
|
32
|
+
|
|
33
|
+
const { runner, ...rest } = args;
|
|
34
|
+
expect(Jest).toHaveBeenCalledWith(rest);
|
|
35
|
+
expect(jest.mocked(Jest).mock.instances[0].run).toHaveBeenCalled();
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function itRunsVitest() {
|
|
40
|
+
test('runs Vitest', async () => {
|
|
41
|
+
await subject();
|
|
42
|
+
|
|
43
|
+
expect(Vitest).toHaveBeenCalled();
|
|
44
|
+
expect(jest.mocked(Vitest).mock.instances[0].run).toHaveBeenCalled();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
itRunsJest();
|
|
49
|
+
|
|
50
|
+
describe('with --runner=vitest', () => {
|
|
51
|
+
beforeEach(() => (args.runner = 'vitest'));
|
|
52
|
+
|
|
53
|
+
itRunsVitest();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('with unrecognized --runner', () => {
|
|
57
|
+
beforeEach(() => (args.runner = 'foo' as any));
|
|
58
|
+
|
|
59
|
+
test('throws error', () => {
|
|
60
|
+
jest.spyOn(process.stdout, 'write').mockImplementation(jest.fn()); // suppress error output
|
|
61
|
+
expect(subject).rejects.toThrow('unrecognized runner "foo"');
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('with {testRunner: "vitest"}', () => {
|
|
66
|
+
beforeEach(() => {
|
|
67
|
+
jest.mocked(getConfiguration).mockReturnValue({ testRunner: 'vitest' });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
itRunsVitest();
|
|
71
|
+
|
|
72
|
+
describe('with --runner=jest', () => {
|
|
73
|
+
beforeEach(() => (args.runner = 'jest'));
|
|
74
|
+
|
|
75
|
+
itRunsJest();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './tests';
|
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
import { runCLI } from '@jest/core';
|
|
2
|
-
import { Config } from '@jest/types';
|
|
3
|
-
import { getJestConfigCLI } from '../../../utils';
|
|
4
2
|
|
|
5
|
-
import {
|
|
3
|
+
import { Jest } from '../jest';
|
|
4
|
+
import { getJestConfigCLI } from '../../../../../utils';
|
|
6
5
|
|
|
7
6
|
jest.mock('@jest/core', () => ({ runCLI: jest.fn() }));
|
|
8
|
-
jest.mock('
|
|
9
|
-
...jest.requireActual('
|
|
7
|
+
jest.mock('../../../../../utils', () => ({
|
|
8
|
+
...jest.requireActual('../../../../../utils'),
|
|
10
9
|
getJestConfigCLI: jest.fn(),
|
|
11
10
|
}));
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
type JestArgs = ConstructorParameters<typeof Jest>[0];
|
|
13
|
+
|
|
14
|
+
describe(`[startup] Test ${Jest.name}`, () => {
|
|
14
15
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
15
|
-
const args:
|
|
16
|
-
const jestConfig:
|
|
16
|
+
const args: JestArgs = { _: ['foo'], $0: 'bar' };
|
|
17
|
+
const jestConfig: JestArgs = { ...args, setupFilesAfterEnv: ['./setupTests.js'] };
|
|
17
18
|
|
|
18
19
|
beforeAll(() => {
|
|
19
20
|
jest.mocked(getJestConfigCLI).mockReturnValue(jestConfig);
|
|
20
21
|
jest.mocked(runCLI).mockResolvedValue({ results: { success: true } } as any);
|
|
21
22
|
});
|
|
22
23
|
|
|
23
|
-
const subject = async () => new
|
|
24
|
-
|
|
25
|
-
test('command is greedy', () => {
|
|
26
|
-
expect(new Tests(args).greedy).toBe(true);
|
|
27
|
-
});
|
|
24
|
+
const subject = async () => new Jest(args).run();
|
|
28
25
|
|
|
29
26
|
test('runs Jest CLI', async () => {
|
|
30
27
|
await subject();
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import deepmerge from 'deepmerge';
|
|
2
|
+
import { fs, vol } from 'memfs';
|
|
3
|
+
import { configDefaults, coverageConfigDefaults, mergeConfig, ViteUserConfig } from 'vitest/config';
|
|
4
|
+
import { parseCLI, resolveConfig, startVitest } from 'vitest/node';
|
|
5
|
+
import { Vitest } from '../vitest';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mocking "vitest/" includes all vite and vitest entry points because there is
|
|
9
|
+
* one identity-obj-proxy for "^(vite|vitest)/" @see cli.test.moduleNameMapper
|
|
10
|
+
* in {@link file://./../../../../../../../../package.json}
|
|
11
|
+
*/
|
|
12
|
+
jest.mock('vitest/', () => ({
|
|
13
|
+
configDefaults: { exclude: ['node_modules'] },
|
|
14
|
+
coverageConfigDefaults: { exclude: ['node_modules'] },
|
|
15
|
+
mergeConfig: jest.fn(),
|
|
16
|
+
parseCLI: jest.fn(),
|
|
17
|
+
resolveConfig: jest.fn(),
|
|
18
|
+
startVitest: jest.fn(),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
jest.mock('fs', () => fs);
|
|
22
|
+
|
|
23
|
+
describe(`[startup] Test ${Vitest.name}`, () => {
|
|
24
|
+
const defaultConfig: ViteUserConfig['test'] = {
|
|
25
|
+
coverage: {
|
|
26
|
+
include: ['**/*.{ts,tsx}'],
|
|
27
|
+
exclude: [
|
|
28
|
+
...coverageConfigDefaults.exclude,
|
|
29
|
+
'**/__mocks__/**',
|
|
30
|
+
'**/*.stories.*',
|
|
31
|
+
'\\.yalc',
|
|
32
|
+
],
|
|
33
|
+
reporter: ['html-spa', 'text', 'json', 'cobertura', 'lcov'],
|
|
34
|
+
},
|
|
35
|
+
environment: 'jsdom',
|
|
36
|
+
exclude: [...configDefaults.exclude, '\\.yalc'],
|
|
37
|
+
restoreMocks: true,
|
|
38
|
+
server: { deps: { inline: ['@servicetitan/anvil2'] } },
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
|
|
44
|
+
jest.mocked(mergeConfig).mockImplementation((a, b) => deepmerge(a, b));
|
|
45
|
+
jest.mocked(parseCLI).mockReturnValue({ filter: [], options: {} });
|
|
46
|
+
jest.mocked(resolveConfig).mockResolvedValue({ viteConfig: {} } as any);
|
|
47
|
+
jest.mocked(startVitest).mockResolvedValue({ close: jest.fn() } as any);
|
|
48
|
+
|
|
49
|
+
vol.fromJSON({ 'package.json': JSON.stringify({}) });
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
afterEach(() => vol.reset());
|
|
53
|
+
|
|
54
|
+
const subject = async () => new Vitest().run();
|
|
55
|
+
|
|
56
|
+
test('runs startVitest with default config', async () => {
|
|
57
|
+
await subject();
|
|
58
|
+
|
|
59
|
+
expect(startVitest).toHaveBeenCalledWith('test', [], {}, { test: defaultConfig });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('closes vitest', async () => {
|
|
63
|
+
await subject();
|
|
64
|
+
|
|
65
|
+
const vitest = await jest.mocked(startVitest).mock.results[0].value;
|
|
66
|
+
expect(vitest.close).toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('with package.json config', () => {
|
|
70
|
+
const packageJSONConfig: ViteUserConfig['test'] = { bail: 1, globals: false };
|
|
71
|
+
|
|
72
|
+
beforeEach(() => {
|
|
73
|
+
vol.fromJSON({
|
|
74
|
+
'package.json': JSON.stringify({ cli: { vitest: packageJSONConfig } }),
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('merges package.json config with default config', async () => {
|
|
79
|
+
await subject();
|
|
80
|
+
|
|
81
|
+
expect(startVitest).toHaveBeenCalledWith(
|
|
82
|
+
'test',
|
|
83
|
+
[],
|
|
84
|
+
{},
|
|
85
|
+
{ test: { ...defaultConfig, ...packageJSONConfig } }
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('with vite test config', () => {
|
|
91
|
+
const viteTestConfig: ViteUserConfig['test'] = { name: 'foo', watch: false };
|
|
92
|
+
|
|
93
|
+
beforeEach(() => {
|
|
94
|
+
jest.mocked(resolveConfig).mockResolvedValue({
|
|
95
|
+
viteConfig: { test: viteTestConfig },
|
|
96
|
+
} as any);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('merges vite test config with default config', async () => {
|
|
100
|
+
await subject();
|
|
101
|
+
|
|
102
|
+
expect(startVitest).toHaveBeenCalledWith(
|
|
103
|
+
'test',
|
|
104
|
+
[],
|
|
105
|
+
{},
|
|
106
|
+
{ test: { ...defaultConfig, ...viteTestConfig } }
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('with command line options', () => {
|
|
112
|
+
const originalArgv = process.argv;
|
|
113
|
+
const cliOptions = ['--mode=foo', 'foo'];
|
|
114
|
+
|
|
115
|
+
beforeEach(() => {
|
|
116
|
+
process.argv = ['node', 'startup', 'test', ...cliOptions];
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
afterEach(() => (process.argv = originalArgv));
|
|
120
|
+
|
|
121
|
+
test('runs startVitest with parsed options', async () => {
|
|
122
|
+
const parseCliResult: ReturnType<typeof parseCLI> = {
|
|
123
|
+
filter: ['foo'],
|
|
124
|
+
options: { mode: 'foo' },
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
jest.mocked(parseCLI).mockReturnValue(parseCliResult);
|
|
128
|
+
|
|
129
|
+
await subject();
|
|
130
|
+
|
|
131
|
+
expect(parseCLI).toHaveBeenCalledWith(['vitest', ...cliOptions]);
|
|
132
|
+
expect(startVitest).toHaveBeenCalledWith(
|
|
133
|
+
'test',
|
|
134
|
+
parseCliResult.filter,
|
|
135
|
+
parseCliResult.options,
|
|
136
|
+
expect.anything()
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe.each(['--runner <name>', '--runner=<name>'])('with %s', args => {
|
|
141
|
+
beforeEach(() => (process.argv = [...process.argv, ...args.split(' ')]));
|
|
142
|
+
|
|
143
|
+
test('omits "runner" from parseCLI arguments', async () => {
|
|
144
|
+
await subject();
|
|
145
|
+
|
|
146
|
+
expect(parseCLI).toHaveBeenCalledWith(['vitest', ...cliOptions]);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|