@servicetitan/startup 31.3.2 → 31.5.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 (234) hide show
  1. package/dist/cli/commands/build.d.ts +0 -7
  2. package/dist/cli/commands/build.d.ts.map +1 -1
  3. package/dist/cli/commands/build.js +28 -17
  4. package/dist/cli/commands/build.js.map +1 -1
  5. package/dist/cli/commands/bundle-package.d.ts +1 -1
  6. package/dist/cli/commands/bundle-package.d.ts.map +1 -1
  7. package/dist/cli/commands/bundle-package.js +13 -21
  8. package/dist/cli/commands/bundle-package.js.map +1 -1
  9. package/dist/cli/commands/clean.js +1 -1
  10. package/dist/cli/commands/clean.js.map +1 -1
  11. package/dist/cli/commands/eslint.d.ts +0 -1
  12. package/dist/cli/commands/eslint.d.ts.map +1 -1
  13. package/dist/cli/commands/eslint.js +0 -3
  14. package/dist/cli/commands/eslint.js.map +1 -1
  15. package/dist/cli/commands/get-command.d.ts.map +1 -1
  16. package/dist/cli/commands/get-command.js +3 -1
  17. package/dist/cli/commands/get-command.js.map +1 -1
  18. package/dist/cli/commands/get-user-commands.js +3 -2
  19. package/dist/cli/commands/get-user-commands.js.map +1 -1
  20. package/dist/cli/commands/init.js.map +1 -1
  21. package/dist/cli/commands/install.js.map +1 -1
  22. package/dist/cli/commands/lint.js.map +1 -1
  23. package/dist/cli/commands/mfe-package-clean.d.ts +3 -4
  24. package/dist/cli/commands/mfe-package-clean.d.ts.map +1 -1
  25. package/dist/cli/commands/mfe-package-clean.js +0 -3
  26. package/dist/cli/commands/mfe-package-clean.js.map +1 -1
  27. package/dist/cli/commands/mfe-package-publish.d.ts +9 -4
  28. package/dist/cli/commands/mfe-package-publish.d.ts.map +1 -1
  29. package/dist/cli/commands/mfe-package-publish.js +70 -47
  30. package/dist/cli/commands/mfe-package-publish.js.map +1 -1
  31. package/dist/cli/commands/mfe-publish.d.ts +3 -3
  32. package/dist/cli/commands/mfe-publish.d.ts.map +1 -1
  33. package/dist/cli/commands/mfe-publish.js +7 -1
  34. package/dist/cli/commands/mfe-publish.js.map +1 -1
  35. package/dist/cli/commands/prepare-package.d.ts +0 -1
  36. package/dist/cli/commands/prepare-package.d.ts.map +1 -1
  37. package/dist/cli/commands/prepare-package.js +0 -3
  38. package/dist/cli/commands/prepare-package.js.map +1 -1
  39. package/dist/cli/commands/review/review.js.map +1 -1
  40. package/dist/cli/commands/review/rules/require-one-anvil-uikit-contrib-version.js.map +1 -1
  41. package/dist/cli/commands/review/rules/require-one-collection-version.js.map +1 -1
  42. package/dist/cli/commands/review/rules/require-one-uikit-version.js.map +1 -1
  43. package/dist/cli/commands/run-task.d.ts +0 -1
  44. package/dist/cli/commands/run-task.d.ts.map +1 -1
  45. package/dist/cli/commands/run-task.js +0 -3
  46. package/dist/cli/commands/run-task.js.map +1 -1
  47. package/dist/cli/commands/start.d.ts +0 -8
  48. package/dist/cli/commands/start.d.ts.map +1 -1
  49. package/dist/cli/commands/start.js +28 -16
  50. package/dist/cli/commands/start.js.map +1 -1
  51. package/dist/cli/commands/styles-check.d.ts +0 -1
  52. package/dist/cli/commands/styles-check.d.ts.map +1 -1
  53. package/dist/cli/commands/styles-check.js +40 -99
  54. package/dist/cli/commands/styles-check.js.map +1 -1
  55. package/dist/cli/commands/tests.js.map +1 -1
  56. package/dist/cli/commands/types.d.ts +1 -1
  57. package/dist/cli/commands/types.d.ts.map +1 -1
  58. package/dist/cli/commands/upload-sourcemaps.d.ts +22 -0
  59. package/dist/cli/commands/upload-sourcemaps.d.ts.map +1 -0
  60. package/dist/cli/commands/upload-sourcemaps.js +179 -0
  61. package/dist/cli/commands/upload-sourcemaps.js.map +1 -0
  62. package/dist/cli/tasks/cli-task.js.map +1 -1
  63. package/dist/cli/tasks/swc-compile-package.js.map +1 -1
  64. package/dist/cli/tasks/task.js.map +1 -1
  65. package/dist/cli/tasks/tsc-compile-package.js.map +1 -1
  66. package/dist/cli/tasks/tsc-compile.js.map +1 -1
  67. package/dist/cli/utils/bundle.d.ts +4 -1
  68. package/dist/cli/utils/bundle.d.ts.map +1 -1
  69. package/dist/cli/utils/bundle.js +67 -74
  70. package/dist/cli/utils/bundle.js.map +1 -1
  71. package/dist/cli/utils/cli-os.js +2 -2
  72. package/dist/cli/utils/cli-os.js.map +1 -1
  73. package/dist/cli/utils/ts-config.js.map +1 -1
  74. package/dist/utils/find-packages.d.ts.map +1 -1
  75. package/dist/utils/find-packages.js +3 -4
  76. package/dist/utils/find-packages.js.map +1 -1
  77. package/dist/utils/find-up.d.ts +2 -0
  78. package/dist/utils/find-up.d.ts.map +1 -0
  79. package/dist/utils/find-up.js +28 -0
  80. package/dist/utils/find-up.js.map +1 -0
  81. package/dist/utils/get-configuration.d.ts +3 -1
  82. package/dist/utils/get-configuration.d.ts.map +1 -1
  83. package/dist/utils/get-configuration.js +1 -0
  84. package/dist/utils/get-configuration.js.map +1 -1
  85. package/dist/utils/index.d.ts +1 -0
  86. package/dist/utils/index.d.ts.map +1 -1
  87. package/dist/utils/index.js +1 -0
  88. package/dist/utils/index.js.map +1 -1
  89. package/dist/utils/log.js.map +1 -1
  90. package/dist/webpack/configs/cache-config.d.ts +6 -0
  91. package/dist/webpack/configs/cache-config.d.ts.map +1 -0
  92. package/dist/webpack/configs/cache-config.js +52 -0
  93. package/dist/webpack/configs/cache-config.js.map +1 -0
  94. package/dist/webpack/configs/dev-server-config.js +1 -1
  95. package/dist/webpack/configs/dev-server-config.js.map +1 -1
  96. package/dist/webpack/configs/entry.config.d.ts.map +1 -1
  97. package/dist/webpack/configs/entry.config.js +15 -6
  98. package/dist/webpack/configs/entry.config.js.map +1 -1
  99. package/dist/webpack/configs/externals-config.d.ts.map +1 -1
  100. package/dist/webpack/configs/externals-config.js +6 -2
  101. package/dist/webpack/configs/externals-config.js.map +1 -1
  102. package/dist/webpack/configs/index.d.ts +1 -0
  103. package/dist/webpack/configs/index.d.ts.map +1 -1
  104. package/dist/webpack/configs/index.js +1 -0
  105. package/dist/webpack/configs/index.js.map +1 -1
  106. package/dist/webpack/configs/optimization-config.d.ts.map +1 -1
  107. package/dist/webpack/configs/optimization-config.js +7 -11
  108. package/dist/webpack/configs/optimization-config.js.map +1 -1
  109. package/dist/webpack/configs/output-config.d.ts.map +1 -1
  110. package/dist/webpack/configs/output-config.js +25 -4
  111. package/dist/webpack/configs/output-config.js.map +1 -1
  112. package/dist/webpack/configs/plugins/assets-manifest-plugin.d.ts +6 -0
  113. package/dist/webpack/configs/plugins/assets-manifest-plugin.d.ts.map +1 -1
  114. package/dist/webpack/configs/plugins/assets-manifest-plugin.js +50 -8
  115. package/dist/webpack/configs/plugins/assets-manifest-plugin.js.map +1 -1
  116. package/dist/webpack/configs/plugins/bundle-analyser-plugin.d.ts.map +1 -1
  117. package/dist/webpack/configs/plugins/bundle-analyser-plugin.js +3 -7
  118. package/dist/webpack/configs/plugins/bundle-analyser-plugin.js.map +1 -1
  119. package/dist/webpack/configs/plugins/define-exposed-dependencies-plugin.d.ts.map +1 -1
  120. package/dist/webpack/configs/plugins/define-exposed-dependencies-plugin.js +3 -2
  121. package/dist/webpack/configs/plugins/define-exposed-dependencies-plugin.js.map +1 -1
  122. package/dist/webpack/configs/plugins/define-exposed-instance-dependencies-plugin.js +2 -2
  123. package/dist/webpack/configs/plugins/define-exposed-instance-dependencies-plugin.js.map +1 -1
  124. package/dist/webpack/configs/plugins/html-plugin.d.ts +1 -1
  125. package/dist/webpack/configs/plugins/html-plugin.d.ts.map +1 -1
  126. package/dist/webpack/configs/plugins/html-plugin.js +2 -3
  127. package/dist/webpack/configs/plugins/html-plugin.js.map +1 -1
  128. package/dist/webpack/configs/plugins/html-tags-plugin.d.ts +4 -0
  129. package/dist/webpack/configs/plugins/html-tags-plugin.d.ts.map +1 -0
  130. package/dist/webpack/configs/plugins/html-tags-plugin.js +49 -0
  131. package/dist/webpack/configs/plugins/html-tags-plugin.js.map +1 -0
  132. package/dist/webpack/configs/plugins/index.d.ts +2 -0
  133. package/dist/webpack/configs/plugins/index.d.ts.map +1 -1
  134. package/dist/webpack/configs/plugins/index.js +2 -0
  135. package/dist/webpack/configs/plugins/index.js.map +1 -1
  136. package/dist/webpack/configs/plugins/remove-empty-scripts-plugin.d.ts +4 -0
  137. package/dist/webpack/configs/plugins/remove-empty-scripts-plugin.d.ts.map +1 -0
  138. package/dist/webpack/configs/plugins/remove-empty-scripts-plugin.js +25 -0
  139. package/dist/webpack/configs/plugins/remove-empty-scripts-plugin.js.map +1 -0
  140. package/dist/webpack/configs/plugins/virtual-modules-plugin.d.ts +1 -0
  141. package/dist/webpack/configs/plugins/virtual-modules-plugin.d.ts.map +1 -1
  142. package/dist/webpack/configs/plugins/virtual-modules-plugin.js +23 -14
  143. package/dist/webpack/configs/plugins/virtual-modules-plugin.js.map +1 -1
  144. package/dist/webpack/configs/plugins-config.d.ts.map +1 -1
  145. package/dist/webpack/configs/plugins-config.js +2 -0
  146. package/dist/webpack/configs/plugins-config.js.map +1 -1
  147. package/dist/webpack/configs/rules/css-rules.d.ts.map +1 -1
  148. package/dist/webpack/configs/rules/css-rules.js +13 -18
  149. package/dist/webpack/configs/rules/css-rules.js.map +1 -1
  150. package/dist/webpack/configs/utils/get-bundle-type.d.ts +3 -0
  151. package/dist/webpack/configs/utils/get-bundle-type.d.ts.map +1 -0
  152. package/dist/webpack/configs/utils/get-bundle-type.js +24 -0
  153. package/dist/webpack/configs/utils/get-bundle-type.js.map +1 -0
  154. package/dist/webpack/configs/utils/index.d.ts +1 -0
  155. package/dist/webpack/configs/utils/index.d.ts.map +1 -1
  156. package/dist/webpack/configs/utils/index.js +1 -0
  157. package/dist/webpack/configs/utils/index.js.map +1 -1
  158. package/dist/webpack/create-webpack-config.d.ts.map +1 -1
  159. package/dist/webpack/create-webpack-config.js +37 -48
  160. package/dist/webpack/create-webpack-config.js.map +1 -1
  161. package/dist/webpack/types.d.ts +4 -0
  162. package/dist/webpack/types.d.ts.map +1 -1
  163. package/dist/webpack/utils/index.d.ts +1 -0
  164. package/dist/webpack/utils/index.d.ts.map +1 -1
  165. package/dist/webpack/utils/index.js +1 -0
  166. package/dist/webpack/utils/index.js.map +1 -1
  167. package/dist/webpack/utils/stringify-config.d.ts +2 -0
  168. package/dist/webpack/utils/stringify-config.d.ts.map +1 -0
  169. package/dist/webpack/utils/stringify-config.js +35 -0
  170. package/dist/webpack/utils/stringify-config.js.map +1 -0
  171. package/package.json +17 -15
  172. package/src/cli/commands/__tests__/build.test.ts +19 -2
  173. package/src/cli/commands/__tests__/bundle-package.test.ts +29 -8
  174. package/src/cli/commands/__tests__/clean.test.ts +2 -0
  175. package/src/cli/commands/__tests__/get-user-commands.test.ts +1 -1
  176. package/src/cli/commands/__tests__/mfe-package-publish.test.ts +91 -15
  177. package/src/cli/commands/__tests__/mfe-publish.test.ts +2 -0
  178. package/src/cli/commands/__tests__/start.test.ts +15 -1
  179. package/src/cli/commands/__tests__/styles-check.test.ts +27 -80
  180. package/src/cli/commands/__tests__/upload-sourcemaps.test.ts +127 -0
  181. package/src/cli/commands/build.ts +33 -17
  182. package/src/cli/commands/bundle-package.ts +10 -19
  183. package/src/cli/commands/clean.ts +1 -1
  184. package/src/cli/commands/eslint.ts +0 -4
  185. package/src/cli/commands/get-command.ts +2 -0
  186. package/src/cli/commands/get-user-commands.ts +1 -1
  187. package/src/cli/commands/mfe-package-clean.ts +2 -6
  188. package/src/cli/commands/mfe-package-publish.ts +104 -70
  189. package/src/cli/commands/mfe-publish.ts +8 -5
  190. package/src/cli/commands/prepare-package.ts +0 -4
  191. package/src/cli/commands/run-task.ts +0 -4
  192. package/src/cli/commands/start.ts +22 -5
  193. package/src/cli/commands/styles-check.ts +28 -131
  194. package/src/cli/commands/types.ts +1 -1
  195. package/src/cli/commands/upload-sourcemaps.ts +108 -0
  196. package/src/cli/utils/__tests__/bundle.test.ts +119 -9
  197. package/src/cli/utils/__tests__/cli-os.test.ts +2 -2
  198. package/src/cli/utils/__tests__/compile.test.ts +2 -0
  199. package/src/cli/utils/__tests__/type-check.test.ts +2 -0
  200. package/src/cli/utils/bundle.ts +76 -54
  201. package/src/cli/utils/cli-os.ts +2 -2
  202. package/src/utils/__tests__/get-configuration.test.ts +1 -1
  203. package/src/utils/find-packages.ts +3 -5
  204. package/src/utils/find-up.ts +12 -0
  205. package/src/utils/get-configuration.ts +2 -0
  206. package/src/utils/index.ts +1 -0
  207. package/src/webpack/__mocks__/style-rules.ts +1 -1
  208. package/src/webpack/__tests__/create-webpack-config-shared-dependencies.test.ts +274 -45
  209. package/src/webpack/__tests__/create-webpack-config-web-component.test.ts +25 -1
  210. package/src/webpack/__tests__/create-webpack-config.test.ts +9 -57
  211. package/src/webpack/configs/cache-config.ts +37 -0
  212. package/src/webpack/configs/dev-server-config.ts +1 -1
  213. package/src/webpack/configs/entry.config.ts +18 -8
  214. package/src/webpack/configs/externals-config.ts +7 -2
  215. package/src/webpack/configs/index.ts +1 -0
  216. package/src/webpack/configs/optimization-config.ts +7 -11
  217. package/src/webpack/configs/output-config.ts +23 -7
  218. package/src/webpack/configs/plugins/assets-manifest-plugin.ts +46 -10
  219. package/src/webpack/configs/plugins/bundle-analyser-plugin.ts +1 -6
  220. package/src/webpack/configs/plugins/define-exposed-dependencies-plugin.ts +3 -2
  221. package/src/webpack/configs/plugins/define-exposed-instance-dependencies-plugin.ts +2 -2
  222. package/src/webpack/configs/plugins/html-plugin.ts +2 -3
  223. package/src/webpack/configs/plugins/html-tags-plugin.ts +28 -0
  224. package/src/webpack/configs/plugins/index.ts +2 -0
  225. package/src/webpack/configs/plugins/remove-empty-scripts-plugin.ts +11 -0
  226. package/src/webpack/configs/plugins/virtual-modules-plugin.ts +27 -16
  227. package/src/webpack/configs/plugins-config.ts +4 -0
  228. package/src/webpack/configs/rules/css-rules.ts +19 -20
  229. package/src/webpack/configs/utils/get-bundle-type.ts +22 -0
  230. package/src/webpack/configs/utils/index.ts +1 -0
  231. package/src/webpack/create-webpack-config.ts +46 -52
  232. package/src/webpack/types.ts +4 -0
  233. package/src/webpack/utils/index.ts +1 -0
  234. package/src/webpack/utils/stringify-config.ts +19 -0
@@ -1,6 +1,6 @@
1
1
  import { fs, vol } from 'memfs';
2
2
  import { log } from '../../../utils';
3
- import { bundle, bundleWatch } from '../../utils';
3
+ import { bundle } from '../../utils';
4
4
 
5
5
  import { BundlePackage } from '../bundle-package';
6
6
 
@@ -13,7 +13,6 @@ jest.mock('../../../utils', () => ({
13
13
  jest.mock('../../utils', () => ({
14
14
  ...jest.requireActual('../../utils'),
15
15
  bundle: jest.fn().mockResolvedValue(undefined),
16
- bundleWatch: jest.fn().mockResolvedValue(undefined),
17
16
  }));
18
17
 
19
18
  describe(`[startup] ${BundlePackage.name}`, () => {
@@ -55,6 +54,30 @@ describe(`[startup] ${BundlePackage.name}`, () => {
55
54
 
56
55
  expect(bundle).toHaveBeenCalledWith(expect.objectContaining({ config: args.config }));
57
56
  });
57
+
58
+ describe('with "exposed-dependencies"', () => {
59
+ beforeEach(() => (args['exposed-dependencies'] = true));
60
+
61
+ test('ignores config file', async () => {
62
+ await subject();
63
+
64
+ expect(bundle).not.toHaveBeenCalledWith(
65
+ expect.objectContaining({ config: args.config })
66
+ );
67
+ });
68
+ });
69
+ });
70
+
71
+ describe('with "exposed-dependencies"', () => {
72
+ beforeEach(() => (args['exposed-dependencies'] = true));
73
+
74
+ test('bundles exposed dependencies', async () => {
75
+ await subject();
76
+
77
+ expect(bundle).toHaveBeenCalledWith(
78
+ expect.objectContaining({ emitExposedDependencies: true })
79
+ );
80
+ });
58
81
  });
59
82
 
60
83
  describe('with "watch"', () => {
@@ -63,7 +86,7 @@ describe(`[startup] ${BundlePackage.name}`, () => {
63
86
  test('bundles package in watch mode', async () => {
64
87
  await subject();
65
88
 
66
- expect(bundleWatch).toHaveBeenCalledWith({ config: undefined });
89
+ expect(bundle).toHaveBeenCalledWith(expect.objectContaining({ watch: true }));
67
90
  });
68
91
 
69
92
  describe('with "config"', () => {
@@ -72,8 +95,8 @@ describe(`[startup] ${BundlePackage.name}`, () => {
72
95
  test('uses specified config file', async () => {
73
96
  await subject();
74
97
 
75
- expect(bundleWatch).toHaveBeenCalledWith(
76
- expect.objectContaining({ config: args.config })
98
+ expect(bundle).toHaveBeenCalledWith(
99
+ expect.objectContaining({ config: args.config, watch: true })
77
100
  );
78
101
  });
79
102
  });
@@ -90,9 +113,7 @@ describe(`[startup] ${BundlePackage.name}`, () => {
90
113
  await subject();
91
114
 
92
115
  expect(log.warning).toHaveBeenCalledWith(
93
- expect.anything(),
94
- expect.stringMatching(/use the "esnext" option/),
95
- expect.anything()
116
+ expect.stringMatching(/should set compilerOptions.module to "esnext"/)
96
117
  );
97
118
  });
98
119
  });
@@ -1,4 +1,5 @@
1
1
  import { exec, execSync } from 'child_process';
2
+ import { log } from '../../../utils';
2
3
  import { Clean } from '../clean';
3
4
 
4
5
  jest.mock('child_process', () => ({
@@ -9,6 +10,7 @@ jest.mock('child_process', () => ({
9
10
  describe(`[startup] ${Clean.name}`, () => {
10
11
  beforeEach(() => {
11
12
  jest.clearAllMocks();
13
+ jest.spyOn(log, 'info').mockImplementation(jest.fn()); // suppress output
12
14
  });
13
15
 
14
16
  const subject = async () => new Clean().execute();
@@ -13,7 +13,7 @@ describe(`${getUserCommands.name}`, () => {
13
13
  .map(name => {
14
14
  const Command = getCommand(name)!;
15
15
  // eslint-disable-next-line @typescript-eslint/naming-convention
16
- return new Command({ _: [] }).description();
16
+ return new Command({ _: [] }).description?.();
17
17
  })
18
18
  .filter(description => !!description);
19
19
 
@@ -1,6 +1,6 @@
1
1
  import { fs, vol } from 'memfs';
2
2
  import path from 'path';
3
- import { isWebComponent, log, readJson } from '../../../utils';
3
+ import { isWebComponent, log, readJson, WebComponentBranchConfigs } from '../../../utils';
4
4
  import { gitGetBranch, gitGetCommitHash } from '../../utils/cli-git';
5
5
  import {
6
6
  npmGetPackageVersions,
@@ -8,13 +8,14 @@ import {
8
8
  npmPublish,
9
9
  npmTagVersion,
10
10
  } from '../../utils/cli-npm';
11
+ import { runCommand } from '../../utils/cli-os';
11
12
  import { MFEPackagePublish } from '../mfe-package-publish';
12
13
 
13
14
  jest.mock('fs', () => fs);
14
15
  jest.mock('../../../utils', () => ({
15
16
  ...jest.requireActual('../../../utils'),
16
17
  isWebComponent: jest.fn(),
17
- log: { info: jest.fn() },
18
+ log: { info: jest.fn(), warning: jest.fn() },
18
19
  }));
19
20
  jest.mock('../../utils/cli-git', () => ({
20
21
  gitGetBranch: jest.fn(),
@@ -26,6 +27,9 @@ jest.mock('../../utils/cli-npm', () => ({
26
27
  npmPublish: jest.fn(),
27
28
  npmTagVersion: jest.fn(),
28
29
  }));
30
+ jest.mock('../../utils/cli-os', () => ({
31
+ runCommand: jest.fn(),
32
+ }));
29
33
 
30
34
  describe(`[startup] ${MFEPackagePublish.name}`, () => {
31
35
  const defaultRegistry = 'https://verdaccio.servicetitan.com';
@@ -112,6 +116,45 @@ describe(`[startup] ${MFEPackagePublish.name}`, () => {
112
116
  );
113
117
  });
114
118
 
119
+ test('uploads sourcemaps', async () => {
120
+ await subject();
121
+
122
+ expect(runCommand).toHaveBeenCalledWith(
123
+ `npx startup upload-sourcemaps --releaseVersion=${defaultPackageVersion()}`
124
+ );
125
+ });
126
+
127
+ function itDoesNotUploadSourcemaps() {
128
+ test('does not upload sourcemaps', async () => {
129
+ await subject();
130
+
131
+ expect(runCommand).not.toHaveBeenCalledWith(
132
+ expect.stringContaining('upload-sourcemaps')
133
+ );
134
+ });
135
+ }
136
+
137
+ describe('with "uploadSourcemaps: false"', () => {
138
+ beforeEach(() => (args.uploadSourcemaps = false));
139
+
140
+ itDoesNotUploadSourcemaps();
141
+ });
142
+
143
+ describe('when branch configuration includes "uploadSourcemaps: false"', () => {
144
+ beforeEach(() =>
145
+ vol.fromJSON({
146
+ 'package.json': JSON.stringify({
147
+ name: packageName,
148
+ cli: {
149
+ 'web-component': { branches: { [branch]: { uploadSourcemaps: false } } },
150
+ },
151
+ }),
152
+ })
153
+ );
154
+
155
+ itDoesNotUploadSourcemaps();
156
+ });
157
+
115
158
  Object.entries({ dev: ['dev', 'develop'], next: ['next'], prod: ['master'] }).forEach(
116
159
  ([tag, branches]) => {
117
160
  describe.each(branches)('when branch is %s', branch => {
@@ -120,17 +163,7 @@ describe(`[startup] ${MFEPackagePublish.name}`, () => {
120
163
  test(`uses tag "${tag}"`, async () => {
121
164
  await subject();
122
165
 
123
- expect(npmPublish).toHaveBeenCalledWith({ dry: false, tag });
124
- });
125
-
126
- describe('with "dry" argument', () => {
127
- beforeEach(() => (args.dry = true));
128
-
129
- test(`does dry run with tag "${tag}"`, async () => {
130
- await subject();
131
-
132
- expect(npmPublish).toHaveBeenCalledWith({ dry: true, tag });
133
- });
166
+ expect(npmPublish).toHaveBeenCalledWith(expect.objectContaining({ tag }));
134
167
  });
135
168
  });
136
169
  }
@@ -142,7 +175,28 @@ describe(`[startup] ${MFEPackagePublish.name}`, () => {
142
175
  test('uses specified tag', async () => {
143
176
  await subject();
144
177
 
145
- expect(npmPublish).toHaveBeenCalledWith({ dry: false, tag: args.tag });
178
+ expect(npmPublish).toHaveBeenCalledWith(expect.objectContaining({ tag: args.tag }));
179
+ });
180
+ });
181
+
182
+ describe('when branch configuration includes "publishTag"', () => {
183
+ const branchConfig: WebComponentBranchConfigs = { publishTag: 'foo' };
184
+
185
+ beforeEach(() =>
186
+ vol.fromJSON({
187
+ 'package.json': JSON.stringify({
188
+ name: packageName,
189
+ cli: { 'web-component': { branches: { [branch]: branchConfig } } },
190
+ }),
191
+ })
192
+ );
193
+
194
+ test('uses configured "publishTag"', async () => {
195
+ await subject();
196
+
197
+ expect(npmPublish).toHaveBeenCalledWith(
198
+ expect.objectContaining({ tag: branchConfig.publishTag })
199
+ );
146
200
  });
147
201
  });
148
202
 
@@ -159,6 +213,20 @@ describe(`[startup] ${MFEPackagePublish.name}`, () => {
159
213
  describe('with "dry" argument', () => {
160
214
  beforeEach(() => (args.dry = true));
161
215
 
216
+ test('publishes in "dry run" mode', async () => {
217
+ await subject();
218
+
219
+ expect(npmPublish).toHaveBeenCalledWith(expect.objectContaining({ dry: true }));
220
+ });
221
+
222
+ test('logs warning', async () => {
223
+ await subject();
224
+
225
+ expect(log.warning).toHaveBeenCalledWith(
226
+ 'DRY-RUN MODE ENABLED, WILL NOT PUBLISH PACKAGES'
227
+ );
228
+ });
229
+
162
230
  test('logs message', async () => {
163
231
  await subject();
164
232
 
@@ -168,6 +236,14 @@ describe(`[startup] ${MFEPackagePublish.name}`, () => {
168
236
  )
169
237
  );
170
238
  });
239
+
240
+ test('uploads sourcemaps with "--dry" option', async () => {
241
+ await subject();
242
+
243
+ expect(runCommand).toHaveBeenCalledWith(
244
+ `npx startup upload-sourcemaps --dry --releaseVersion=${defaultPackageVersion()}`
245
+ );
246
+ });
171
247
  });
172
248
 
173
249
  describe('when package has no files', () => {
@@ -204,7 +280,7 @@ describe(`[startup] ${MFEPackagePublish.name}`, () => {
204
280
  test('logs message and skips publishing', async () => {
205
281
  await subject();
206
282
 
207
- expect(log.info).toHaveBeenCalledWith(expect.stringMatching(message));
283
+ expect(log.warning).toHaveBeenCalledWith(expect.stringMatching(message));
208
284
  expect(npmPublish).not.toHaveBeenCalled();
209
285
  });
210
286
  }
@@ -141,6 +141,8 @@ describe(`[startup] ${MFEPublish.name}`, () => {
141
141
  { name: 'dry', value: true, expected: '--dry' },
142
142
  { name: 'force', value: true, expected: '--force' },
143
143
  { name: 'registry', value: 'https://foo' },
144
+ { name: 'uploadSourcemaps', value: true, expected: '--upload-sourcemaps' },
145
+ { name: 'uploadSourcemaps', value: false, expected: '--no-upload-sourcemaps' },
144
146
  ];
145
147
 
146
148
  describe.each(testArgs)('with "{$name: $value}"', ({ name, value, expected }) => {
@@ -106,6 +106,18 @@ describe(`[startup] ${Start.name}`, () => {
106
106
  itPreparesThePackages();
107
107
  itRunsCompileAndTypeCheck();
108
108
 
109
+ test('bundles exposed dependencies', async () => {
110
+ await subject();
111
+
112
+ expect(lernaExec).toHaveBeenCalledWith({
113
+ 'cmd': 'startup bundle-package',
114
+ 'scope': packages.map(({ name }) => name),
115
+ 'parallel': true,
116
+ 'stream': true,
117
+ '--': ['--exposed-dependencies', '--use-watch-config'],
118
+ });
119
+ });
120
+
109
121
  test('bundles the package in watch mode', async () => {
110
122
  await subject();
111
123
 
@@ -126,6 +138,7 @@ describe(`[startup] ${Start.name}`, () => {
126
138
 
127
139
  expect(lernaExec).toHaveBeenCalledWith(
128
140
  expect.objectContaining({
141
+ 'cmd': 'startup bundle-package',
129
142
  '--': ['--watch', '--code-coverage'],
130
143
  })
131
144
  );
@@ -140,6 +153,7 @@ describe(`[startup] ${Start.name}`, () => {
140
153
 
141
154
  expect(lernaExec).toHaveBeenCalledWith(
142
155
  expect.objectContaining({
156
+ 'cmd': 'startup bundle-package',
143
157
  '--': ['--watch', `--config "${args.config}"`],
144
158
  })
145
159
  );
@@ -175,7 +189,7 @@ describe(`[startup] ${Start.name}`, () => {
175
189
  beforeEach(() => ((args as Record<string, any>)[arg] = true));
176
190
 
177
191
  test('logs warning', async () => {
178
- const logSpy = jest.spyOn(log, 'warning');
192
+ const logSpy = jest.spyOn(log, 'warning').mockImplementation(jest.fn());
179
193
 
180
194
  await subject();
181
195
 
@@ -1,15 +1,6 @@
1
1
  import { fs, vol } from 'memfs';
2
2
  import path from 'path';
3
- import {
4
- getFolders,
5
- getPackageData,
6
- isBundle,
7
- isLegacy,
8
- isStyleCheckDisabled,
9
- isWebComponent,
10
- loadSharedDependencies,
11
- log,
12
- } from '../../../utils';
3
+ import { getFolders, isBundle, isLegacy, isStyleCheckDisabled, log } from '../../../utils';
13
4
 
14
5
  import { StylesCheck } from '../styles-check';
15
6
 
@@ -17,59 +8,44 @@ jest.mock('fs', () => fs);
17
8
  jest.mock('../../../utils', () => ({
18
9
  ...jest.requireActual('../../../utils'),
19
10
  getFolders: jest.fn(),
20
- getPackageData: jest.fn(),
21
11
  isBundle: jest.fn(),
22
12
  isLegacy: jest.fn(),
23
13
  isStyleCheckDisabled: jest.fn(),
24
- isWebComponent: jest.fn(),
25
- loadSharedDependencies: jest.fn(),
26
- log: { error: jest.fn(), info: jest.fn(), warning: jest.fn() },
14
+ log: { error: jest.fn(), info: jest.fn() },
27
15
  }));
28
16
 
29
17
  describe(`[startup] ${StylesCheck.name}`, () => {
30
- const subject = async () => new StylesCheck().execute();
31
-
32
18
  beforeEach(() => {
33
- jest.resetAllMocks();
34
- jest.mocked(isBundle).mockReturnValue(true);
35
19
  jest.mocked(getFolders).mockReturnValue({ source: 'src', destination: 'dist' });
36
- jest.mocked(getPackageData).mockReturnValue({
37
- name: '',
38
- version: '',
39
- dependencies: {},
40
- sharedDependencies: {},
41
- });
42
- jest.mocked(loadSharedDependencies).mockReturnValue({});
20
+ jest.mocked(isBundle).mockReturnValue(true);
21
+ jest.mocked(isLegacy).mockReturnValue(false);
22
+ jest.mocked(isStyleCheckDisabled).mockReturnValue(false);
23
+ jest.clearAllMocks();
43
24
  });
44
25
 
45
26
  afterEach(() => vol.reset());
46
27
 
47
- describe('when application has design-system as a dependency', () => {
48
- beforeEach(() => {
49
- jest.mocked(loadSharedDependencies).mockReturnValue({
50
- '@servicetitan/design-system': '1.0.0',
51
- });
52
- });
28
+ const subject = async () => new StylesCheck().execute();
53
29
 
54
- test("warns that application doesn't have design-system.css", async () => {
30
+ function itExitsSilently() {
31
+ test('exits silently', async () => {
55
32
  await subject();
56
33
 
57
- expect(log.warning).toHaveBeenCalledWith(
58
- expect.stringContaining("application doesn't have design-system.css")
59
- );
34
+ expect(getFolders).not.toHaveBeenCalled();
35
+ expect(log.info).not.toHaveBeenCalled();
60
36
  });
61
- });
37
+ }
62
38
 
63
39
  describe('with a legacy package', () => {
64
40
  beforeEach(() => jest.mocked(isLegacy).mockReturnValue(true));
65
41
 
66
- test('exits silently', async () => {
67
- await subject();
42
+ itExitsSilently();
43
+ });
68
44
 
69
- expect(getFolders).not.toHaveBeenCalled();
70
- expect(log.info).not.toHaveBeenCalled();
71
- expect(log.warning).not.toHaveBeenCalled();
72
- });
45
+ describe('when package is a library', () => {
46
+ beforeEach(() => jest.mocked(isBundle).mockReturnValue(false));
47
+
48
+ itExitsSilently();
73
49
  });
74
50
 
75
51
  describe('when style check is disabled', () => {
@@ -78,9 +54,8 @@ describe(`[startup] ${StylesCheck.name}`, () => {
78
54
  test('logs message and does not check styles', async () => {
79
55
  await subject();
80
56
 
81
- expect(log.info).toHaveBeenCalledWith('style check is disabled');
82
57
  expect(getFolders).not.toHaveBeenCalled();
83
- expect(log.warning).not.toHaveBeenCalled();
58
+ expect(log.info).toHaveBeenCalledWith('style check is disabled');
84
59
  });
85
60
  });
86
61
 
@@ -98,43 +73,15 @@ describe(`[startup] ${StylesCheck.name}`, () => {
98
73
  });
99
74
  });
100
75
 
101
- function itReportsErrors() {
102
- test('reports errors', async () => {
103
- try {
104
- await subject();
105
- } catch (error: any) {
106
- expect(error.message).toMatch(/style check error/);
107
- }
108
-
109
- const errors = jest.mocked(log.error).mock.calls[0][0].split('\n');
110
- const expectedErrors = [
111
- expect.stringMatching(/style check error/i),
112
- expect.stringMatching(/style check failed/i),
113
- `file bar.less contains link to "${anvilFontsCss}"`,
114
- `file foo.css contains link to "${tokenCss}"`,
115
- `file ${path.join('styles', 'baz.css')} contains link to "${systemMinCss}"`,
116
- ];
117
- expect(errors).toEqual(expect.arrayContaining(expectedErrors));
118
- expect(errors.length).toEqual(expectedErrors.length);
119
- });
120
- }
76
+ test('reports errors', async () => {
77
+ jest.spyOn(process.stdout, 'write').mockImplementation(jest.fn()); // suppress error output
78
+ await expect(subject()).rejects.toThrow(/style check failed/);
121
79
 
122
- itReportsErrors();
123
-
124
- describe('when package is web component', () => {
125
- beforeEach(() => jest.mocked(isWebComponent).mockReturnValue(true));
126
-
127
- itReportsErrors();
128
- });
129
-
130
- describe('when package is a library', () => {
131
- beforeEach(() => jest.mocked(isBundle).mockReturnValue(false));
132
-
133
- test('does not report errors', async () => {
134
- await subject();
135
-
136
- expect(log.error).not.toHaveBeenCalled();
137
- });
80
+ [
81
+ `Error: file bar.less contains "${anvilFontsCss}"`,
82
+ `Error: file foo.css contains "${tokenCss}"`,
83
+ `Error: file ${path.join('styles', 'baz.css')} contains "${systemMinCss}"`,
84
+ ].forEach(message => expect(log.error).toHaveBeenCalledWith(message));
138
85
  });
139
86
  });
140
87
  });
@@ -0,0 +1,127 @@
1
+ import { execSync } from 'child_process';
2
+ import { vol, fs } from 'memfs';
3
+ import { inspect } from 'node:util';
4
+ import path from 'path';
5
+ import { log } from '../../../utils';
6
+ import { UploadSourcemaps } from '../upload-sourcemaps';
7
+
8
+ jest.mock('child_process', () => ({ execSync: jest.fn() }));
9
+ jest.mock('fs', () => fs);
10
+ jest.mock('../../../utils', () => ({
11
+ ...jest.requireActual('../../../utils'),
12
+ log: { info: jest.fn(), warning: jest.fn() },
13
+ }));
14
+
15
+ describe(`[startup] ${UploadSourcemaps.name}`, () => {
16
+ const OLD_ENV = process.env;
17
+ const packageJSON = { name: '@servicetitan/example-mfe', cli: { 'web-component': true } };
18
+ const tsconfigJSON = { compilerOptions: { outDir: 'dist' } };
19
+ const metadataJSON = { name: `${packageJSON.name}-hash` };
20
+ let args: ConstructorParameters<typeof UploadSourcemaps>[0];
21
+
22
+ function volumeFromJSON(overrides: Record<string, any> = {}) {
23
+ const { outDir } = tsconfigJSON.compilerOptions;
24
+ vol.fromJSON({
25
+ 'package.json': JSON.stringify(packageJSON),
26
+ 'tsconfig.json': JSON.stringify(tsconfigJSON),
27
+ [path.join(outDir, 'metadata.json')]: JSON.stringify(metadataJSON),
28
+ ...Object.fromEntries(
29
+ Object.entries(overrides).map(([key, value]) => [key, JSON.stringify(value)])
30
+ ),
31
+ });
32
+ }
33
+
34
+ beforeEach(() => {
35
+ jest.clearAllMocks();
36
+
37
+ // eslint-disable-next-line @typescript-eslint/naming-convention
38
+ process.env = { DATADOG_API_KEY: 'datadog-api-key' };
39
+ args = { releaseVersion: 'releaseVersion' };
40
+
41
+ volumeFromJSON();
42
+ });
43
+
44
+ afterEach(() => {
45
+ vol.reset();
46
+ process.env = OLD_ENV;
47
+ });
48
+
49
+ const subject = () => new UploadSourcemaps(args).execute();
50
+
51
+ test('runs datadog-ci sourcemaps upload', async () => {
52
+ await subject();
53
+
54
+ const outDir = tsconfigJSON.compilerOptions.outDir;
55
+ expect(execSync).toHaveBeenCalledWith(
56
+ [
57
+ 'npx --yes @datadog/datadog-ci@3 sourcemaps upload',
58
+ path.join(outDir, 'bundle'),
59
+ `--service=${packageJSON.name.replace('@servicetitan/', '')}`,
60
+ `--release-version=${args.releaseVersion}`,
61
+ `--minified-path-prefix=https://unpkg.servicetitan.com/${packageJSON.name}@${args.releaseVersion}/${outDir}/bundle`,
62
+ `--project-path=${metadataJSON.name}/`,
63
+ ].join(' '),
64
+ { stdio: 'inherit' }
65
+ );
66
+ });
67
+
68
+ describe('with "--dry"', () => {
69
+ beforeEach(() => (args.dry = true));
70
+
71
+ test('runs datadog-ci with --dry-run', async () => {
72
+ await subject();
73
+
74
+ expect(execSync).toHaveBeenCalledWith(
75
+ expect.stringMatching(' --dry-run '),
76
+ expect.anything()
77
+ );
78
+ });
79
+ });
80
+
81
+ function itThrowsError(message: string | RegExp) {
82
+ test(`throws ${inspect(message)}`, async () => {
83
+ jest.spyOn(process.stdout, 'write').mockImplementation(jest.fn());
84
+ await expect(subject()).rejects.toThrow(message);
85
+ });
86
+ }
87
+
88
+ describe('when DATADOG_API_KEY is not set', () => {
89
+ beforeEach(() => delete process.env.DATADOG_API_KEY);
90
+
91
+ itThrowsError('DATADOG_API_KEY environment variable is not set');
92
+
93
+ describe('when in CI environment', () => {
94
+ beforeEach(() => (process.env.CI = '1'));
95
+
96
+ afterEach(() => delete process.env.CI);
97
+
98
+ test('logs warning', async () => {
99
+ await subject();
100
+
101
+ expect(log.warning).toHaveBeenCalledWith(
102
+ 'DATADOG_API_KEY environment variable is not set; skipping sourcemaps'
103
+ );
104
+ });
105
+ });
106
+ });
107
+
108
+ describe('when --releaseVersion is omitted', () => {
109
+ beforeEach(() => delete (args as any).releaseVersion);
110
+
111
+ itThrowsError('--release-version is required');
112
+ });
113
+
114
+ describe('when package is not a web-component', () => {
115
+ beforeEach(() => {
116
+ volumeFromJSON({ 'package.json': { name: packageJSON.name } });
117
+ });
118
+
119
+ itThrowsError(/must be run inside .+ directory/);
120
+ });
121
+
122
+ describe('when outDir is not configured', () => {
123
+ beforeEach(() => volumeFromJSON({ 'tsconfig.json': {} }));
124
+
125
+ itThrowsError('compilerOptions.outDir is not configured');
126
+ });
127
+ });