@hubspot/ui-extensions-dev-server 0.10.2 → 1.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/README.md +23 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -45
- package/dist/lib/DevModeInterface.d.ts +2 -2
- package/dist/lib/DevModeInterface.js +12 -28
- package/dist/lib/DevModeParentInterface.d.ts +2 -2
- package/dist/lib/DevModeParentInterface.js +138 -154
- package/dist/lib/DevModeUnifiedInterface.d.ts +2 -2
- package/dist/lib/DevModeUnifiedInterface.js +28 -49
- package/dist/lib/DevServerState.d.ts +9 -5
- package/dist/lib/DevServerState.js +37 -18
- package/dist/lib/ExtensionsWebSocket.d.ts +25 -0
- package/dist/lib/ExtensionsWebSocket.js +110 -0
- package/dist/lib/__mocks__/config.d.ts +2 -0
- package/dist/lib/__mocks__/config.js +5 -0
- package/dist/lib/__mocks__/isExtensionFile.d.ts +5 -0
- package/dist/lib/__mocks__/isExtensionFile.js +11 -0
- package/dist/lib/__tests__/DevModeInterface.spec.d.ts +1 -0
- package/dist/lib/__tests__/DevModeInterface.spec.js +155 -0
- package/dist/lib/__tests__/DevModeParentInterface.spec.d.ts +1 -0
- package/dist/lib/__tests__/DevModeParentInterface.spec.js +179 -0
- package/dist/lib/__tests__/DevModeUnifiedInterface.spec.d.ts +1 -0
- package/dist/lib/__tests__/DevModeUnifiedInterface.spec.js +236 -0
- package/dist/lib/__tests__/ExtensionsWebSocket.spec.d.ts +1 -0
- package/dist/lib/__tests__/ExtensionsWebSocket.spec.js +304 -0
- package/dist/lib/__tests__/ast.spec.d.ts +1 -0
- package/dist/lib/__tests__/ast.spec.js +737 -0
- package/dist/lib/__tests__/build.spec.d.ts +1 -0
- package/dist/lib/__tests__/build.spec.js +159 -0
- package/dist/lib/__tests__/config.spec.d.ts +1 -0
- package/dist/lib/__tests__/config.spec.js +291 -0
- package/dist/lib/__tests__/dev.spec.d.ts +1 -0
- package/dist/lib/__tests__/dev.spec.js +80 -0
- package/dist/lib/__tests__/extensionsService.spec.d.ts +1 -0
- package/dist/lib/__tests__/extensionsService.spec.js +150 -0
- package/dist/lib/__tests__/factories.d.ts +48 -0
- package/dist/lib/__tests__/factories.js +32 -0
- package/dist/lib/__tests__/fixtures/extensionConfig.d.ts +182 -0
- package/dist/lib/__tests__/fixtures/extensionConfig.js +304 -0
- package/dist/lib/__tests__/fixtures/urls.d.ts +4 -0
- package/dist/lib/__tests__/fixtures/urls.js +4 -0
- package/dist/lib/__tests__/parsing-utils.spec.d.ts +1 -0
- package/dist/lib/__tests__/parsing-utils.spec.js +467 -0
- package/dist/lib/__tests__/plugins/codeBlockingPlugin.spec.d.ts +1 -0
- package/dist/lib/__tests__/plugins/codeBlockingPlugin.spec.js +112 -0
- package/dist/lib/__tests__/plugins/codeCheckingPlugin.spec.d.ts +1 -0
- package/dist/lib/__tests__/plugins/codeCheckingPlugin.spec.js +73 -0
- package/dist/lib/__tests__/plugins/devBuildPlugin.spec.d.ts +1 -0
- package/dist/lib/__tests__/plugins/devBuildPlugin.spec.js +256 -0
- package/dist/lib/__tests__/plugins/friendlyLoggingPlugin.spec.d.ts +1 -0
- package/dist/lib/__tests__/plugins/friendlyLoggingPlugin.spec.js +65 -0
- package/dist/lib/__tests__/plugins/manifestPlugin.spec.d.ts +1 -0
- package/dist/lib/__tests__/plugins/manifestPlugin.spec.js +455 -0
- package/dist/lib/__tests__/plugins/relevantModulesPlugin.spec.d.ts +1 -0
- package/dist/lib/__tests__/plugins/relevantModulesPlugin.spec.js +81 -0
- package/dist/lib/__tests__/server.spec.d.ts +1 -0
- package/dist/lib/__tests__/server.spec.js +152 -0
- package/dist/lib/__tests__/test-utils/ast.d.ts +1 -0
- package/dist/lib/__tests__/test-utils/ast.js +4 -0
- package/dist/lib/__tests__/utils.spec.d.ts +1 -0
- package/dist/lib/__tests__/utils.spec.js +176 -0
- package/dist/lib/ast.d.ts +1 -1
- package/dist/lib/ast.js +22 -29
- package/dist/lib/bin/cli.js +52 -72
- package/dist/lib/build.d.ts +1 -1
- package/dist/lib/build.js +60 -78
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/config.js +31 -34
- package/dist/lib/constants.d.ts +0 -2
- package/dist/lib/constants.js +20 -27
- package/dist/lib/dev.d.ts +1 -1
- package/dist/lib/dev.js +52 -69
- package/dist/lib/extensionsService.d.ts +1 -1
- package/dist/lib/extensionsService.js +21 -15
- package/dist/lib/parsing-utils.d.ts +1 -1
- package/dist/lib/parsing-utils.js +7 -11
- package/dist/lib/plugins/codeBlockingPlugin.d.ts +1 -1
- package/dist/lib/plugins/codeBlockingPlugin.js +5 -8
- package/dist/lib/plugins/codeCheckingPlugin.d.ts +1 -1
- package/dist/lib/plugins/codeCheckingPlugin.js +4 -9
- package/dist/lib/plugins/devBuildPlugin.d.ts +2 -2
- package/dist/lib/plugins/devBuildPlugin.js +74 -99
- package/dist/lib/plugins/friendlyLoggingPlugin.d.ts +2 -2
- package/dist/lib/plugins/friendlyLoggingPlugin.js +4 -12
- package/dist/lib/plugins/manifestPlugin.d.ts +1 -1
- package/dist/lib/plugins/manifestPlugin.js +46 -26
- package/dist/lib/plugins/relevantModulesPlugin.d.ts +2 -2
- package/dist/lib/plugins/relevantModulesPlugin.js +4 -7
- package/dist/lib/server.d.ts +7 -2
- package/dist/lib/server.js +85 -84
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/types.js +4 -7
- package/dist/lib/utils.d.ts +1 -1
- package/dist/lib/utils.js +23 -40
- package/package.json +44 -31
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { isExtensionFileMock } from "../../__mocks__/isExtensionFile.js";
|
|
3
|
+
vi.mock('../../utils', async () => {
|
|
4
|
+
const originalModule = (await vi.importActual('../../utils'));
|
|
5
|
+
return {
|
|
6
|
+
...originalModule,
|
|
7
|
+
isExtensionFile: isExtensionFileMock,
|
|
8
|
+
};
|
|
9
|
+
});
|
|
10
|
+
vi.mock('fs', () => {
|
|
11
|
+
const readFileSyncMock = vi.fn((filename) => JSON.stringify({
|
|
12
|
+
filename,
|
|
13
|
+
}));
|
|
14
|
+
return {
|
|
15
|
+
default: {
|
|
16
|
+
readFileSync: readFileSyncMock,
|
|
17
|
+
},
|
|
18
|
+
readFileSync: readFileSyncMock,
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
import manifestPlugin from "../../plugins/manifestPlugin.js";
|
|
22
|
+
import fs from 'fs';
|
|
23
|
+
import { MANIFEST_FILE } from "../../constants.js";
|
|
24
|
+
import path from 'path';
|
|
25
|
+
const bundleEntry = {
|
|
26
|
+
facadeModuleId: 'facadeModuleId',
|
|
27
|
+
moduleIds: ['foo', 'bar', 'baz', 'node_modules/lodash'],
|
|
28
|
+
modules: {
|
|
29
|
+
foo: {
|
|
30
|
+
renderedExports: ['bar'],
|
|
31
|
+
},
|
|
32
|
+
bar: {
|
|
33
|
+
renderedExports: ['baz'],
|
|
34
|
+
},
|
|
35
|
+
baz: {
|
|
36
|
+
renderedExports: [],
|
|
37
|
+
},
|
|
38
|
+
'node_modules/lodash': {
|
|
39
|
+
renderedExports: ['get'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
describe('manifestPlugin', () => {
|
|
44
|
+
let logger;
|
|
45
|
+
let options;
|
|
46
|
+
let bundle;
|
|
47
|
+
describe('metadata', () => {
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
logger = {
|
|
50
|
+
info: vi.fn(),
|
|
51
|
+
error: vi.fn(),
|
|
52
|
+
debug: vi.fn(),
|
|
53
|
+
warn: vi.fn(),
|
|
54
|
+
};
|
|
55
|
+
options = {
|
|
56
|
+
output: 'SomeFileName.js',
|
|
57
|
+
extensionPath: '/some/path/to/the/project',
|
|
58
|
+
logger,
|
|
59
|
+
};
|
|
60
|
+
bundle = {
|
|
61
|
+
[options.output]: bundleEntry,
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
afterEach(() => {
|
|
65
|
+
vi.clearAllMocks();
|
|
66
|
+
});
|
|
67
|
+
it('should return the correct metadata', () => {
|
|
68
|
+
const plugin = manifestPlugin({ output: '', logger });
|
|
69
|
+
expect(plugin).toStrictEqual(expect.objectContaining({
|
|
70
|
+
name: 'ui-extensions-manifest-generation-plugin',
|
|
71
|
+
enforce: 'post',
|
|
72
|
+
generateBundle: expect.any(Function),
|
|
73
|
+
}));
|
|
74
|
+
});
|
|
75
|
+
it('should handle extensionPath without trailing slash', () => {
|
|
76
|
+
const plugin = manifestPlugin({
|
|
77
|
+
...options,
|
|
78
|
+
extensionPath: '/mock/extension/path',
|
|
79
|
+
});
|
|
80
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
81
|
+
plugin.emitFile = vi.fn();
|
|
82
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
83
|
+
plugin.generateBundle({}, bundle);
|
|
84
|
+
expect(fs.readFileSync).toHaveBeenCalledWith('/mock/extension/path/package-lock.json');
|
|
85
|
+
});
|
|
86
|
+
it('should handle extensionPath with trailing slash', () => {
|
|
87
|
+
const plugin = manifestPlugin({
|
|
88
|
+
...options,
|
|
89
|
+
extensionPath: '/mock/extension/path/',
|
|
90
|
+
});
|
|
91
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
92
|
+
plugin.emitFile = vi.fn();
|
|
93
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
94
|
+
plugin.generateBundle({}, bundle);
|
|
95
|
+
expect(fs.readFileSync).toHaveBeenCalledWith('/mock/extension/path/package-lock.json');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe('generateBundle', () => {
|
|
99
|
+
it('should load the package-lock.json file when no extensionsPath is provided', () => {
|
|
100
|
+
const plugin = manifestPlugin({ ...options, extensionPath: undefined });
|
|
101
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
102
|
+
plugin.emitFile = vi.fn(); // Mock plugin function that gets bound
|
|
103
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
104
|
+
plugin.generateBundle({}, bundle);
|
|
105
|
+
expect(fs.readFileSync).toHaveBeenCalledWith(expect.stringMatching(/.*\/package-lock.json$/));
|
|
106
|
+
expect(fs.readFileSync).not.toHaveBeenCalledWith(expect.stringMatching(/.*\/package.json$/));
|
|
107
|
+
});
|
|
108
|
+
it('should load the package-lock.json file when extensionsPath is provided', () => {
|
|
109
|
+
const plugin = manifestPlugin(options);
|
|
110
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
111
|
+
plugin.emitFile = vi.fn(); // Mock plugin function that gets bound
|
|
112
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
113
|
+
plugin.generateBundle({}, bundle);
|
|
114
|
+
expect(fs.readFileSync).toHaveBeenCalledWith(`${options.extensionPath}/package-lock.json`);
|
|
115
|
+
expect(fs.readFileSync).not.toHaveBeenCalledWith(`${options.extensionPath}/package.json`);
|
|
116
|
+
});
|
|
117
|
+
it('should fallback to loading the package.json file if no lockfile is present', () => {
|
|
118
|
+
const plugin = manifestPlugin(options);
|
|
119
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
120
|
+
plugin.emitFile = vi.fn(); // Mock plugin function that gets bound
|
|
121
|
+
// @ts-expect-error TS thinks mockImplementationOnce doesn't exist on readFileSync
|
|
122
|
+
vi.mocked(fs.readFileSync).mockImplementationOnce((filename) => {
|
|
123
|
+
if (filename.includes('package-lock.json')) {
|
|
124
|
+
throw new Error('YOU SHALL NOT PASS!');
|
|
125
|
+
}
|
|
126
|
+
return JSON.stringify({ filename });
|
|
127
|
+
});
|
|
128
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
129
|
+
plugin.generateBundle({}, bundle);
|
|
130
|
+
expect(fs.readFileSync).toHaveBeenCalledWith(`${options.extensionPath}/package-lock.json`);
|
|
131
|
+
expect(fs.readFileSync).toHaveBeenCalledWith(`${options.extensionPath}/package.json`);
|
|
132
|
+
});
|
|
133
|
+
it('should call emitFile with the manifest contents', () => {
|
|
134
|
+
const plugin = manifestPlugin(options);
|
|
135
|
+
let actualSource = '';
|
|
136
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
137
|
+
plugin.emitFile = vi.fn(({ source }) => {
|
|
138
|
+
actualSource = source;
|
|
139
|
+
}); // Mock plugin function that gets bound
|
|
140
|
+
vi.mocked(fs.readFileSync).mockImplementationOnce((filename) => {
|
|
141
|
+
return JSON.stringify({ filename });
|
|
142
|
+
});
|
|
143
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
144
|
+
plugin.generateBundle({}, bundle);
|
|
145
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
146
|
+
expect(plugin.emitFile).toHaveBeenCalledTimes(1);
|
|
147
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
148
|
+
expect(plugin.emitFile).toHaveBeenCalledWith(expect.objectContaining({
|
|
149
|
+
type: 'asset',
|
|
150
|
+
fileName: `${path.parse(options.output).name}-${MANIFEST_FILE}`,
|
|
151
|
+
}));
|
|
152
|
+
expect(JSON.parse(actualSource)).toEqual({
|
|
153
|
+
dataDeps: [],
|
|
154
|
+
entry: bundleEntry.facadeModuleId,
|
|
155
|
+
modules: {
|
|
156
|
+
internal: [
|
|
157
|
+
{
|
|
158
|
+
module: 'foo',
|
|
159
|
+
renderedExports: bundleEntry.modules.foo.renderedExports,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
module: 'bar',
|
|
163
|
+
renderedExports: bundleEntry.modules.bar.renderedExports,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
module: 'baz',
|
|
167
|
+
renderedExports: bundleEntry.modules.baz.renderedExports,
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
external: [
|
|
171
|
+
{
|
|
172
|
+
module: 'node_modules/lodash',
|
|
173
|
+
renderedExports: bundleEntry.modules['node_modules/lodash'].renderedExports,
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
package: {
|
|
178
|
+
filename: expect.stringMatching(/.*\/package-lock.json$/),
|
|
179
|
+
},
|
|
180
|
+
variables: {},
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
it('should generate manifest for multiple bundles', () => {
|
|
184
|
+
const plugin = manifestPlugin(options);
|
|
185
|
+
let actualSource = '';
|
|
186
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
187
|
+
plugin.emitFile = vi.fn(({ source }) => {
|
|
188
|
+
actualSource = source;
|
|
189
|
+
}); // Mock plugin function that gets bound
|
|
190
|
+
const multiBundle = {
|
|
191
|
+
'bundle1.js': bundleEntry,
|
|
192
|
+
'bundle2.js': {
|
|
193
|
+
facadeModuleId: 'facadeModuleId2',
|
|
194
|
+
moduleIds: ['foo2', 'bar2'],
|
|
195
|
+
modules: {
|
|
196
|
+
foo2: {
|
|
197
|
+
renderedExports: ['bar2'],
|
|
198
|
+
},
|
|
199
|
+
bar2: {
|
|
200
|
+
renderedExports: [],
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
vi.mocked(fs.readFileSync).mockImplementationOnce((filename) => {
|
|
206
|
+
return JSON.stringify({ filename });
|
|
207
|
+
});
|
|
208
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
209
|
+
plugin.generateBundle({}, multiBundle);
|
|
210
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
211
|
+
expect(plugin.emitFile).toHaveBeenCalledTimes(1);
|
|
212
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
213
|
+
expect(plugin.emitFile).toHaveBeenCalledWith(expect.objectContaining({
|
|
214
|
+
type: 'asset',
|
|
215
|
+
fileName: `${path.parse(options.output).name}-${MANIFEST_FILE}`,
|
|
216
|
+
}));
|
|
217
|
+
const expectedManifest = {
|
|
218
|
+
'bundle1.js': {
|
|
219
|
+
entry: 'facadeModuleId',
|
|
220
|
+
modules: {
|
|
221
|
+
internal: [
|
|
222
|
+
{
|
|
223
|
+
module: 'foo',
|
|
224
|
+
renderedExports: bundleEntry.modules.foo.renderedExports,
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
module: 'bar',
|
|
228
|
+
renderedExports: bundleEntry.modules.bar.renderedExports,
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
module: 'baz',
|
|
232
|
+
renderedExports: bundleEntry.modules.baz.renderedExports,
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
external: [
|
|
236
|
+
{
|
|
237
|
+
module: 'node_modules/lodash',
|
|
238
|
+
renderedExports: bundleEntry.modules['node_modules/lodash'].renderedExports,
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
'bundle2.js': {
|
|
244
|
+
entry: 'facadeModuleId2',
|
|
245
|
+
modules: {
|
|
246
|
+
internal: [
|
|
247
|
+
{
|
|
248
|
+
module: 'foo2',
|
|
249
|
+
renderedExports: multiBundle['bundle2.js'].modules.foo2.renderedExports,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
module: 'bar2',
|
|
253
|
+
renderedExports: multiBundle['bundle2.js'].modules.bar2.renderedExports,
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
external: [],
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
dataDeps: [],
|
|
260
|
+
package: {
|
|
261
|
+
filename: expect.stringMatching(/.*\/package-lock.json$/),
|
|
262
|
+
},
|
|
263
|
+
variables: {},
|
|
264
|
+
};
|
|
265
|
+
expect(JSON.parse(actualSource)).toEqual(expectedManifest);
|
|
266
|
+
});
|
|
267
|
+
it('should include variables from manifestConfig when provided', () => {
|
|
268
|
+
const manifestConfig = {
|
|
269
|
+
variables: {
|
|
270
|
+
ENV: 'development',
|
|
271
|
+
DEBUG: true,
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
const optionsWithManifestConfig = { ...options, manifestConfig };
|
|
275
|
+
const plugin = manifestPlugin(optionsWithManifestConfig);
|
|
276
|
+
let actualSource = '';
|
|
277
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
278
|
+
plugin.emitFile = vi.fn(({ source }) => {
|
|
279
|
+
actualSource = source;
|
|
280
|
+
});
|
|
281
|
+
vi.mocked(fs.readFileSync).mockImplementationOnce((filename) => {
|
|
282
|
+
return JSON.stringify({ filename });
|
|
283
|
+
});
|
|
284
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
285
|
+
plugin.generateBundle({}, bundle);
|
|
286
|
+
expect(JSON.parse(actualSource)).toEqual({
|
|
287
|
+
dataDeps: [],
|
|
288
|
+
entry: bundleEntry.facadeModuleId,
|
|
289
|
+
modules: {
|
|
290
|
+
internal: [
|
|
291
|
+
{
|
|
292
|
+
module: 'foo',
|
|
293
|
+
renderedExports: bundleEntry.modules.foo.renderedExports,
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
module: 'bar',
|
|
297
|
+
renderedExports: bundleEntry.modules.bar.renderedExports,
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
module: 'baz',
|
|
301
|
+
renderedExports: bundleEntry.modules.baz.renderedExports,
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
external: [
|
|
305
|
+
{
|
|
306
|
+
module: 'node_modules/lodash',
|
|
307
|
+
renderedExports: bundleEntry.modules['node_modules/lodash'].renderedExports,
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
},
|
|
311
|
+
package: {
|
|
312
|
+
filename: expect.stringMatching(/.*\/package-lock.json$/),
|
|
313
|
+
},
|
|
314
|
+
variables: {
|
|
315
|
+
ENV: 'development',
|
|
316
|
+
DEBUG: true,
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
it('should handle null variables in manifestConfig', () => {
|
|
321
|
+
const manifestConfig = {
|
|
322
|
+
variables: null,
|
|
323
|
+
};
|
|
324
|
+
const optionsWithManifestConfig = { ...options, manifestConfig };
|
|
325
|
+
const plugin = manifestPlugin(optionsWithManifestConfig);
|
|
326
|
+
let actualSource = '';
|
|
327
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
328
|
+
plugin.emitFile = vi.fn(({ source }) => {
|
|
329
|
+
actualSource = source;
|
|
330
|
+
});
|
|
331
|
+
vi.mocked(fs.readFileSync).mockImplementationOnce((filename) => {
|
|
332
|
+
return JSON.stringify({ filename });
|
|
333
|
+
});
|
|
334
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
335
|
+
plugin.generateBundle({}, bundle);
|
|
336
|
+
const manifest = JSON.parse(actualSource);
|
|
337
|
+
expect(manifest.variables).toEqual({});
|
|
338
|
+
});
|
|
339
|
+
it('should handle undefined manifestConfig', () => {
|
|
340
|
+
const optionsWithoutManifestConfig = {
|
|
341
|
+
...options,
|
|
342
|
+
manifestConfig: undefined,
|
|
343
|
+
};
|
|
344
|
+
const plugin = manifestPlugin(optionsWithoutManifestConfig);
|
|
345
|
+
let actualSource = '';
|
|
346
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
347
|
+
plugin.emitFile = vi.fn(({ source }) => {
|
|
348
|
+
actualSource = source;
|
|
349
|
+
});
|
|
350
|
+
vi.mocked(fs.readFileSync).mockImplementationOnce((filename) => {
|
|
351
|
+
return JSON.stringify({ filename });
|
|
352
|
+
});
|
|
353
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
354
|
+
plugin.generateBundle({}, bundle);
|
|
355
|
+
const manifest = JSON.parse(actualSource);
|
|
356
|
+
expect(manifest.variables).toEqual({});
|
|
357
|
+
});
|
|
358
|
+
it('should handle empty variables object vs undefined variables', () => {
|
|
359
|
+
const manifestConfigWithEmptyVars = {
|
|
360
|
+
variables: {},
|
|
361
|
+
};
|
|
362
|
+
const plugin1 = manifestPlugin({
|
|
363
|
+
...options,
|
|
364
|
+
manifestConfig: manifestConfigWithEmptyVars,
|
|
365
|
+
});
|
|
366
|
+
let actualSource1 = '';
|
|
367
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
368
|
+
plugin1.emitFile = vi.fn(({ source }) => {
|
|
369
|
+
actualSource1 = source;
|
|
370
|
+
});
|
|
371
|
+
vi.mocked(fs.readFileSync).mockImplementationOnce((filename) => {
|
|
372
|
+
return JSON.stringify({ filename });
|
|
373
|
+
});
|
|
374
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
375
|
+
plugin1.generateBundle({}, bundle);
|
|
376
|
+
const manifest1 = JSON.parse(actualSource1);
|
|
377
|
+
expect(manifest1.variables).toEqual({});
|
|
378
|
+
const manifestConfigWithUndefinedVars = {
|
|
379
|
+
variables: undefined,
|
|
380
|
+
};
|
|
381
|
+
const plugin2 = manifestPlugin({
|
|
382
|
+
...options,
|
|
383
|
+
manifestConfig: manifestConfigWithUndefinedVars,
|
|
384
|
+
});
|
|
385
|
+
let actualSource2 = '';
|
|
386
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
387
|
+
plugin2.emitFile = vi.fn(({ source }) => {
|
|
388
|
+
actualSource2 = source;
|
|
389
|
+
});
|
|
390
|
+
vi.mocked(fs.readFileSync).mockImplementationOnce((filename) => {
|
|
391
|
+
return JSON.stringify({ filename });
|
|
392
|
+
});
|
|
393
|
+
// @ts-expect-error TS thinks these aren't functions
|
|
394
|
+
plugin2.generateBundle({}, bundle);
|
|
395
|
+
const manifest2 = JSON.parse(actualSource2);
|
|
396
|
+
expect(manifest2.variables).toEqual({});
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
describe('transform', () => {
|
|
400
|
+
let plugin;
|
|
401
|
+
const extensionPath = '/mock/extension/path';
|
|
402
|
+
beforeEach(() => {
|
|
403
|
+
logger = {
|
|
404
|
+
info: vi.fn(),
|
|
405
|
+
error: vi.fn(),
|
|
406
|
+
debug: vi.fn(),
|
|
407
|
+
warn: vi.fn(),
|
|
408
|
+
};
|
|
409
|
+
plugin = manifestPlugin({ output: 'output.js', extensionPath, logger });
|
|
410
|
+
});
|
|
411
|
+
afterEach(() => {
|
|
412
|
+
vi.clearAllMocks();
|
|
413
|
+
});
|
|
414
|
+
it('should parse extension files and collect data dependencies', () => {
|
|
415
|
+
const code = 'valid code';
|
|
416
|
+
const filename = `${extensionPath}/someFile.ts`;
|
|
417
|
+
// @ts-expect-error It does exist, I promise
|
|
418
|
+
plugin.parse = vi.fn(() => {
|
|
419
|
+
return {};
|
|
420
|
+
});
|
|
421
|
+
// @ts-expect-error Deep breath TS, it's ok
|
|
422
|
+
const result = plugin.transform(code, filename);
|
|
423
|
+
// @ts-expect-error It does exist, I promise
|
|
424
|
+
expect(plugin.parse).toBeCalledTimes(1);
|
|
425
|
+
// @ts-expect-error It does exist, I promise
|
|
426
|
+
expect(plugin.parse).toBeCalledWith(code);
|
|
427
|
+
expect(result.code).toBe(code);
|
|
428
|
+
});
|
|
429
|
+
it('should not parse non-extension files', () => {
|
|
430
|
+
const code = 'valid code';
|
|
431
|
+
const filename = 'node_modules/someFile.ts';
|
|
432
|
+
// @ts-expect-error It does exist, I promise
|
|
433
|
+
plugin.parse = vi.fn(() => {
|
|
434
|
+
return {};
|
|
435
|
+
});
|
|
436
|
+
// @ts-expect-error Deep breath TS, it's ok
|
|
437
|
+
const result = plugin.transform(code, filename);
|
|
438
|
+
// @ts-expect-error It does exist, I promise
|
|
439
|
+
expect(plugin.parse).not.toHaveBeenCalled();
|
|
440
|
+
expect(result.code).toBe(code);
|
|
441
|
+
});
|
|
442
|
+
it('should log an error if parsing fails', () => {
|
|
443
|
+
const code = 'invalid code';
|
|
444
|
+
const filename = `${extensionPath}/someFile.ts`;
|
|
445
|
+
// @ts-expect-error It does exist, I promise
|
|
446
|
+
plugin.parse = vi.fn(() => {
|
|
447
|
+
throw new Error('Parsing error');
|
|
448
|
+
});
|
|
449
|
+
// @ts-expect-error Deep breath TS, it's ok
|
|
450
|
+
const result = plugin.transform(code, filename);
|
|
451
|
+
expect(logger.error).toHaveBeenCalledWith(`Unable to parse source code for ${filename}, Error: Parsing error`);
|
|
452
|
+
expect(result.code).toBe(code);
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import relevantModulesPlugin, { getRelevantModules, } from "../../plugins/relevantModulesPlugin.js";
|
|
3
|
+
describe('manifestPlugin', () => {
|
|
4
|
+
let logger;
|
|
5
|
+
let options;
|
|
6
|
+
let bundle;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
logger = {
|
|
9
|
+
info: vi.fn(),
|
|
10
|
+
debug: vi.fn(),
|
|
11
|
+
warn: vi.fn(),
|
|
12
|
+
error: vi.fn(),
|
|
13
|
+
};
|
|
14
|
+
options = {
|
|
15
|
+
output: 'SomeFileName.js',
|
|
16
|
+
logger,
|
|
17
|
+
};
|
|
18
|
+
bundle = {
|
|
19
|
+
[options.output]: {
|
|
20
|
+
moduleIds: [
|
|
21
|
+
'A.js',
|
|
22
|
+
'B.js',
|
|
23
|
+
'C.js',
|
|
24
|
+
'node_modules/lodash',
|
|
25
|
+
'node_modules/react',
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
// @ts-expect-error We don't need all the other fields
|
|
29
|
+
empty: {
|
|
30
|
+
moduleIds: [],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
vi.clearAllMocks();
|
|
36
|
+
});
|
|
37
|
+
describe('metadata', () => {
|
|
38
|
+
it('should return the correct metadata', () => {
|
|
39
|
+
const plugin = relevantModulesPlugin(options);
|
|
40
|
+
expect(plugin).toStrictEqual(expect.objectContaining({
|
|
41
|
+
name: 'ui-extensions-relevant-modules-plugin',
|
|
42
|
+
generateBundle: expect.any(Function),
|
|
43
|
+
}));
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe('getRelevantModules', () => {
|
|
47
|
+
it('should return an empty array instead of undefined', () => {
|
|
48
|
+
const actual = getRelevantModules('this property does not exist');
|
|
49
|
+
expect(actual).toStrictEqual([]);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('generateBundle', () => {
|
|
53
|
+
it('should not update the relevantModules when output is not found in the bundle', () => {
|
|
54
|
+
const plugin = relevantModulesPlugin(options);
|
|
55
|
+
// @ts-expect-error TS thinks this isn't a function
|
|
56
|
+
plugin.generateBundle({}, {
|
|
57
|
+
output: 'no modules for this string',
|
|
58
|
+
});
|
|
59
|
+
const actual = getRelevantModules('something wrong');
|
|
60
|
+
expect(actual).toStrictEqual([]);
|
|
61
|
+
expect(logger.error).toBeCalledTimes(1);
|
|
62
|
+
expect(logger.error).toHaveBeenCalledWith('Invalid bundle format, please try saving the extension again. If the problem persists try restarting `hs project dev`');
|
|
63
|
+
});
|
|
64
|
+
it('should not update the relevantModules when moduleIds is not defined', () => {
|
|
65
|
+
const plugin = relevantModulesPlugin({ output: 'empty', logger });
|
|
66
|
+
// @ts-expect-error TS thinks this isn't a function
|
|
67
|
+
plugin.generateBundle({}, bundle);
|
|
68
|
+
const actual = getRelevantModules(options.output);
|
|
69
|
+
expect(actual).toStrictEqual([]);
|
|
70
|
+
expect(logger.error).toBeCalledTimes(1);
|
|
71
|
+
expect(logger.error).toHaveBeenCalledWith('Unable to determine relevant files to watch, please try saving the extension again. If the problem persists try restarting `hs project dev`');
|
|
72
|
+
});
|
|
73
|
+
it('should update the relevantModules when generateBundle is called', () => {
|
|
74
|
+
const plugin = relevantModulesPlugin(options);
|
|
75
|
+
// @ts-expect-error TS thinks this isn't a function
|
|
76
|
+
plugin.generateBundle({}, bundle);
|
|
77
|
+
const actual = getRelevantModules(options.output);
|
|
78
|
+
expect(actual).toStrictEqual(['A.js', 'B.js', 'C.js']);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|