@servicetitan/startup 22.14.0 → 22.16.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.
Files changed (112) hide show
  1. package/dist/cli/__mocks__/create-package.d.ts +3 -0
  2. package/dist/cli/__mocks__/create-package.d.ts.map +1 -0
  3. package/dist/cli/__mocks__/create-package.js +9 -0
  4. package/dist/cli/__mocks__/create-package.js.map +1 -0
  5. package/dist/cli/__mocks__/index.d.ts +2 -0
  6. package/dist/cli/__mocks__/index.d.ts.map +1 -0
  7. package/dist/cli/__mocks__/index.js +18 -0
  8. package/dist/cli/__mocks__/index.js.map +1 -0
  9. package/dist/cli/commands/eslint.d.ts +12 -0
  10. package/dist/cli/commands/eslint.d.ts.map +1 -0
  11. package/dist/cli/commands/eslint.js +47 -0
  12. package/dist/cli/commands/eslint.js.map +1 -0
  13. package/dist/cli/commands/index.d.ts +1 -0
  14. package/dist/cli/commands/index.d.ts.map +1 -1
  15. package/dist/cli/commands/index.js +1 -0
  16. package/dist/cli/commands/index.js.map +1 -1
  17. package/dist/cli/commands/lint.d.ts +5 -0
  18. package/dist/cli/commands/lint.d.ts.map +1 -1
  19. package/dist/cli/commands/lint.js +22 -30
  20. package/dist/cli/commands/lint.js.map +1 -1
  21. package/dist/cli/index.js +20 -6
  22. package/dist/cli/index.js.map +1 -1
  23. package/dist/cli/utils/eslint.d.ts +7 -0
  24. package/dist/cli/utils/eslint.d.ts.map +1 -0
  25. package/dist/cli/utils/eslint.js +57 -0
  26. package/dist/cli/utils/eslint.js.map +1 -0
  27. package/dist/cli/utils/index.d.ts +2 -0
  28. package/dist/cli/utils/index.d.ts.map +1 -1
  29. package/dist/cli/utils/index.js +2 -0
  30. package/dist/cli/utils/index.js.map +1 -1
  31. package/dist/cli/utils/set-node-options.d.ts +7 -0
  32. package/dist/cli/utils/set-node-options.d.ts.map +1 -0
  33. package/dist/cli/utils/set-node-options.js +46 -0
  34. package/dist/cli/utils/set-node-options.js.map +1 -0
  35. package/dist/cli/utils/tcm.d.ts.map +1 -1
  36. package/dist/cli/utils/tcm.js +3 -1
  37. package/dist/cli/utils/tcm.js.map +1 -1
  38. package/dist/utils/get-configuration.d.ts +5 -1
  39. package/dist/utils/get-configuration.d.ts.map +1 -1
  40. package/dist/utils/get-configuration.js +2 -2
  41. package/dist/utils/get-configuration.js.map +1 -1
  42. package/dist/utils/get-jest-config.d.ts +1 -1
  43. package/dist/utils/get-jest-config.d.ts.map +1 -1
  44. package/dist/utils/get-jest-config.js +8 -6
  45. package/dist/utils/get-jest-config.js.map +1 -1
  46. package/dist/utils/get-package-data.js +3 -3
  47. package/dist/utils/get-package-data.js.map +1 -1
  48. package/dist/utils/get-package-name.d.ts.map +1 -1
  49. package/dist/utils/get-package-name.js +2 -2
  50. package/dist/utils/get-package-name.js.map +1 -1
  51. package/dist/utils/get-packages.js +8 -7
  52. package/dist/utils/get-packages.js.map +1 -1
  53. package/dist/webpack/shared.config.d.ts.map +1 -1
  54. package/dist/webpack/shared.config.js +1 -0
  55. package/dist/webpack/shared.config.js.map +1 -1
  56. package/package.json +4 -4
  57. package/src/cli/__mocks__/create-package.ts +12 -0
  58. package/src/cli/__mocks__/index.ts +1 -0
  59. package/src/cli/commands/__tests__/build.test.ts +135 -0
  60. package/src/cli/commands/__tests__/bundle-package.test.ts +72 -0
  61. package/src/cli/commands/__tests__/eslint.test.ts +19 -0
  62. package/src/cli/commands/__tests__/init.test.ts +42 -0
  63. package/src/cli/commands/__tests__/lint.test.ts +114 -0
  64. package/src/cli/commands/__tests__/mfe-package-clean.test.ts +193 -0
  65. package/src/cli/commands/__tests__/mfe-package-publish.test.ts +192 -0
  66. package/src/cli/commands/__tests__/mfe-publish.test.ts +172 -0
  67. package/src/cli/commands/__tests__/prepare-package.test.ts +75 -0
  68. package/src/cli/commands/__tests__/start.test.ts +111 -0
  69. package/src/cli/commands/__tests__/styles-check.test.ts +119 -0
  70. package/src/cli/commands/__tests__/tests.test.ts +43 -0
  71. package/src/cli/commands/eslint.ts +19 -0
  72. package/src/cli/commands/index.ts +1 -0
  73. package/src/cli/commands/lint.ts +29 -42
  74. package/src/cli/index.ts +17 -5
  75. package/src/cli/utils/__tests__/assets-copy.test.ts +48 -52
  76. package/src/cli/utils/__tests__/bundle.test.ts +361 -0
  77. package/src/cli/utils/__tests__/cli-git.test.ts +28 -0
  78. package/src/cli/utils/__tests__/cli-npm.test.ts +166 -0
  79. package/src/cli/utils/__tests__/cli-os.test.ts +103 -0
  80. package/src/cli/utils/__tests__/eslint.test.ts +91 -0
  81. package/src/cli/utils/__tests__/get-module-type.test.ts +56 -0
  82. package/src/cli/utils/__tests__/is-module-installed.test.ts +24 -0
  83. package/src/cli/utils/__tests__/set-node-options.test.ts +131 -0
  84. package/src/cli/utils/__tests__/styles-copy.test.ts +48 -44
  85. package/src/cli/utils/__tests__/tcm.test.ts +101 -192
  86. package/src/cli/utils/__tests__/tsc.test.ts +85 -0
  87. package/src/cli/utils/eslint.ts +50 -0
  88. package/src/cli/utils/index.ts +2 -0
  89. package/src/cli/utils/set-node-options.ts +45 -0
  90. package/src/cli/utils/tcm.ts +3 -1
  91. package/src/utils/__tests__/get-configuration.test.ts +215 -16
  92. package/src/utils/__tests__/get-destination-folders.test.ts +65 -0
  93. package/src/utils/__tests__/get-jest-config.test.ts +134 -0
  94. package/src/utils/__tests__/get-package-data.test.ts +90 -0
  95. package/src/utils/__tests__/get-packages.test.ts +165 -0
  96. package/src/utils/__tests__/get-tsconfig.test.ts +48 -0
  97. package/src/utils/__tests__/log.test.ts +123 -0
  98. package/src/utils/__tests__/to-array.test.ts +19 -0
  99. package/src/utils/get-configuration.ts +8 -3
  100. package/src/utils/get-jest-config.ts +3 -1
  101. package/src/utils/get-package-data.ts +1 -1
  102. package/src/utils/get-package-name.ts +1 -2
  103. package/src/utils/get-packages.ts +2 -2
  104. package/src/webpack/shared.config.ts +1 -0
  105. package/template/package.json +8 -1
  106. package/template/packages/application/package.json +5 -0
  107. package/template/packages/application/src/__tests__/app.test.tsx +33 -0
  108. package/template/packages/application/src/app.tsx +9 -6
  109. package/template/packages/application/src/main-page.tsx +5 -0
  110. package/template/packages/application/src/second-page.tsx +5 -0
  111. package/template/setupTests.ts +27 -0
  112. package/template/tsconfig.test.json +1 -1
@@ -1,31 +1,230 @@
1
- import mock from 'mock-fs';
1
+ import mockFS from 'mock-fs';
2
+ import {
3
+ getConfiguration,
4
+ getDevServerConfiguration,
5
+ getESLintConfiguration,
6
+ getJestConfiguration,
7
+ getStylelintConfiguration,
8
+ isBundle,
9
+ isCustomStyleRules,
10
+ isExposeSharedDependencies,
11
+ isLegacy,
12
+ isStyleCheckDisabled,
13
+ isWebComponent,
14
+ } from '../get-configuration';
15
+ import WebpackDevServer from 'webpack-dev-server';
2
16
 
3
- import { isBundle } from '..';
17
+ describe('[startup] Utils', () => {
18
+ const packageJson = 'package.json';
4
19
 
5
- describe('[Startup] utils:get-configuration', () => {
6
- afterAll(() => {
7
- mock.restore();
20
+ function packageJsonFS(content: Record<string, any> = {}) {
21
+ return { [packageJson]: JSON.stringify(content) };
22
+ }
23
+
24
+ function mockPackageJson(content: Record<string, any> = {}) {
25
+ mockFS(packageJsonFS(content));
26
+ }
27
+
28
+ function itReturns(subject: Function, value: any) {
29
+ test(`returns ${JSON.stringify(value)}`, () => expect(subject()).toEqual(value));
30
+ }
31
+
32
+ beforeEach(() => mockPackageJson());
33
+
34
+ afterEach(() => mockFS.restore());
35
+
36
+ describe(`${getConfiguration.name}`, () => {
37
+ let location: string | undefined;
38
+
39
+ beforeEach(() => (location = undefined));
40
+
41
+ const subject = () => getConfiguration(location);
42
+
43
+ itReturns(subject, {});
44
+
45
+ describe(`when ${packageJson} contains cli`, () => {
46
+ const cli = { foo: 'bar' };
47
+
48
+ beforeEach(() => mockPackageJson({ cli }));
49
+
50
+ test('returns cli', () => expect(subject()).toEqual(cli));
51
+ });
52
+
53
+ describe('with a location', () => {
54
+ const cli = { baz: 'qux' };
55
+
56
+ beforeEach(() => {
57
+ location = 'packages/foo';
58
+ mockFS({ packages: { foo: { [packageJson]: JSON.stringify({ cli }) } } });
59
+ });
60
+
61
+ test("returns location's cli", () => {
62
+ expect(subject()).toEqual(cli);
63
+ });
64
+ });
65
+ });
66
+
67
+ describe(`${getDevServerConfiguration.name}`, () => {
68
+ const subject = () => getDevServerConfiguration();
69
+
70
+ itReturns(subject, undefined);
71
+
72
+ describe('with "cli.webpack"', () => {
73
+ const webpack: WebpackDevServer.Configuration = {
74
+ // allowed options
75
+ contentBase: 'foo',
76
+ headers: { foo: 'bar' },
77
+ port: 9000,
78
+ proxy: { baz: 'qux' },
79
+ // example disallowed options
80
+ compress: true,
81
+ clientLogLevel: 'debug',
82
+ };
83
+
84
+ beforeEach(() => mockPackageJson({ cli: { webpack } }));
85
+
86
+ test('returns allowed options from "cli.webpack', () => {
87
+ const { contentBase, headers, port, proxy } = webpack;
88
+ expect(subject()).toEqual({ contentBase, headers, port, proxy });
89
+ });
90
+
91
+ describe('when "cli.webpack.proxy" is a path', () => {
92
+ const proxy = 'proxy.json';
93
+ const proxyConfig = { cli: { webpack: { ...webpack, proxy } } };
94
+
95
+ beforeEach(() => mockPackageJson(proxyConfig));
96
+
97
+ describe('when file does not exist', () => {
98
+ test('drops the proxy option', () => {
99
+ expect(subject()?.proxy).toBeUndefined();
100
+ });
101
+ });
102
+
103
+ describe('when file exists', () => {
104
+ beforeEach(() => {
105
+ mockFS({
106
+ ...packageJsonFS(proxyConfig),
107
+ [proxy]: JSON.stringify(webpack.proxy),
108
+ // Need node_modules so Jest can require() json file
109
+ // eslint-disable-next-line @typescript-eslint/naming-convention
110
+ node_modules: mockFS.load('./node_modules'),
111
+ });
112
+ });
113
+
114
+ test('loads proxy option from the file', () => {
115
+ expect(subject()?.proxy).toEqual(webpack.proxy);
116
+ });
117
+ });
118
+ });
119
+ });
8
120
  });
9
121
 
10
- beforeEach(() => {
11
- mock({
12
- 'package.json': JSON.stringify({}),
122
+ describe(`${getESLintConfiguration.name}`, () => {
123
+ const subject = () => getESLintConfiguration();
124
+
125
+ itReturns(subject, {});
126
+
127
+ describe('with "cli.lint.eslint"', () => {
128
+ const content = { cli: { lint: { eslint: { foo: 'bar' } } } };
129
+
130
+ beforeEach(() => mockPackageJson(content));
131
+
132
+ test('returns "cli.lint.eslint"', () => {
133
+ expect(subject()).toEqual(content.cli.lint.eslint);
134
+ });
13
135
  });
14
136
  });
15
137
 
16
- test('isBundle returns true if not explicitly disabled', () => {
17
- expect(isBundle()).toBeTruthy();
138
+ describe(`${getJestConfiguration.name}`, () => {
139
+ const subject = () => getJestConfiguration();
18
140
 
19
- mock({
20
- 'package.json': JSON.stringify({ cli: { webpack: true } }),
141
+ itReturns(subject, {});
142
+
143
+ describe('with "cli.test"', () => {
144
+ const content = { cli: { test: { foo: 'bar' } } };
145
+
146
+ beforeEach(() => mockPackageJson(content));
147
+
148
+ test('returns "cli.test"', () => {
149
+ expect(subject()).toEqual(content.cli.test);
150
+ });
21
151
  });
152
+ });
153
+
154
+ describe(`${getStylelintConfiguration.name}`, () => {
155
+ const subject = () => getStylelintConfiguration();
156
+
157
+ itReturns(subject, {});
22
158
 
23
- expect(isBundle()).toBeTruthy();
159
+ describe('with "cli.lint.stylelint"', () => {
160
+ const content = { cli: { lint: { stylelint: { foo: 'bar' } } } };
24
161
 
25
- mock({
26
- 'package.json': JSON.stringify({ cli: { webpack: false } }),
162
+ beforeEach(() => mockPackageJson(content));
163
+
164
+ test('returns "cli.lint.stylelint"', () => {
165
+ expect(subject()).toEqual(content.cli.lint.stylelint);
166
+ });
167
+ });
168
+ });
169
+
170
+ describe.each([
171
+ {
172
+ fn: isBundle,
173
+ defaultValue: true,
174
+ trigger: { cli: { webpack: false } },
175
+ },
176
+ {
177
+ fn: isCustomStyleRules,
178
+ defaultValue: false,
179
+ trigger: { cli: { webpack: { 'custom-style-rules': true } } },
180
+ },
181
+ {
182
+ fn: isExposeSharedDependencies,
183
+ defaultValue: false,
184
+ trigger: { cli: { webpack: { 'expose-shared-dependencies': true } } },
185
+ },
186
+ {
187
+ fn: isLegacy,
188
+ defaultValue: false,
189
+ trigger: { cli: { legacy: true } },
190
+ },
191
+ {
192
+ fn: isStyleCheckDisabled,
193
+ defaultValue: false,
194
+ trigger: { cli: { webpack: { 'disable-style-check': true } } },
195
+ },
196
+ {
197
+ fn: isWebComponent,
198
+ defaultValue: false,
199
+ trigger: { cli: { 'web-component': true } },
200
+ },
201
+ ])('$fn.name', ({ fn, defaultValue, trigger }) => {
202
+ itReturns(fn, defaultValue);
203
+
204
+ describe(`when ${packageJson} contains ${JSON.stringify(trigger)}`, () => {
205
+ beforeEach(() => mockPackageJson(trigger));
206
+
207
+ itReturns(fn, !defaultValue);
27
208
  });
209
+ });
210
+
211
+ describe(`${isLegacy.name}`, () => {
212
+ const trigger = { cli: { legacy: true } };
213
+ let location: string | undefined;
214
+
215
+ beforeEach(() => (location = undefined));
28
216
 
29
- expect(isBundle()).toBeFalsy();
217
+ const subject = () => isLegacy(location);
218
+
219
+ describe('with a location', () => {
220
+ beforeEach(() => {
221
+ location = 'packages/foo';
222
+ mockFS({ packages: { foo: { [packageJson]: JSON.stringify(trigger) } } });
223
+ });
224
+
225
+ test("returns location's status", () => {
226
+ expect(subject()).toBe(true);
227
+ });
228
+ });
30
229
  });
31
230
  });
@@ -0,0 +1,65 @@
1
+ import fs from 'fs';
2
+ import mockFS from 'mock-fs';
3
+ import { getPackages } from '../get-packages';
4
+
5
+ import { getDestinationFolders } from '../get-destination-folders';
6
+
7
+ jest.mock('../get-packages', () => ({ getPackages: jest.fn() }));
8
+
9
+ describe('[startup] Utils', () => {
10
+ describe(`${getDestinationFolders.name}`, () => {
11
+ let locations: string[];
12
+
13
+ beforeEach(() => {
14
+ locations = ['foo', 'bar'];
15
+ mockFS(packageFS(locations));
16
+ jest.mocked(getPackages).mockImplementation((): any =>
17
+ locations.map(location => ({ location: `packages/${location}` }))
18
+ );
19
+ });
20
+
21
+ afterEach(() => mockFS.restore());
22
+
23
+ const subject = () => getDestinationFolders();
24
+
25
+ function packageFS(locations: string[]) {
26
+ const packages = Object.fromEntries(
27
+ locations.map(location => [
28
+ location,
29
+ {
30
+ 'tsconfig.json': JSON.stringify({
31
+ compilerOptions: { outDir: `${location}outDir` },
32
+ }),
33
+ },
34
+ ])
35
+ );
36
+ return { packages };
37
+ }
38
+
39
+ function expectedOutDirs(locations: string[]) {
40
+ return locations.map(location => `/packages/${location}/${location}outDir/`);
41
+ }
42
+
43
+ test('returns outDir path for all packages', () => {
44
+ expect(subject()).toEqual(expectedOutDirs(locations));
45
+ });
46
+
47
+ describe('when package has no tsconfig', () => {
48
+ beforeEach(() => mockFS(packageFS(locations.slice(1))));
49
+
50
+ test('omits location from result', () => {
51
+ expect(subject()).toEqual(expectedOutDirs(locations.slice(1)));
52
+ });
53
+ });
54
+
55
+ describe('when tsconfig has no "outDir"', () => {
56
+ beforeEach(() => {
57
+ fs.writeFileSync(`packages/${locations[0]}/tsconfig.json`, JSON.stringify({}));
58
+ });
59
+
60
+ test('omits location from result', () => {
61
+ expect(subject()).toEqual(expectedOutDirs(locations.slice(1)));
62
+ });
63
+ });
64
+ });
65
+ });
@@ -0,0 +1,134 @@
1
+ import { Config } from '@jest/types';
2
+ import { getJestConfiguration } from '../get-configuration';
3
+ import { getDestinationFolders } from '../get-destination-folders';
4
+
5
+ import { getJestConfig, getJestConfigCLI } from '../get-jest-config';
6
+
7
+ jest.mock('../get-destination-folders');
8
+ jest.mock('../get-configuration', () => ({
9
+ ...jest.requireActual('../get-configuration'),
10
+ getJestConfiguration: jest.fn(),
11
+ }));
12
+
13
+ describe('[startup] Utils', () => {
14
+ const destinationFolders = ['dist'];
15
+ const defaultConfig = {
16
+ verbose: true,
17
+ testEnvironment: 'jsdom',
18
+ testRunner: 'jest-circus/runner',
19
+ transformIgnorePatterns: ['node_modules/(?!@servicetitan/)'],
20
+ modulePathIgnorePatterns: ['<rootDir>/.*/__mocks__'],
21
+ transform: {
22
+ '^.+\\.jsx?$': [
23
+ 'babel-jest',
24
+ { presets: [['@babel/preset-env', { targets: { node: 'current' } }]] },
25
+ ],
26
+ '^.+\\.tsx?$': 'ts-jest',
27
+ },
28
+ moduleNameMapper: {
29
+ '\\.(css|scss|less|png|svg|jpg|jpeg|gif|woff|woff2|eot|ttf|otf)$': 'identity-obj-proxy',
30
+ },
31
+ globals: { 'ts-jest': { tsconfig: './tsconfig.test.json' } },
32
+ testPathIgnorePatterns: ['\\.yalc', ...destinationFolders],
33
+ setupFiles: [expect.stringMatching(/jest\/setup\.js/)],
34
+ coveragePathIgnorePatterns: ['^.+\\.d\\.ts$'],
35
+ coverageReporters: ['html-spa', 'text', 'json', 'cobertura'],
36
+ collectCoverageFrom: ['**/*.{ts,tsx}'],
37
+ };
38
+
39
+ beforeEach(() => {
40
+ jest.mocked(getDestinationFolders).mockReturnValue(destinationFolders);
41
+ jest.mocked(getJestConfiguration).mockReturnValue({});
42
+ });
43
+
44
+ describe(`${getJestConfig.name}`, () => {
45
+ const subject = () => getJestConfig();
46
+
47
+ test('returns default config', () => {
48
+ expect(subject()).toEqual(defaultConfig);
49
+ });
50
+
51
+ describe.each(['coveragePathIgnorePatterns', 'setupFiles', 'testPathIgnorePatterns'])(
52
+ 'with custom "%s"',
53
+ (
54
+ option: keyof Pick<
55
+ typeof defaultConfig,
56
+ 'coveragePathIgnorePatterns' | 'setupFiles' | 'testPathIgnorePatterns'
57
+ >
58
+ ) => {
59
+ const customValue = ['foo', 'bar'];
60
+
61
+ beforeEach(() => {
62
+ jest.mocked(getJestConfiguration).mockReturnValue({ [option]: customValue });
63
+ });
64
+
65
+ test(`appends custom value to "${option}"`, () => {
66
+ expect(subject()).toEqual(
67
+ expect.objectContaining({
68
+ [option]: [...defaultConfig[option], ...customValue],
69
+ })
70
+ );
71
+ });
72
+ }
73
+ );
74
+
75
+ describe.each(['globals'])(
76
+ 'with custom "%s"',
77
+ (option: keyof Pick<typeof defaultConfig, 'globals'>) => {
78
+ const customValue = { foo: 'bar' };
79
+
80
+ beforeEach(() => {
81
+ jest.mocked(getJestConfiguration).mockReturnValue({ [option]: customValue });
82
+ });
83
+
84
+ test(`merges custom value with "${option}"`, () => {
85
+ expect(subject()).toEqual(
86
+ expect.objectContaining({
87
+ [option]: { ...defaultConfig[option], ...customValue },
88
+ })
89
+ );
90
+ });
91
+ }
92
+ );
93
+
94
+ describe('with other custom options', () => {
95
+ const customOptions = { resetMocks: true, testEnvironment: 'node' };
96
+
97
+ beforeEach(() => jest.mocked(getJestConfiguration).mockReturnValue(customOptions));
98
+
99
+ test('merges custom options with default config', () => {
100
+ expect(subject()).toEqual({ ...defaultConfig, ...customOptions });
101
+ });
102
+ });
103
+ });
104
+
105
+ describe(`${getJestConfigCLI.name}`, () => {
106
+ let args: Config.Argv;
107
+
108
+ const subject = () => getJestConfigCLI(args);
109
+
110
+ beforeEach(() => {
111
+ const commandLineOptions: Omit<Config.Argv, '_' | '$0'> = { runInBand: true };
112
+ // eslint-disable-next-line @typescript-eslint/naming-convention
113
+ args = { _: [], $0: '', ...commandLineOptions };
114
+ });
115
+
116
+ const stringified: (keyof typeof defaultConfig)[] = [
117
+ 'globals',
118
+ 'moduleNameMapper',
119
+ 'transform',
120
+ ];
121
+
122
+ test(`merges command line args with default config and stringifies "${stringified.join(
123
+ '", "'
124
+ )}"`, () => {
125
+ expect(subject()).toEqual({
126
+ ...defaultConfig,
127
+ ...args,
128
+ ...Object.fromEntries(
129
+ stringified.map(option => [option, JSON.stringify(defaultConfig[option])])
130
+ ),
131
+ });
132
+ });
133
+ });
134
+ });
@@ -0,0 +1,90 @@
1
+ import { readJson } from '../read-json';
2
+
3
+ import { getPackageData, getPackageDependencyVersion } from '../get-package-data';
4
+
5
+ jest.mock('../read-json', () => ({ readJson: jest.fn() }));
6
+
7
+ describe(`[startup] Utils`, () => {
8
+ describe(`${getPackageData.name}`, () => {
9
+ const packageJson = './package.json';
10
+ const ancestorPackageJson = '../../package.json';
11
+ let packages: Record<string, Record<string, any>>;
12
+
13
+ beforeEach(() => {
14
+ packages = {
15
+ [ancestorPackageJson]: { dependencies: { foo: '1.0.0', bar: '2.0.0' } },
16
+ [packageJson]: { dependencies: { foo: '1.1.0', baz: '3.0.0' } },
17
+ };
18
+ jest.mocked(readJson).mockImplementation(path => packages[path] ?? {});
19
+ });
20
+
21
+ const subject = () => getPackageData();
22
+
23
+ test(`returns merged dependencies from ${packageJson} and ${ancestorPackageJson}`, () => {
24
+ expect(subject()).toEqual({
25
+ dependencies: {
26
+ ...packages[ancestorPackageJson].dependencies,
27
+ ...packages[packageJson].dependencies,
28
+ },
29
+ });
30
+ });
31
+
32
+ describe(`when ${packageJson} contains sharedDependencies`, () => {
33
+ const sharedDependencies = { react: 'SharedDependencies.React' };
34
+
35
+ beforeEach(() => {
36
+ Object.assign(packages[packageJson], {
37
+ cli: { webpack: { 'shared-dependencies': sharedDependencies } },
38
+ });
39
+ });
40
+
41
+ test('returns sharedDependencies', () => {
42
+ expect(subject()).toEqual(expect.objectContaining({ sharedDependencies }));
43
+ });
44
+ });
45
+ });
46
+
47
+ describe(`${getPackageDependencyVersion.name}`, () => {
48
+ const dependency = 'foo';
49
+ let defaultVersion: string | undefined;
50
+
51
+ beforeEach(() => (defaultVersion = undefined));
52
+
53
+ const subject = () => getPackageDependencyVersion(dependency, defaultVersion);
54
+
55
+ function itReturnsUndefinedOrDefaultVersion() {
56
+ test('returns undefined', () => {
57
+ expect(subject()).toBe(undefined);
58
+ });
59
+
60
+ describe('with a default version', () => {
61
+ beforeEach(() => (defaultVersion = '1.2.3'));
62
+
63
+ test('returns default version', () => {
64
+ expect(subject()).toBe(defaultVersion);
65
+ });
66
+ });
67
+ }
68
+
69
+ itReturnsUndefinedOrDefaultVersion();
70
+
71
+ describe('when dependency exists', () => {
72
+ const module: Record<string, any> = {};
73
+
74
+ beforeEach(() => {
75
+ module.version = '2.3.4';
76
+ jest.doMock(`${dependency}/package.json`, () => module, { virtual: true });
77
+ });
78
+
79
+ test('returns dependency version', () => {
80
+ expect(subject()).toBe(module.version);
81
+ });
82
+
83
+ describe('when dependency has no version', () => {
84
+ beforeEach(() => delete module.version);
85
+
86
+ itReturnsUndefinedOrDefaultVersion();
87
+ });
88
+ });
89
+ });
90
+ });