@squiz/component-cli-lib 1.2.9 → 1.2.11
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/CHANGELOG.md +16 -0
- package/lib/component-dev-folder-structures.integration.spec.js +15 -0
- package/lib/component-dev-folder-structures.integration.spec.js.map +1 -1
- package/lib/component-dev.d.ts +1 -0
- package/lib/component-dev.integration.spec.js.map +1 -1
- package/lib/component-dev.js +4 -0
- package/lib/component-dev.js.map +1 -1
- package/lib/integration-tests/helper.d.ts +2 -2
- package/lib/integration-tests/helper.js.map +1 -1
- package/lib/integration-tests/upload-and-render-component.integration.spec.js +126 -118
- package/lib/integration-tests/upload-and-render-component.integration.spec.js.map +1 -1
- package/package.json +9 -8
- package/src/component-dev-folder-structures.integration.spec.ts +16 -0
- package/src/component-dev.integration.spec.ts +1 -0
- package/src/component-dev.ts +6 -1
- package/src/integration-tests/helper.ts +2 -2
- package/src/integration-tests/upload-and-render-component.integration.spec.ts +177 -168
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -14,7 +14,7 @@ import color from 'cli-color';
|
|
|
14
14
|
import path from 'path';
|
|
15
15
|
import supertest from 'supertest';
|
|
16
16
|
import { logger } from '../upload-component-folder';
|
|
17
|
-
import {
|
|
17
|
+
import { ComponentSetWebModelForCreate } from '@squiz/component-lib';
|
|
18
18
|
import fsp from 'fs/promises';
|
|
19
19
|
import { randomUUID } from 'crypto';
|
|
20
20
|
|
|
@@ -22,195 +22,204 @@ const mockConsoleError = jest.fn();
|
|
|
22
22
|
const mockConsoleLog = jest.fn();
|
|
23
23
|
|
|
24
24
|
const orgConsoleError = console.error;
|
|
25
|
-
const webPath = 'set';
|
|
25
|
+
const webPath = 'set-' + randomUUID();
|
|
26
26
|
const contentItemId = randomUUID();
|
|
27
27
|
const testFilesDir = path.resolve(__dirname, 'test-files');
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
afterAll(async () => {
|
|
35
|
-
// clean up the component added by the test
|
|
36
|
-
await deleteComponentSet(webPath);
|
|
37
|
-
await deleteContentItem(contentItemId);
|
|
38
|
-
|
|
39
|
-
for (const componentName of getTestComponents()) {
|
|
40
|
-
try {
|
|
41
|
-
await managementService.delete(`/component/smoke-test-components/${componentName}`);
|
|
42
|
-
} catch {
|
|
43
|
-
// no op
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// clean up the test componnet files
|
|
48
|
-
await fsp.rm(testFilesDir, { force: true, recursive: true });
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('Test isolated test cases', () => {
|
|
52
|
-
beforeEach(() => {
|
|
53
|
-
jest.spyOn(logger, 'error').mockImplementation(mockConsoleError);
|
|
54
|
-
jest.spyOn(logger, 'info').mockImplementation(mockConsoleLog);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('Should fail uploading a component without manifest.json', async () => {
|
|
58
|
-
mockConsoleError.mockClear();
|
|
59
|
-
const componentPath = path.join(__dirname, '/__components__/invalid-upload');
|
|
60
|
-
await uploadComponentFolder(
|
|
61
|
-
componentPath,
|
|
62
|
-
configObj.managementServiceUrl + '/v1',
|
|
63
|
-
configObj.renderServiceUrl,
|
|
64
|
-
testFilesDir,
|
|
65
|
-
);
|
|
66
|
-
expect(mockConsoleError.mock.calls[0][0]).toEqual(color.red('manifest could not be found'));
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('Should fail uploading a component that has invalid manifest.json', async () => {
|
|
70
|
-
mockConsoleError.mockClear();
|
|
71
|
-
const componentPath = path.join(__dirname, '/__components__/invalid-manifest');
|
|
72
|
-
await uploadComponentFolder(
|
|
73
|
-
componentPath,
|
|
74
|
-
configObj.managementServiceUrl + '/v1',
|
|
75
|
-
configObj.renderServiceUrl,
|
|
76
|
-
testFilesDir,
|
|
77
|
-
);
|
|
78
|
-
expect(mockConsoleError.mock.calls[0][0]).toEqual(
|
|
79
|
-
color.red('failed validation: /name pattern must match pattern "^[a-zA-Z0-9_\\-]+$"'),
|
|
80
|
-
);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('Should fail uploading the component that has size more than 100MB', async () => {
|
|
84
|
-
mockConsoleError.mockClear();
|
|
85
|
-
const componentPath = path.join(__dirname, '/__components__/big-package');
|
|
86
|
-
const filePath = `${componentPath}/105mb-file`;
|
|
87
|
-
await createFile(filePath, 105); // Higher limit has been used because compression reduces the size if you use closer to 100MB
|
|
88
|
-
await uploadComponentFolder(
|
|
89
|
-
componentPath,
|
|
90
|
-
configObj.managementServiceUrl + '/v1',
|
|
91
|
-
configObj.renderServiceUrl,
|
|
92
|
-
testFilesDir,
|
|
93
|
-
);
|
|
94
|
-
expect(mockConsoleError.mock.calls[0][0]).toEqual(
|
|
95
|
-
color.red(['File size exceeds the maximum limit of 100MB'].join('')),
|
|
96
|
-
);
|
|
97
|
-
removeFile(filePath);
|
|
29
|
+
describe('uploading a component', () => {
|
|
30
|
+
beforeAll(async () => {
|
|
31
|
+
await fsp.rm(testFilesDir, { force: true, recursive: true });
|
|
32
|
+
await fsp.mkdir(testFilesDir);
|
|
98
33
|
});
|
|
99
|
-
});
|
|
100
34
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const componentPath = path.join(__dirname, '/__components__/cmp-static-file-test');
|
|
104
|
-
|
|
105
|
-
beforeAll(async () => {
|
|
35
|
+
afterAll(async () => {
|
|
36
|
+
// clean up the component added by the test
|
|
106
37
|
await deleteComponentSet(webPath);
|
|
107
38
|
await deleteContentItem(contentItemId);
|
|
39
|
+
|
|
108
40
|
for (const componentName of getTestComponents()) {
|
|
109
41
|
try {
|
|
110
|
-
await managementService.delete(`/component/${componentName}`);
|
|
42
|
+
await managementService.delete(`/component/smoke-test-components/${componentName}`);
|
|
111
43
|
} catch {
|
|
112
44
|
// no op
|
|
113
45
|
}
|
|
114
46
|
}
|
|
115
|
-
});
|
|
116
47
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
console.log = mockConsoleLog;
|
|
48
|
+
// clean up the test componnet files
|
|
49
|
+
await fsp.rm(testFilesDir, { force: true, recursive: true });
|
|
120
50
|
});
|
|
121
51
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
52
|
+
describe('Test isolated test cases', () => {
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
jest.spyOn(logger, 'error').mockImplementation(mockConsoleError);
|
|
55
|
+
jest.spyOn(logger, 'info').mockImplementation(mockConsoleLog);
|
|
56
|
+
});
|
|
125
57
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
componentPath,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
expect((get as any)?.res?.text).toContain(uploadedComponent);
|
|
138
|
-
});
|
|
58
|
+
it('Should fail uploading a component without manifest.json', async () => {
|
|
59
|
+
mockConsoleError.mockClear();
|
|
60
|
+
const componentPath = path.join(__dirname, '/__components__/invalid-upload');
|
|
61
|
+
await uploadComponentFolder(
|
|
62
|
+
componentPath,
|
|
63
|
+
configObj.managementServiceUrl + '/v1',
|
|
64
|
+
configObj.renderServiceUrl,
|
|
65
|
+
testFilesDir,
|
|
66
|
+
);
|
|
67
|
+
expect(mockConsoleError.mock.calls[0][0]).toEqual(color.red('manifest could not be found'));
|
|
68
|
+
});
|
|
139
69
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
70
|
+
it('Should fail uploading a component that has invalid manifest.json', async () => {
|
|
71
|
+
mockConsoleError.mockClear();
|
|
72
|
+
const componentPath = path.join(__dirname, '/__components__/invalid-manifest');
|
|
73
|
+
await uploadComponentFolder(
|
|
74
|
+
componentPath,
|
|
75
|
+
configObj.managementServiceUrl + '/v1',
|
|
76
|
+
configObj.renderServiceUrl,
|
|
77
|
+
testFilesDir,
|
|
78
|
+
);
|
|
79
|
+
expect(mockConsoleError.mock.calls[0][0]).toEqual(
|
|
80
|
+
color.red('failed validation: /name pattern must match pattern "^[a-zA-Z0-9_\\-]+$"'),
|
|
81
|
+
);
|
|
82
|
+
});
|
|
152
83
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
'/r/set/smoke-test-components/cmp-static-file-test/1.0.0/?something=hello',
|
|
170
|
-
);
|
|
171
|
-
expect(response.status).toEqual(200);
|
|
172
|
-
expect(response.data).toEqual(
|
|
173
|
-
[
|
|
174
|
-
'<div>Input: hello</div>',
|
|
175
|
-
'<div>smoke-test-components/cmp-static-file-test 1.0.0 ',
|
|
176
|
-
`${configObj.renderServiceUrl}/s/set/smoke-test-components/cmp-static-file-test/1.0.0/birthday-cake.png</div>`,
|
|
177
|
-
].join(''),
|
|
178
|
-
);
|
|
84
|
+
it('Should fail uploading the component that has size more than 100MB', async () => {
|
|
85
|
+
mockConsoleError.mockClear();
|
|
86
|
+
const componentPath = path.join(__dirname, '/__components__/big-package');
|
|
87
|
+
const filePath = `${componentPath}/105mb-file`;
|
|
88
|
+
await createFile(filePath, 105); // Higher limit has been used because compression reduces the size if you use closer to 100MB
|
|
89
|
+
await uploadComponentFolder(
|
|
90
|
+
componentPath,
|
|
91
|
+
configObj.managementServiceUrl + '/v1',
|
|
92
|
+
configObj.renderServiceUrl,
|
|
93
|
+
testFilesDir,
|
|
94
|
+
);
|
|
95
|
+
expect(mockConsoleError.mock.calls[0][0]).toEqual(
|
|
96
|
+
color.red(['File size exceeds the maximum limit of 100MB'].join('')),
|
|
97
|
+
);
|
|
98
|
+
removeFile(filePath);
|
|
99
|
+
});
|
|
179
100
|
});
|
|
180
101
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
something: 'from-content-item-service',
|
|
201
|
-
},
|
|
102
|
+
describe('Deploy basic component having a static file', () => {
|
|
103
|
+
// component to deploy for this test
|
|
104
|
+
const componentPath = path.join(__dirname, '/__components__/cmp-static-file-test');
|
|
105
|
+
|
|
106
|
+
beforeAll(async () => {
|
|
107
|
+
await deleteComponentSet(webPath);
|
|
108
|
+
await deleteContentItem(contentItemId);
|
|
109
|
+
for (const componentName of getTestComponents()) {
|
|
110
|
+
try {
|
|
111
|
+
await managementService.delete(`/component/${componentName}`);
|
|
112
|
+
} catch {
|
|
113
|
+
// no op
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
beforeEach(() => {
|
|
119
|
+
console.error = mockConsoleError;
|
|
120
|
+
console.log = mockConsoleLog;
|
|
202
121
|
});
|
|
203
122
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
123
|
+
afterEach(() => {
|
|
124
|
+
console.error = orgConsoleError;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('Should upload the component and return a valid url to preview', async () => {
|
|
128
|
+
await uploadComponentFolder(
|
|
129
|
+
componentPath,
|
|
130
|
+
configObj.managementServiceUrl + '/v1',
|
|
131
|
+
configObj.renderServiceUrl,
|
|
132
|
+
testFilesDir,
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const uploadedComponent = '<a href="/preview/smoke-test-components/cmp-static-file-test/1.0.0">1.0.0</a>';
|
|
136
|
+
const get = await supertest(configObj.renderServiceUrl).get('/');
|
|
137
|
+
expect(get.status).toEqual(200);
|
|
138
|
+
expect((get as any)?.res?.text).toContain(uploadedComponent);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('Should fail upload the component with same version', async () => {
|
|
142
|
+
mockConsoleError.mockClear();
|
|
143
|
+
await uploadComponentFolder(
|
|
144
|
+
componentPath,
|
|
145
|
+
configObj.managementServiceUrl + '/v1',
|
|
146
|
+
configObj.renderServiceUrl,
|
|
147
|
+
testFilesDir,
|
|
148
|
+
);
|
|
149
|
+
expect(mockConsoleError.mock.calls[0][0]).toEqual(
|
|
150
|
+
color.red('Cannot upload component version, smoke-test-components/cmp-static-file-test 1.0.0 already exists'),
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('Should render component', async () => {
|
|
155
|
+
const componentSet: ComponentSetWebModelForCreate = {
|
|
156
|
+
webPath,
|
|
157
|
+
displayName: 'some-display-name',
|
|
158
|
+
description: 'Set description',
|
|
159
|
+
headers: {},
|
|
160
|
+
environmentVariables: {},
|
|
161
|
+
components: {
|
|
162
|
+
'smoke-test-components/cmp-static-file-test': [
|
|
163
|
+
{
|
|
164
|
+
environmentVariables: {},
|
|
165
|
+
version: '1.0.0',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
componentVersionRules: {},
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
await addComponentSet(componentSet);
|
|
173
|
+
|
|
174
|
+
const response = await renderService.get(
|
|
175
|
+
`/r/${webPath}/smoke-test-components/cmp-static-file-test/1.0.0/?something=hello`,
|
|
176
|
+
);
|
|
177
|
+
expect(response.status).toEqual(200);
|
|
178
|
+
expect(response.data).toEqual(
|
|
179
|
+
[
|
|
180
|
+
'<div>Input: hello</div>',
|
|
181
|
+
'<div>smoke-test-components/cmp-static-file-test 1.0.0 ',
|
|
182
|
+
`${configObj.renderServiceUrl}/s/${webPath}/smoke-test-components/cmp-static-file-test/1.0.0/birthday-cake.png</div>`,
|
|
183
|
+
].join(''),
|
|
184
|
+
);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('Should render component with content item ID input', async () => {
|
|
188
|
+
const componentSet: ComponentSetWebModelForCreate = {
|
|
189
|
+
webPath,
|
|
190
|
+
displayName: 'some-display-name',
|
|
191
|
+
description: 'Set description',
|
|
192
|
+
headers: {},
|
|
193
|
+
environmentVariables: {},
|
|
194
|
+
components: {
|
|
195
|
+
'smoke-test-components/cmp-static-file-test': [{ environmentVariables: {}, version: '1.0.0' }],
|
|
196
|
+
},
|
|
197
|
+
componentVersionRules: {},
|
|
198
|
+
};
|
|
199
|
+
await addComponentSet(componentSet);
|
|
200
|
+
|
|
201
|
+
// add a component item for the test
|
|
202
|
+
await addContentItem({
|
|
203
|
+
id: contentItemId,
|
|
204
|
+
schemaName: 'smoke-test-components/cmp-static-file-test/1.0.0/main',
|
|
205
|
+
content: {
|
|
206
|
+
something: 'from-content-item-service',
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
console.log(`/r/${webPath}/smoke-test-components/cmp-static-file-test/1.0.0/?_contentItemId=` + contentItemId);
|
|
211
|
+
|
|
212
|
+
const response = await renderService.get(
|
|
213
|
+
`/r/${webPath}/smoke-test-components/cmp-static-file-test/1.0.0/?_contentItemId=` + contentItemId,
|
|
214
|
+
);
|
|
215
|
+
expect(response.status).toEqual(200);
|
|
216
|
+
expect(response.data).toEqual(
|
|
217
|
+
[
|
|
218
|
+
'<div>Input: from-content-item-service</div>',
|
|
219
|
+
'<div>smoke-test-components/cmp-static-file-test 1.0.0 ',
|
|
220
|
+
`${configObj.renderServiceUrl}/s/${webPath}/smoke-test-components/cmp-static-file-test/1.0.0/birthday-cake.png</div>`,
|
|
221
|
+
].join(''),
|
|
222
|
+
);
|
|
223
|
+
});
|
|
215
224
|
});
|
|
216
225
|
});
|