@appsemble/cli 0.30.1 → 0.30.2
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 +3 -3
- package/lib/app.test.js +1265 -1264
- package/lib/asset.test.js +68 -67
- package/lib/block.test.js +143 -142
- package/lib/config.test.js +205 -203
- package/lib/group.test.js +543 -542
- package/lib/organization.test.js +188 -187
- package/lib/resource.test.js +321 -320
- package/package.json +8 -7
- package/templates/apps/empty/app-definition.yaml +2 -2
- package/templates/blocks/mini-jsx/package.json +1 -1
- package/templates/blocks/preact/package.json +2 -2
- package/templates/blocks/vanilla/package.json +1 -1
- package/vitest.setup.js +11 -0
package/lib/app.test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeFile } from 'node:fs/promises';
|
|
2
2
|
import { readFixture, resolveFixture } from '@appsemble/node-utils';
|
|
3
|
-
import { createServer, createTestUser, models, setArgv
|
|
3
|
+
import { createServer, createTestUser, models, setArgv } from '@appsemble/server';
|
|
4
4
|
import { PredefinedOrganizationRole } from '@appsemble/types';
|
|
5
5
|
import { ISODateTimePattern } from '@appsemble/utils';
|
|
6
6
|
import { setTestApp } from 'axios-test-instance';
|
|
@@ -14,65 +14,65 @@ const argv = { host: 'http://localhost', secret: 'test', aesSecret: 'testSecret'
|
|
|
14
14
|
let user;
|
|
15
15
|
let organization;
|
|
16
16
|
let testApp;
|
|
17
|
-
|
|
18
|
-
beforeAll(() => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
22
|
-
beforeEach(async () => {
|
|
23
|
-
vi.clearAllTimers();
|
|
24
|
-
vi.setSystemTime(0);
|
|
25
|
-
const server = await createServer();
|
|
26
|
-
testApp = await setTestApp(server);
|
|
27
|
-
initAxios({ remote: testApp.defaults.baseURL });
|
|
28
|
-
user = await createTestUser();
|
|
29
|
-
organization = await Organization.create({
|
|
30
|
-
id: 'testorganization',
|
|
31
|
-
name: 'Test Organization',
|
|
32
|
-
});
|
|
33
|
-
await OrganizationMember.create({
|
|
34
|
-
OrganizationId: organization.id,
|
|
35
|
-
UserId: user.id,
|
|
36
|
-
role: PredefinedOrganizationRole.Owner,
|
|
17
|
+
describe('app', () => {
|
|
18
|
+
beforeAll(() => {
|
|
19
|
+
vi.useFakeTimers();
|
|
20
|
+
setArgv(argv);
|
|
37
21
|
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
vi.clearAllTimers();
|
|
24
|
+
vi.setSystemTime(0);
|
|
25
|
+
const server = await createServer();
|
|
26
|
+
testApp = await setTestApp(server);
|
|
27
|
+
initAxios({ remote: testApp.defaults.baseURL });
|
|
28
|
+
user = await createTestUser();
|
|
29
|
+
organization = await Organization.create({
|
|
30
|
+
id: 'testorganization',
|
|
31
|
+
name: 'Test Organization',
|
|
32
|
+
});
|
|
33
|
+
await OrganizationMember.create({
|
|
34
|
+
OrganizationId: organization.id,
|
|
35
|
+
UserId: user.id,
|
|
36
|
+
role: PredefinedOrganizationRole.Owner,
|
|
37
|
+
});
|
|
38
|
+
await Organization.create({ id: 'appsemble', name: 'Appsemble' });
|
|
39
|
+
await BlockVersion.create({
|
|
40
|
+
name: 'test',
|
|
41
|
+
OrganizationId: 'appsemble',
|
|
42
|
+
version: '0.0.0',
|
|
43
|
+
parameters: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: {
|
|
46
|
+
foo: {
|
|
47
|
+
type: 'number',
|
|
48
|
+
},
|
|
48
49
|
},
|
|
49
50
|
},
|
|
50
|
-
}
|
|
51
|
+
});
|
|
51
52
|
});
|
|
52
|
-
|
|
53
|
-
afterAll(() => {
|
|
54
|
-
vi.useRealTimers();
|
|
55
|
-
});
|
|
56
|
-
describe('publishApp', () => {
|
|
57
|
-
it('should publish app', async () => {
|
|
53
|
+
afterAll(() => {
|
|
58
54
|
vi.useRealTimers();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
55
|
+
});
|
|
56
|
+
describe('publishApp', () => {
|
|
57
|
+
it('should publish app', async () => {
|
|
58
|
+
vi.useRealTimers();
|
|
59
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
60
|
+
await publishApp({
|
|
61
|
+
path: resolveFixture('apps/test'),
|
|
62
|
+
organization: organization.id,
|
|
63
|
+
remote: testApp.defaults.baseURL,
|
|
64
|
+
clientCredentials,
|
|
65
|
+
// Required defaults
|
|
66
|
+
visibility: 'unlisted',
|
|
67
|
+
iconBackground: '#ffffff',
|
|
68
|
+
});
|
|
69
|
+
vi.useFakeTimers();
|
|
70
|
+
const app = await App.findOne();
|
|
71
|
+
expect(app.toJSON()).toMatchInlineSnapshot({
|
|
72
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
73
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
74
|
+
iconUrl: expect.any(String),
|
|
75
|
+
}, `
|
|
76
76
|
{
|
|
77
77
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
78
78
|
"$updated": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -162,77 +162,77 @@ describe('publishApp', () => {
|
|
|
162
162
|
",
|
|
163
163
|
}
|
|
164
164
|
`);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
expect(app.icon).toStrictEqual(await readFixture('apps/test/icon.png'));
|
|
166
|
+
expect(app.maskableIcon).toStrictEqual(await readFixture('apps/test/maskable-icon.png'));
|
|
167
|
+
const appBlockStyle = await AppBlockStyle.findOne();
|
|
168
|
+
expect(appBlockStyle.style).toBe(`.tux {
|
|
169
169
|
color: rgb(0 0 0);
|
|
170
170
|
}`);
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
});
|
|
183
|
-
it('should throw an error if the user doesn’t have enough scope permissions', async () => {
|
|
184
|
-
const clientCredentials = await authorizeCLI('', testApp);
|
|
185
|
-
vi.useRealTimers();
|
|
186
|
-
await expect(() => publishApp({
|
|
187
|
-
path: resolveFixture('apps/test'),
|
|
188
|
-
organization: organization.id,
|
|
189
|
-
remote: testApp.defaults.baseURL,
|
|
190
|
-
clientCredentials,
|
|
191
|
-
// Required defaults
|
|
192
|
-
visibility: 'unlisted',
|
|
193
|
-
iconBackground: '#ffffff',
|
|
194
|
-
})).rejects.toThrow('Request failed with status code 401');
|
|
195
|
-
vi.useFakeTimers();
|
|
196
|
-
const app = await App.findOne();
|
|
197
|
-
expect(app).toBeNull();
|
|
198
|
-
});
|
|
199
|
-
it('should not publish if dryRun is specified', async () => {
|
|
200
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
201
|
-
await publishApp({
|
|
202
|
-
path: resolveFixture('apps/test'),
|
|
203
|
-
organization: organization.id,
|
|
204
|
-
remote: testApp.defaults.baseURL,
|
|
205
|
-
clientCredentials,
|
|
206
|
-
// Required defaults
|
|
207
|
-
visibility: 'unlisted',
|
|
208
|
-
iconBackground: '#ffffff',
|
|
209
|
-
dryRun: true,
|
|
171
|
+
const appScreenshot = await AppScreenshot.findOne();
|
|
172
|
+
expect(appScreenshot.screenshot).toStrictEqual(await readFixture('apps/test/screenshots/test_en-us.png'));
|
|
173
|
+
const appMessages = await AppMessages.findAll({ order: [['language', 'DESC']] });
|
|
174
|
+
expect(appMessages.map(({ language, messages }) => [language, messages])).toStrictEqual([
|
|
175
|
+
['nl', JSON.parse(String(await readFixture('apps/test/i18n/nl.json')))],
|
|
176
|
+
['en', JSON.parse(String(await readFixture('apps/test/i18n/en.json')))],
|
|
177
|
+
]);
|
|
178
|
+
const resource = await Resource.findAll();
|
|
179
|
+
expect(resource).toStrictEqual([]);
|
|
180
|
+
const asset = await Asset.findAll();
|
|
181
|
+
expect(asset).toStrictEqual([]);
|
|
210
182
|
});
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
resources: true,
|
|
227
|
-
assets: true,
|
|
183
|
+
it('should throw an error if the user doesn’t have enough scope permissions', async () => {
|
|
184
|
+
const clientCredentials = await authorizeCLI('', testApp);
|
|
185
|
+
vi.useRealTimers();
|
|
186
|
+
await expect(() => publishApp({
|
|
187
|
+
path: resolveFixture('apps/test'),
|
|
188
|
+
organization: organization.id,
|
|
189
|
+
remote: testApp.defaults.baseURL,
|
|
190
|
+
clientCredentials,
|
|
191
|
+
// Required defaults
|
|
192
|
+
visibility: 'unlisted',
|
|
193
|
+
iconBackground: '#ffffff',
|
|
194
|
+
})).rejects.toThrow('Request failed with status code 401');
|
|
195
|
+
vi.useFakeTimers();
|
|
196
|
+
const app = await App.findOne();
|
|
197
|
+
expect(app).toBeNull();
|
|
228
198
|
});
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
199
|
+
it('should not publish if dryRun is specified', async () => {
|
|
200
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
201
|
+
await publishApp({
|
|
202
|
+
path: resolveFixture('apps/test'),
|
|
203
|
+
organization: organization.id,
|
|
204
|
+
remote: testApp.defaults.baseURL,
|
|
205
|
+
clientCredentials,
|
|
206
|
+
// Required defaults
|
|
207
|
+
visibility: 'unlisted',
|
|
208
|
+
iconBackground: '#ffffff',
|
|
209
|
+
dryRun: true,
|
|
210
|
+
});
|
|
211
|
+
const apps = await App.findAll();
|
|
212
|
+
expect(apps).toStrictEqual([]);
|
|
213
|
+
});
|
|
214
|
+
it('should publish app with resources and assets', async () => {
|
|
215
|
+
vi.useRealTimers();
|
|
216
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write assets:write', testApp);
|
|
217
|
+
await publishApp({
|
|
218
|
+
path: resolveFixture('apps/test'),
|
|
219
|
+
organization: organization.id,
|
|
220
|
+
remote: testApp.defaults.baseURL,
|
|
221
|
+
clientCredentials,
|
|
222
|
+
// Required defaults
|
|
223
|
+
visibility: 'unlisted',
|
|
224
|
+
iconBackground: '#ffffff',
|
|
225
|
+
// Additional
|
|
226
|
+
resources: true,
|
|
227
|
+
assets: true,
|
|
228
|
+
});
|
|
229
|
+
vi.useFakeTimers();
|
|
230
|
+
const app = await App.findOne();
|
|
231
|
+
expect(app.toJSON()).toMatchInlineSnapshot({
|
|
232
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
233
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
234
|
+
iconUrl: expect.any(String),
|
|
235
|
+
}, `
|
|
236
236
|
{
|
|
237
237
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
238
238
|
"$updated": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -322,26 +322,26 @@ describe('publishApp', () => {
|
|
|
322
322
|
",
|
|
323
323
|
}
|
|
324
324
|
`);
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
325
|
+
expect(app.icon).toStrictEqual(await readFixture('apps/test/icon.png'));
|
|
326
|
+
expect(app.maskableIcon).toStrictEqual(await readFixture('apps/test/maskable-icon.png'));
|
|
327
|
+
const appBlockStyle = await AppBlockStyle.findOne();
|
|
328
|
+
expect(appBlockStyle.style).toBe(`.tux {
|
|
329
329
|
color: rgb(0 0 0);
|
|
330
330
|
}`);
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
331
|
+
const appScreenshot = await AppScreenshot.findOne();
|
|
332
|
+
expect(appScreenshot.screenshot).toStrictEqual(await readFixture('apps/test/screenshots/test_en-us.png'));
|
|
333
|
+
const appMessages = await AppMessages.findAll({ order: [['language', 'DESC']] });
|
|
334
|
+
expect(appMessages.map(({ language, messages }) => [language, messages])).toStrictEqual([
|
|
335
|
+
['nl', JSON.parse(String(await readFixture('apps/test/i18n/nl.json')))],
|
|
336
|
+
['en', JSON.parse(String(await readFixture('apps/test/i18n/en.json')))],
|
|
337
|
+
]);
|
|
338
|
+
const resources = await Resource.findAll();
|
|
339
|
+
expect(resources.map((r) => r.toJSON())).toMatchInlineSnapshot([
|
|
340
|
+
{
|
|
341
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
342
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
343
|
+
},
|
|
344
|
+
], `
|
|
345
345
|
[
|
|
346
346
|
{
|
|
347
347
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -351,42 +351,42 @@ describe('publishApp', () => {
|
|
|
351
351
|
},
|
|
352
352
|
]
|
|
353
353
|
`);
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
});
|
|
359
|
-
it('should publish app with runtime config', async () => {
|
|
360
|
-
await AppCollection.create({
|
|
361
|
-
name: 'test',
|
|
362
|
-
expertName: 'Expert',
|
|
363
|
-
expertProfileImage: Buffer.alloc(0),
|
|
364
|
-
expertProfileImageMimeType: 'image/png',
|
|
365
|
-
headerImage: Buffer.alloc(0),
|
|
366
|
-
headerImageMimeType: 'image/png',
|
|
367
|
-
OrganizationId: organization.id,
|
|
368
|
-
visibility: 'public',
|
|
354
|
+
const assets = await Asset.findAll();
|
|
355
|
+
expect(assets.map((a) => a.data)).toStrictEqual([
|
|
356
|
+
await readFixture('apps/test/assets/tux.png'),
|
|
357
|
+
]);
|
|
369
358
|
});
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
359
|
+
it('should publish app with runtime config', async () => {
|
|
360
|
+
await AppCollection.create({
|
|
361
|
+
name: 'test',
|
|
362
|
+
expertName: 'Expert',
|
|
363
|
+
expertProfileImage: Buffer.alloc(0),
|
|
364
|
+
expertProfileImageMimeType: 'image/png',
|
|
365
|
+
headerImage: Buffer.alloc(0),
|
|
366
|
+
headerImageMimeType: 'image/png',
|
|
367
|
+
OrganizationId: organization.id,
|
|
368
|
+
visibility: 'public',
|
|
369
|
+
});
|
|
370
|
+
vi.useRealTimers();
|
|
371
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write assets:write', testApp);
|
|
372
|
+
await publishApp({
|
|
373
|
+
path: resolveFixture('apps/test'),
|
|
374
|
+
organization: organization.id,
|
|
375
|
+
remote: testApp.defaults.baseURL,
|
|
376
|
+
clientCredentials,
|
|
377
|
+
// Required defaults
|
|
378
|
+
visibility: 'unlisted',
|
|
379
|
+
iconBackground: '#ffffff',
|
|
380
|
+
// Define context
|
|
381
|
+
context: 'test',
|
|
382
|
+
});
|
|
383
|
+
vi.useFakeTimers();
|
|
384
|
+
const app = await App.findOne();
|
|
385
|
+
expect(app.toJSON()).toMatchInlineSnapshot({
|
|
386
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
387
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
388
|
+
iconUrl: expect.any(String),
|
|
389
|
+
}, `
|
|
390
390
|
{
|
|
391
391
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
392
392
|
"$updated": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -476,30 +476,30 @@ describe('publishApp', () => {
|
|
|
476
476
|
",
|
|
477
477
|
}
|
|
478
478
|
`);
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
479
|
+
expect(app.icon).toStrictEqual(await readFixture('apps/test/icon.png'));
|
|
480
|
+
expect(app.maskableIcon).toStrictEqual(await readFixture('apps/test/maskable-icon.png'));
|
|
481
|
+
const appBlockStyle = await AppBlockStyle.findOne();
|
|
482
|
+
expect(appBlockStyle.style).toBe(`.tux {
|
|
483
483
|
color: rgb(0 0 0);
|
|
484
484
|
}`);
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
485
|
+
const appScreenshot = await AppScreenshot.findOne();
|
|
486
|
+
expect(appScreenshot.screenshot).toStrictEqual(await readFixture('apps/test/screenshots/test_en-us.png'));
|
|
487
|
+
const appMessages = await AppMessages.findAll({ order: [['language', 'DESC']] });
|
|
488
|
+
expect(appMessages.map(({ language, messages }) => [language, messages])).toStrictEqual([
|
|
489
|
+
['nl', JSON.parse(String(await readFixture('apps/test/i18n/nl.json')))],
|
|
490
|
+
['en', JSON.parse(String(await readFixture('apps/test/i18n/en.json')))],
|
|
491
|
+
]);
|
|
492
|
+
const resources = await Resource.findAll();
|
|
493
|
+
expect(resources.map((r) => r.toJSON())).toMatchInlineSnapshot([
|
|
494
|
+
{
|
|
495
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
496
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
500
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
501
|
+
},
|
|
502
|
+
], `
|
|
503
503
|
[
|
|
504
504
|
{
|
|
505
505
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -516,38 +516,38 @@ describe('publishApp', () => {
|
|
|
516
516
|
},
|
|
517
517
|
]
|
|
518
518
|
`);
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
});
|
|
528
|
-
it('should publish app with app variant patches applied', async () => {
|
|
529
|
-
vi.useRealTimers();
|
|
530
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write assets:write', testApp);
|
|
531
|
-
await publishApp({
|
|
532
|
-
path: resolveFixture('apps/test'),
|
|
533
|
-
organization: organization.id,
|
|
534
|
-
remote: testApp.defaults.baseURL,
|
|
535
|
-
clientCredentials,
|
|
536
|
-
// Required defaults
|
|
537
|
-
visibility: 'unlisted',
|
|
538
|
-
iconBackground: '#ffffff',
|
|
539
|
-
// Define app variant
|
|
540
|
-
variant: 'tux',
|
|
541
|
-
resources: true,
|
|
542
|
-
assets: true,
|
|
519
|
+
const assets = await Asset.findAll();
|
|
520
|
+
expect(assets.map((a) => a.data)).toStrictEqual([
|
|
521
|
+
await readFixture('apps/test/assets/tux.png'),
|
|
522
|
+
await readFixture('apps/test/assets/tux.png'),
|
|
523
|
+
]);
|
|
524
|
+
const appCollectionApp = await AppCollectionApp.findOne();
|
|
525
|
+
expect(appCollectionApp.AppId).toBe(1);
|
|
526
|
+
expect(appCollectionApp.AppCollectionId).toBe(1);
|
|
543
527
|
});
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
528
|
+
it('should publish app with app variant patches applied', async () => {
|
|
529
|
+
vi.useRealTimers();
|
|
530
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write assets:write', testApp);
|
|
531
|
+
await publishApp({
|
|
532
|
+
path: resolveFixture('apps/test'),
|
|
533
|
+
organization: organization.id,
|
|
534
|
+
remote: testApp.defaults.baseURL,
|
|
535
|
+
clientCredentials,
|
|
536
|
+
// Required defaults
|
|
537
|
+
visibility: 'unlisted',
|
|
538
|
+
iconBackground: '#ffffff',
|
|
539
|
+
// Define app variant
|
|
540
|
+
variant: 'tux',
|
|
541
|
+
resources: true,
|
|
542
|
+
assets: true,
|
|
543
|
+
});
|
|
544
|
+
vi.useFakeTimers();
|
|
545
|
+
const app = await App.findOne();
|
|
546
|
+
expect(app.toJSON()).toMatchInlineSnapshot({
|
|
547
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
548
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
549
|
+
iconUrl: expect.any(String),
|
|
550
|
+
}, `
|
|
551
551
|
{
|
|
552
552
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
553
553
|
"$updated": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -631,25 +631,25 @@ describe('publishApp', () => {
|
|
|
631
631
|
",
|
|
632
632
|
}
|
|
633
633
|
`);
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
634
|
+
expect(app.icon).toStrictEqual(await readFixture('apps/test/variants/tux/icon.png'));
|
|
635
|
+
expect(app.maskableIcon).toStrictEqual(await readFixture('apps/test/variants/tux/maskable-icon.png'));
|
|
636
|
+
const appBlockStyle = await AppBlockStyle.findOne();
|
|
637
|
+
expect(appBlockStyle.style).toBe('.tux{color:rgb(1 2 3)}');
|
|
638
|
+
const appScreenshot = await AppScreenshot.findOne();
|
|
639
|
+
expect(appScreenshot.screenshot).toStrictEqual(await readFixture('apps/test/variants/tux/screenshots/tux.png'));
|
|
640
|
+
const appMessages = await AppMessages.findAll({ order: [['language', 'DESC']] });
|
|
641
|
+
const messages = JSON.parse(String(await readFixture('apps/test/variants/tux/patches/messages.json')));
|
|
642
|
+
expect(appMessages.map(({ language, messages: msgs }) => [language, msgs])).toStrictEqual([
|
|
643
|
+
['nl', messages.nl],
|
|
644
|
+
['en', messages.en],
|
|
645
|
+
]);
|
|
646
|
+
const resources = await Resource.findAll();
|
|
647
|
+
expect(resources.map((r) => r.toJSON())).toMatchInlineSnapshot([
|
|
648
|
+
{
|
|
649
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
650
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
651
|
+
},
|
|
652
|
+
], `
|
|
653
653
|
[
|
|
654
654
|
{
|
|
655
655
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -659,203 +659,203 @@ describe('publishApp', () => {
|
|
|
659
659
|
},
|
|
660
660
|
]
|
|
661
661
|
`);
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
});
|
|
667
|
-
it('should publish app variables and secrets', async () => {
|
|
668
|
-
vi.useRealTimers();
|
|
669
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
670
|
-
process.env.TEST_VARIABLE_1 = 'test-variable-1';
|
|
671
|
-
process.env.TEST_VARIABLE_2 = 'test-variable-2';
|
|
672
|
-
process.env.TEST_SECRET = 'test-secret';
|
|
673
|
-
process.env.TEST_SERVICE_URL_PATTERNS = 'http://localhost:1234';
|
|
674
|
-
process.env.TEST_SERVICE_IDENTIFIER = 'Authorization';
|
|
675
|
-
process.env.TEST_SERVICE_SECRET = 'secret';
|
|
676
|
-
process.env.TEST_SAML_IDP_CERTIFICATE = 'certificate';
|
|
677
|
-
process.env.TEST_SAML_ENTITY_ID = 'http://localhost:1234';
|
|
678
|
-
process.env.TEST_SAML_SSO_URL = 'http://localhost:1234';
|
|
679
|
-
process.env.TEST_OAUTH2_AUTHORIZATION_URL = 'http://localhost:1234';
|
|
680
|
-
process.env.TEST_OAUTH2_TOKEN_URL = 'http://localhost:1234';
|
|
681
|
-
process.env.TEST_OAUTH2_USER_INFO_URL = 'http://localhost:1234';
|
|
682
|
-
process.env.TEST_OAUTH2_CLIENT_ID = 'id';
|
|
683
|
-
process.env.TEST_OAUTH2_CLIENT_SECRET = 'secret';
|
|
684
|
-
process.env.TEST_SCIM_TOKEN = 'token';
|
|
685
|
-
process.env.TEST_SSL_KEY = 'key';
|
|
686
|
-
process.env.TEST_SSL_CERTIFICATE = 'certificate';
|
|
687
|
-
await publishApp({
|
|
688
|
-
path: resolveFixture('apps/test'),
|
|
689
|
-
organization: organization.id,
|
|
690
|
-
remote: testApp.defaults.baseURL,
|
|
691
|
-
clientCredentials,
|
|
692
|
-
visibility: 'unlisted',
|
|
693
|
-
iconBackground: '#ffffff',
|
|
662
|
+
const assets = await Asset.findAll();
|
|
663
|
+
expect(assets.map((a) => a.data)).toStrictEqual([
|
|
664
|
+
await readFixture('apps/test/variants/tux/assets/small-tux.png'),
|
|
665
|
+
]);
|
|
694
666
|
});
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
667
|
+
it('should publish app variables and secrets', async () => {
|
|
668
|
+
vi.useRealTimers();
|
|
669
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
670
|
+
process.env.TEST_VARIABLE_1 = 'test-variable-1';
|
|
671
|
+
process.env.TEST_VARIABLE_2 = 'test-variable-2';
|
|
672
|
+
process.env.TEST_SECRET = 'test-secret';
|
|
673
|
+
process.env.TEST_SERVICE_URL_PATTERNS = 'http://localhost:1234';
|
|
674
|
+
process.env.TEST_SERVICE_IDENTIFIER = 'Authorization';
|
|
675
|
+
process.env.TEST_SERVICE_SECRET = 'secret';
|
|
676
|
+
process.env.TEST_SAML_IDP_CERTIFICATE = 'certificate';
|
|
677
|
+
process.env.TEST_SAML_ENTITY_ID = 'http://localhost:1234';
|
|
678
|
+
process.env.TEST_SAML_SSO_URL = 'http://localhost:1234';
|
|
679
|
+
process.env.TEST_OAUTH2_AUTHORIZATION_URL = 'http://localhost:1234';
|
|
680
|
+
process.env.TEST_OAUTH2_TOKEN_URL = 'http://localhost:1234';
|
|
681
|
+
process.env.TEST_OAUTH2_USER_INFO_URL = 'http://localhost:1234';
|
|
682
|
+
process.env.TEST_OAUTH2_CLIENT_ID = 'id';
|
|
683
|
+
process.env.TEST_OAUTH2_CLIENT_SECRET = 'secret';
|
|
684
|
+
process.env.TEST_SCIM_TOKEN = 'token';
|
|
685
|
+
process.env.TEST_SSL_KEY = 'key';
|
|
686
|
+
process.env.TEST_SSL_CERTIFICATE = 'certificate';
|
|
687
|
+
await publishApp({
|
|
688
|
+
path: resolveFixture('apps/test'),
|
|
689
|
+
organization: organization.id,
|
|
690
|
+
remote: testApp.defaults.baseURL,
|
|
691
|
+
clientCredentials,
|
|
692
|
+
visibility: 'unlisted',
|
|
693
|
+
iconBackground: '#ffffff',
|
|
694
|
+
});
|
|
695
|
+
vi.useFakeTimers();
|
|
696
|
+
const app = await App.findOne({
|
|
697
|
+
attributes: ['scimEnabled', 'scimToken', 'sslKey', 'sslCertificate'],
|
|
698
|
+
where: {
|
|
699
|
+
id: 1,
|
|
700
|
+
},
|
|
701
|
+
});
|
|
702
|
+
expect({
|
|
703
|
+
scimEnabled: app.scimEnabled,
|
|
704
|
+
scimToken: app.scimToken,
|
|
705
|
+
sslKey: app.sslKey,
|
|
706
|
+
sslCertificate: app.sslCertificate,
|
|
707
|
+
}).toStrictEqual({
|
|
708
|
+
scimEnabled: true,
|
|
709
|
+
scimToken: expect.any(Buffer),
|
|
710
|
+
sslKey: 'key',
|
|
711
|
+
sslCertificate: 'certificate',
|
|
712
|
+
});
|
|
713
|
+
const appVariables = await AppVariable.findAll({
|
|
714
|
+
attributes: ['name', 'value'],
|
|
715
|
+
where: {
|
|
716
|
+
AppId: 1,
|
|
717
|
+
},
|
|
718
|
+
});
|
|
719
|
+
expect(appVariables[0].toJSON()).toStrictEqual({
|
|
720
|
+
name: 'test-variable-inline',
|
|
721
|
+
value: 'inline',
|
|
722
|
+
});
|
|
723
|
+
expect(appVariables[1].toJSON()).toStrictEqual({
|
|
724
|
+
name: 'test-variable',
|
|
725
|
+
value: 'test-variable-1.test-variable-2',
|
|
726
|
+
});
|
|
727
|
+
const appServiceSecret = await AppServiceSecret.findOne({
|
|
728
|
+
attributes: ['name', 'authenticationMethod', 'urlPatterns', 'identifier', 'secret'],
|
|
729
|
+
where: {
|
|
730
|
+
AppId: 1,
|
|
731
|
+
},
|
|
732
|
+
});
|
|
733
|
+
expect(appServiceSecret.toJSON()).toStrictEqual({
|
|
734
|
+
name: 'test-service-secret',
|
|
735
|
+
authenticationMethod: 'custom-header',
|
|
736
|
+
urlPatterns: 'http://localhost:1234',
|
|
737
|
+
identifier: 'Authorization',
|
|
738
|
+
secret: expect.any(Buffer),
|
|
739
|
+
});
|
|
740
|
+
const appSamlSecret = await AppSamlSecret.findOne({
|
|
741
|
+
attributes: [
|
|
742
|
+
'name',
|
|
743
|
+
'icon',
|
|
744
|
+
'nameAttribute',
|
|
745
|
+
'emailAttribute',
|
|
746
|
+
'idpCertificate',
|
|
747
|
+
'entityId',
|
|
748
|
+
'ssoUrl',
|
|
749
|
+
],
|
|
750
|
+
where: {
|
|
751
|
+
AppId: 1,
|
|
752
|
+
},
|
|
753
|
+
});
|
|
754
|
+
expect(appSamlSecret.toJSON()).toStrictEqual({
|
|
755
|
+
emailAttribute: 'email',
|
|
756
|
+
emailVerifiedAttribute: null,
|
|
757
|
+
entityId: 'http://localhost:1234',
|
|
758
|
+
icon: 'redhat',
|
|
699
759
|
id: 1,
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
'icon',
|
|
744
|
-
'nameAttribute',
|
|
745
|
-
'emailAttribute',
|
|
746
|
-
'idpCertificate',
|
|
747
|
-
'entityId',
|
|
748
|
-
'ssoUrl',
|
|
749
|
-
],
|
|
750
|
-
where: {
|
|
751
|
-
AppId: 1,
|
|
752
|
-
},
|
|
753
|
-
});
|
|
754
|
-
expect(appSamlSecret.toJSON()).toStrictEqual({
|
|
755
|
-
emailAttribute: 'email',
|
|
756
|
-
emailVerifiedAttribute: null,
|
|
757
|
-
entityId: 'http://localhost:1234',
|
|
758
|
-
icon: 'redhat',
|
|
759
|
-
id: 1,
|
|
760
|
-
idpCertificate: 'certificate',
|
|
761
|
-
name: 'test-saml-secret',
|
|
762
|
-
nameAttribute: 'name',
|
|
763
|
-
ssoUrl: 'http://localhost:1234',
|
|
764
|
-
spCertificate: expect.any(String),
|
|
765
|
-
});
|
|
766
|
-
const appOauth2Secret = await AppOAuth2Secret.findOne({
|
|
767
|
-
attributes: [
|
|
768
|
-
'name',
|
|
769
|
-
'icon',
|
|
770
|
-
'scope',
|
|
771
|
-
'remapper',
|
|
772
|
-
'authorizationUrl',
|
|
773
|
-
'tokenUrl',
|
|
774
|
-
'userInfoUrl',
|
|
775
|
-
'clientId',
|
|
776
|
-
'clientSecret',
|
|
777
|
-
],
|
|
778
|
-
where: {
|
|
779
|
-
AppId: 1,
|
|
780
|
-
},
|
|
781
|
-
});
|
|
782
|
-
expect({
|
|
783
|
-
authorizationUrl: appOauth2Secret.authorizationUrl,
|
|
784
|
-
clientId: appOauth2Secret.clientId,
|
|
785
|
-
clientSecret: appOauth2Secret.clientSecret,
|
|
786
|
-
icon: appOauth2Secret.icon,
|
|
787
|
-
name: appOauth2Secret.name,
|
|
788
|
-
remapper: appOauth2Secret.remapper,
|
|
789
|
-
scope: appOauth2Secret.scope,
|
|
790
|
-
tokenUrl: appOauth2Secret.tokenUrl,
|
|
791
|
-
userInfoUrl: appOauth2Secret.userInfoUrl,
|
|
792
|
-
}).toStrictEqual({
|
|
793
|
-
authorizationUrl: 'http://localhost:1234',
|
|
794
|
-
clientId: 'id',
|
|
795
|
-
clientSecret: 'secret',
|
|
796
|
-
icon: 'redhat',
|
|
797
|
-
name: 'test-oauth2-secret',
|
|
798
|
-
remapper: [{ prop: 'email' }],
|
|
799
|
-
scope: 'email openid profile',
|
|
800
|
-
tokenUrl: 'http://localhost:1234',
|
|
801
|
-
userInfoUrl: 'http://localhost:1234',
|
|
802
|
-
});
|
|
803
|
-
});
|
|
804
|
-
it('should validate and throw if there’s an error before publishing an app', async () => {
|
|
805
|
-
await BlockVersion.destroy({
|
|
806
|
-
where: {
|
|
807
|
-
version: '0.0.0',
|
|
808
|
-
OrganizationId: 'appsemble',
|
|
809
|
-
name: 'test',
|
|
810
|
-
},
|
|
760
|
+
idpCertificate: 'certificate',
|
|
761
|
+
name: 'test-saml-secret',
|
|
762
|
+
nameAttribute: 'name',
|
|
763
|
+
ssoUrl: 'http://localhost:1234',
|
|
764
|
+
spCertificate: expect.any(String),
|
|
765
|
+
});
|
|
766
|
+
const appOauth2Secret = await AppOAuth2Secret.findOne({
|
|
767
|
+
attributes: [
|
|
768
|
+
'name',
|
|
769
|
+
'icon',
|
|
770
|
+
'scope',
|
|
771
|
+
'remapper',
|
|
772
|
+
'authorizationUrl',
|
|
773
|
+
'tokenUrl',
|
|
774
|
+
'userInfoUrl',
|
|
775
|
+
'clientId',
|
|
776
|
+
'clientSecret',
|
|
777
|
+
],
|
|
778
|
+
where: {
|
|
779
|
+
AppId: 1,
|
|
780
|
+
},
|
|
781
|
+
});
|
|
782
|
+
expect({
|
|
783
|
+
authorizationUrl: appOauth2Secret.authorizationUrl,
|
|
784
|
+
clientId: appOauth2Secret.clientId,
|
|
785
|
+
clientSecret: appOauth2Secret.clientSecret,
|
|
786
|
+
icon: appOauth2Secret.icon,
|
|
787
|
+
name: appOauth2Secret.name,
|
|
788
|
+
remapper: appOauth2Secret.remapper,
|
|
789
|
+
scope: appOauth2Secret.scope,
|
|
790
|
+
tokenUrl: appOauth2Secret.tokenUrl,
|
|
791
|
+
userInfoUrl: appOauth2Secret.userInfoUrl,
|
|
792
|
+
}).toStrictEqual({
|
|
793
|
+
authorizationUrl: 'http://localhost:1234',
|
|
794
|
+
clientId: 'id',
|
|
795
|
+
clientSecret: 'secret',
|
|
796
|
+
icon: 'redhat',
|
|
797
|
+
name: 'test-oauth2-secret',
|
|
798
|
+
remapper: [{ prop: 'email' }],
|
|
799
|
+
scope: 'email openid profile',
|
|
800
|
+
tokenUrl: 'http://localhost:1234',
|
|
801
|
+
userInfoUrl: 'http://localhost:1234',
|
|
802
|
+
});
|
|
811
803
|
});
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
vapidPublicKey: 'a',
|
|
834
|
-
vapidPrivateKey: 'b',
|
|
835
|
-
visibility: 'public',
|
|
836
|
-
OrganizationId: organization.id,
|
|
804
|
+
it('should validate and throw if there’s an error before publishing an app', async () => {
|
|
805
|
+
await BlockVersion.destroy({
|
|
806
|
+
where: {
|
|
807
|
+
version: '0.0.0',
|
|
808
|
+
OrganizationId: 'appsemble',
|
|
809
|
+
name: 'test',
|
|
810
|
+
},
|
|
811
|
+
});
|
|
812
|
+
vi.useRealTimers();
|
|
813
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
814
|
+
await expect(() => publishApp({
|
|
815
|
+
path: resolveFixture('apps/test'),
|
|
816
|
+
organization: organization.id,
|
|
817
|
+
remote: testApp.defaults.baseURL,
|
|
818
|
+
clientCredentials,
|
|
819
|
+
// Required defaults
|
|
820
|
+
visibility: 'unlisted',
|
|
821
|
+
iconBackground: '#ffffff',
|
|
822
|
+
})).rejects.toThrow('is not a known block type');
|
|
823
|
+
const app = await App.findOne();
|
|
824
|
+
expect(app).toBeNull();
|
|
837
825
|
});
|
|
838
826
|
});
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
force: false,
|
|
827
|
+
describe('updateApp', () => {
|
|
828
|
+
let app;
|
|
829
|
+
beforeEach(async () => {
|
|
830
|
+
app = await App.create({
|
|
831
|
+
path: 'test-app',
|
|
832
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
833
|
+
vapidPublicKey: 'a',
|
|
834
|
+
vapidPrivateKey: 'b',
|
|
835
|
+
visibility: 'public',
|
|
836
|
+
OrganizationId: organization.id,
|
|
837
|
+
});
|
|
851
838
|
});
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
839
|
+
it('should update app', async () => {
|
|
840
|
+
vi.useRealTimers();
|
|
841
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
842
|
+
await updateApp({
|
|
843
|
+
id: app.id,
|
|
844
|
+
path: resolveFixture('apps/test'),
|
|
845
|
+
remote: testApp.defaults.baseURL,
|
|
846
|
+
clientCredentials,
|
|
847
|
+
// Required defaults
|
|
848
|
+
visibility: 'unlisted',
|
|
849
|
+
iconBackground: '#ffffff',
|
|
850
|
+
force: false,
|
|
851
|
+
});
|
|
852
|
+
vi.useFakeTimers();
|
|
853
|
+
await app.reload();
|
|
854
|
+
expect(app.toJSON()).toMatchInlineSnapshot({
|
|
855
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
856
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
857
|
+
iconUrl: expect.any(String),
|
|
858
|
+
}, `
|
|
859
859
|
{
|
|
860
860
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
861
861
|
"$updated": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -945,71 +945,71 @@ describe('updateApp', () => {
|
|
|
945
945
|
",
|
|
946
946
|
}
|
|
947
947
|
`);
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
948
|
+
expect(app.icon).toStrictEqual(await readFixture('apps/test/icon.png'));
|
|
949
|
+
expect(app.maskableIcon).toStrictEqual(await readFixture('apps/test/maskable-icon.png'));
|
|
950
|
+
const appBlockStyle = await AppBlockStyle.findOne();
|
|
951
|
+
expect(appBlockStyle.style).toBe(`.tux {
|
|
952
952
|
color: rgb(0 0 0);
|
|
953
953
|
}`);
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
});
|
|
966
|
-
it('should throw an error if the user doesn’t have enough scope permissions', async () => {
|
|
967
|
-
const clientCredentials = await authorizeCLI('', testApp);
|
|
968
|
-
vi.useRealTimers();
|
|
969
|
-
await expect(() => updateApp({
|
|
970
|
-
id: app.id,
|
|
971
|
-
force: false,
|
|
972
|
-
path: resolveFixture('apps/test'),
|
|
973
|
-
remote: testApp.defaults.baseURL,
|
|
974
|
-
clientCredentials,
|
|
975
|
-
// Required defaults
|
|
976
|
-
visibility: 'unlisted',
|
|
977
|
-
iconBackground: '#ffffff',
|
|
978
|
-
})).rejects.toThrow('Request failed with status code 401');
|
|
979
|
-
vi.useFakeTimers();
|
|
980
|
-
await app.reload();
|
|
981
|
-
expect(app).toMatchObject({
|
|
982
|
-
path: 'test-app',
|
|
983
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
984
|
-
vapidPublicKey: 'a',
|
|
985
|
-
vapidPrivateKey: 'b',
|
|
986
|
-
visibility: 'public',
|
|
987
|
-
OrganizationId: organization.id,
|
|
954
|
+
const appScreenshot = await AppScreenshot.findOne();
|
|
955
|
+
expect(appScreenshot.screenshot).toStrictEqual(await readFixture('apps/test/screenshots/test_en-us.png'));
|
|
956
|
+
const appMessages = await AppMessages.findAll({ order: [['language', 'DESC']] });
|
|
957
|
+
expect(appMessages.map(({ language, messages }) => [language, messages])).toStrictEqual([
|
|
958
|
+
['nl', JSON.parse(String(await readFixture('apps/test/i18n/nl.json')))],
|
|
959
|
+
['en', JSON.parse(String(await readFixture('apps/test/i18n/en.json')))],
|
|
960
|
+
]);
|
|
961
|
+
const resource = await Resource.findAll();
|
|
962
|
+
expect(resource).toStrictEqual([]);
|
|
963
|
+
const asset = await Asset.findAll();
|
|
964
|
+
expect(asset).toStrictEqual([]);
|
|
988
965
|
});
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
966
|
+
it('should throw an error if the user doesn’t have enough scope permissions', async () => {
|
|
967
|
+
const clientCredentials = await authorizeCLI('', testApp);
|
|
968
|
+
vi.useRealTimers();
|
|
969
|
+
await expect(() => updateApp({
|
|
970
|
+
id: app.id,
|
|
971
|
+
force: false,
|
|
972
|
+
path: resolveFixture('apps/test'),
|
|
973
|
+
remote: testApp.defaults.baseURL,
|
|
974
|
+
clientCredentials,
|
|
975
|
+
// Required defaults
|
|
976
|
+
visibility: 'unlisted',
|
|
977
|
+
iconBackground: '#ffffff',
|
|
978
|
+
})).rejects.toThrow('Request failed with status code 401');
|
|
979
|
+
vi.useFakeTimers();
|
|
980
|
+
await app.reload();
|
|
981
|
+
expect(app).toMatchObject({
|
|
982
|
+
path: 'test-app',
|
|
983
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
984
|
+
vapidPublicKey: 'a',
|
|
985
|
+
vapidPrivateKey: 'b',
|
|
986
|
+
visibility: 'public',
|
|
987
|
+
OrganizationId: organization.id,
|
|
988
|
+
});
|
|
1005
989
|
});
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
990
|
+
it('should update app with resources and assets', async () => {
|
|
991
|
+
vi.useRealTimers();
|
|
992
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write assets:write', testApp);
|
|
993
|
+
await updateApp({
|
|
994
|
+
id: app.id,
|
|
995
|
+
path: resolveFixture('apps/test'),
|
|
996
|
+
remote: testApp.defaults.baseURL,
|
|
997
|
+
clientCredentials,
|
|
998
|
+
// Required defaults
|
|
999
|
+
visibility: 'unlisted',
|
|
1000
|
+
iconBackground: '#ffffff',
|
|
1001
|
+
force: false,
|
|
1002
|
+
// Additional
|
|
1003
|
+
resources: true,
|
|
1004
|
+
assets: true,
|
|
1005
|
+
});
|
|
1006
|
+
vi.useFakeTimers();
|
|
1007
|
+
await app.reload();
|
|
1008
|
+
expect(app.toJSON()).toMatchInlineSnapshot({
|
|
1009
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
1010
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
1011
|
+
iconUrl: expect.any(String),
|
|
1012
|
+
}, `
|
|
1013
1013
|
{
|
|
1014
1014
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
1015
1015
|
"$updated": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -1099,26 +1099,26 @@ describe('updateApp', () => {
|
|
|
1099
1099
|
",
|
|
1100
1100
|
}
|
|
1101
1101
|
`);
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1102
|
+
expect(app.icon).toStrictEqual(await readFixture('apps/test/icon.png'));
|
|
1103
|
+
expect(app.maskableIcon).toStrictEqual(await readFixture('apps/test/maskable-icon.png'));
|
|
1104
|
+
const appBlockStyle = await AppBlockStyle.findOne();
|
|
1105
|
+
expect(appBlockStyle.style).toBe(`.tux {
|
|
1106
1106
|
color: rgb(0 0 0);
|
|
1107
1107
|
}`);
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1108
|
+
const appScreenshot = await AppScreenshot.findOne();
|
|
1109
|
+
expect(appScreenshot.screenshot).toStrictEqual(await readFixture('apps/test/screenshots/test_en-us.png'));
|
|
1110
|
+
const appMessages = await AppMessages.findAll({ order: [['language', 'DESC']] });
|
|
1111
|
+
expect(appMessages.map(({ language, messages }) => [language, messages])).toStrictEqual([
|
|
1112
|
+
['nl', JSON.parse(String(await readFixture('apps/test/i18n/nl.json')))],
|
|
1113
|
+
['en', JSON.parse(String(await readFixture('apps/test/i18n/en.json')))],
|
|
1114
|
+
]);
|
|
1115
|
+
const resources = await Resource.findAll();
|
|
1116
|
+
expect(resources.map((r) => r.toJSON())).toMatchInlineSnapshot([
|
|
1117
|
+
{
|
|
1118
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
1119
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
1120
|
+
},
|
|
1121
|
+
], `
|
|
1122
1122
|
[
|
|
1123
1123
|
{
|
|
1124
1124
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -1128,43 +1128,43 @@ describe('updateApp', () => {
|
|
|
1128
1128
|
},
|
|
1129
1129
|
]
|
|
1130
1130
|
`);
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
});
|
|
1136
|
-
it('should update app with runtime config', async () => {
|
|
1137
|
-
await AppCollection.create({
|
|
1138
|
-
name: 'test',
|
|
1139
|
-
expertName: 'Expert',
|
|
1140
|
-
expertProfileImage: Buffer.alloc(0),
|
|
1141
|
-
expertProfileImageMimeType: 'image/png',
|
|
1142
|
-
headerImage: Buffer.alloc(0),
|
|
1143
|
-
headerImageMimeType: 'image/png',
|
|
1144
|
-
OrganizationId: organization.id,
|
|
1145
|
-
visibility: 'public',
|
|
1131
|
+
const assets = await Asset.findAll();
|
|
1132
|
+
expect(assets.map((a) => a.data)).toStrictEqual([
|
|
1133
|
+
await readFixture('apps/test/assets/tux.png'),
|
|
1134
|
+
]);
|
|
1146
1135
|
});
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1136
|
+
it('should update app with runtime config', async () => {
|
|
1137
|
+
await AppCollection.create({
|
|
1138
|
+
name: 'test',
|
|
1139
|
+
expertName: 'Expert',
|
|
1140
|
+
expertProfileImage: Buffer.alloc(0),
|
|
1141
|
+
expertProfileImageMimeType: 'image/png',
|
|
1142
|
+
headerImage: Buffer.alloc(0),
|
|
1143
|
+
headerImageMimeType: 'image/png',
|
|
1144
|
+
OrganizationId: organization.id,
|
|
1145
|
+
visibility: 'public',
|
|
1146
|
+
});
|
|
1147
|
+
vi.useRealTimers();
|
|
1148
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write assets:write', testApp);
|
|
1149
|
+
await updateApp({
|
|
1150
|
+
path: resolveFixture('apps/test'),
|
|
1151
|
+
id: app.id,
|
|
1152
|
+
remote: testApp.defaults.baseURL,
|
|
1153
|
+
clientCredentials,
|
|
1154
|
+
// Required defaults
|
|
1155
|
+
visibility: 'unlisted',
|
|
1156
|
+
iconBackground: '#ffffff',
|
|
1157
|
+
force: false,
|
|
1158
|
+
// Define context
|
|
1159
|
+
context: 'test',
|
|
1160
|
+
});
|
|
1161
|
+
vi.useFakeTimers();
|
|
1162
|
+
await app.reload();
|
|
1163
|
+
expect(app.toJSON()).toMatchInlineSnapshot({
|
|
1164
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
1165
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
1166
|
+
iconUrl: expect.any(String),
|
|
1167
|
+
}, `
|
|
1168
1168
|
{
|
|
1169
1169
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
1170
1170
|
"$updated": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -1254,30 +1254,30 @@ describe('updateApp', () => {
|
|
|
1254
1254
|
",
|
|
1255
1255
|
}
|
|
1256
1256
|
`);
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1257
|
+
expect(app.icon).toStrictEqual(await readFixture('apps/test/icon.png'));
|
|
1258
|
+
expect(app.maskableIcon).toStrictEqual(await readFixture('apps/test/maskable-icon.png'));
|
|
1259
|
+
const appBlockStyle = await AppBlockStyle.findOne();
|
|
1260
|
+
expect(appBlockStyle.style).toBe(`.tux {
|
|
1261
1261
|
color: rgb(0 0 0);
|
|
1262
1262
|
}`);
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1263
|
+
const appScreenshot = await AppScreenshot.findOne();
|
|
1264
|
+
expect(appScreenshot.screenshot).toStrictEqual(await readFixture('apps/test/screenshots/test_en-us.png'));
|
|
1265
|
+
const appMessages = await AppMessages.findAll({ order: [['language', 'DESC']] });
|
|
1266
|
+
expect(appMessages.map(({ language, messages }) => [language, messages])).toStrictEqual([
|
|
1267
|
+
['nl', JSON.parse(String(await readFixture('apps/test/i18n/nl.json')))],
|
|
1268
|
+
['en', JSON.parse(String(await readFixture('apps/test/i18n/en.json')))],
|
|
1269
|
+
]);
|
|
1270
|
+
const resources = await Resource.findAll();
|
|
1271
|
+
expect(resources.map((r) => r.toJSON())).toMatchInlineSnapshot([
|
|
1272
|
+
{
|
|
1273
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
1274
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
1278
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
1279
|
+
},
|
|
1280
|
+
], `
|
|
1281
1281
|
[
|
|
1282
1282
|
{
|
|
1283
1283
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -1294,40 +1294,40 @@ describe('updateApp', () => {
|
|
|
1294
1294
|
},
|
|
1295
1295
|
]
|
|
1296
1296
|
`);
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
});
|
|
1307
|
-
it('should update app with app variant patches applied', async () => {
|
|
1308
|
-
vi.useRealTimers();
|
|
1309
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write assets:write', testApp);
|
|
1310
|
-
await updateApp({
|
|
1311
|
-
path: resolveFixture('apps/test'),
|
|
1312
|
-
id: app.id,
|
|
1313
|
-
remote: testApp.defaults.baseURL,
|
|
1314
|
-
clientCredentials,
|
|
1315
|
-
// Required defaults
|
|
1316
|
-
visibility: 'unlisted',
|
|
1317
|
-
iconBackground: '#ffffff',
|
|
1318
|
-
force: false,
|
|
1319
|
-
// Define app variant
|
|
1320
|
-
variant: 'tux',
|
|
1321
|
-
resources: true,
|
|
1322
|
-
assets: true,
|
|
1297
|
+
const assets = await Asset.findAll();
|
|
1298
|
+
expect(assets.map((a) => a.data)).toStrictEqual([
|
|
1299
|
+
await readFixture('apps/test/assets/tux.png'),
|
|
1300
|
+
await readFixture('apps/test/assets/tux.png'),
|
|
1301
|
+
]);
|
|
1302
|
+
// TODO: not yet implemented
|
|
1303
|
+
// const appCollectionApp = await AppCollectionApp.findOne();
|
|
1304
|
+
// expect(appCollectionApp.AppId).toBe(1);
|
|
1305
|
+
// expect(appCollectionApp.AppCollectionId).toBe(1);
|
|
1323
1306
|
});
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1307
|
+
it('should update app with app variant patches applied', async () => {
|
|
1308
|
+
vi.useRealTimers();
|
|
1309
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write assets:write', testApp);
|
|
1310
|
+
await updateApp({
|
|
1311
|
+
path: resolveFixture('apps/test'),
|
|
1312
|
+
id: app.id,
|
|
1313
|
+
remote: testApp.defaults.baseURL,
|
|
1314
|
+
clientCredentials,
|
|
1315
|
+
// Required defaults
|
|
1316
|
+
visibility: 'unlisted',
|
|
1317
|
+
iconBackground: '#ffffff',
|
|
1318
|
+
force: false,
|
|
1319
|
+
// Define app variant
|
|
1320
|
+
variant: 'tux',
|
|
1321
|
+
resources: true,
|
|
1322
|
+
assets: true,
|
|
1323
|
+
});
|
|
1324
|
+
vi.useFakeTimers();
|
|
1325
|
+
await app.reload();
|
|
1326
|
+
expect(app.toJSON()).toMatchInlineSnapshot({
|
|
1327
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
1328
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
1329
|
+
iconUrl: expect.any(String),
|
|
1330
|
+
}, `
|
|
1331
1331
|
{
|
|
1332
1332
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
1333
1333
|
"$updated": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -1411,25 +1411,25 @@ describe('updateApp', () => {
|
|
|
1411
1411
|
",
|
|
1412
1412
|
}
|
|
1413
1413
|
`);
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1414
|
+
expect(app.icon).toStrictEqual(await readFixture('apps/test/variants/tux/icon.png'));
|
|
1415
|
+
expect(app.maskableIcon).toStrictEqual(await readFixture('apps/test/variants/tux/maskable-icon.png'));
|
|
1416
|
+
const appBlockStyle = await AppBlockStyle.findOne();
|
|
1417
|
+
expect(appBlockStyle.style).toBe('.tux{color:rgb(1 2 3)}');
|
|
1418
|
+
const appScreenshot = await AppScreenshot.findOne();
|
|
1419
|
+
expect(appScreenshot.screenshot).toStrictEqual(await readFixture('apps/test/variants/tux/screenshots/tux.png'));
|
|
1420
|
+
const appMessages = await AppMessages.findAll({ order: [['language', 'DESC']] });
|
|
1421
|
+
const messages = JSON.parse(String(await readFixture('apps/test/variants/tux/patches/messages.json')));
|
|
1422
|
+
expect(appMessages.map(({ language, messages: msgs }) => [language, msgs])).toStrictEqual([
|
|
1423
|
+
['nl', messages.nl],
|
|
1424
|
+
['en', messages.en],
|
|
1425
|
+
]);
|
|
1426
|
+
const resources = await Resource.findAll();
|
|
1427
|
+
expect(resources.map((r) => r.toJSON())).toMatchInlineSnapshot([
|
|
1428
|
+
{
|
|
1429
|
+
$created: expect.stringMatching(ISODateTimePattern),
|
|
1430
|
+
$updated: expect.stringMatching(ISODateTimePattern),
|
|
1431
|
+
},
|
|
1432
|
+
], `
|
|
1433
1433
|
[
|
|
1434
1434
|
{
|
|
1435
1435
|
"$created": StringMatching /\\\\d\\{4\\}\\(\\.\\\\d\\{2\\}\\)\\{2\\}\\(\\\\s\\|T\\)\\(\\\\d\\{2\\}\\.\\)\\{2\\}\\\\d\\{2\\}/,
|
|
@@ -1439,557 +1439,557 @@ describe('updateApp', () => {
|
|
|
1439
1439
|
},
|
|
1440
1440
|
]
|
|
1441
1441
|
`);
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
});
|
|
1447
|
-
it('should update app variables and secrets', async () => {
|
|
1448
|
-
vi.useRealTimers();
|
|
1449
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
1450
|
-
process.env.TEST_VARIABLE_1 = 'test-variable-1';
|
|
1451
|
-
process.env.TEST_VARIABLE_2 = 'test-variable-2';
|
|
1452
|
-
process.env.TEST_SECRET = 'test-secret';
|
|
1453
|
-
process.env.TEST_SERVICE_URL_PATTERNS = 'http://localhost:1234';
|
|
1454
|
-
process.env.TEST_SERVICE_IDENTIFIER = 'Authorization';
|
|
1455
|
-
process.env.TEST_SERVICE_SECRET = 'secret';
|
|
1456
|
-
process.env.TEST_SAML_IDP_CERTIFICATE = 'certificate';
|
|
1457
|
-
process.env.TEST_SAML_ENTITY_ID = 'http://localhost:1234';
|
|
1458
|
-
process.env.TEST_SAML_SSO_URL = 'http://localhost:1234';
|
|
1459
|
-
process.env.TEST_OAUTH2_AUTHORIZATION_URL = 'http://localhost:1234';
|
|
1460
|
-
process.env.TEST_OAUTH2_TOKEN_URL = 'http://localhost:1234';
|
|
1461
|
-
process.env.TEST_OAUTH2_USER_INFO_URL = 'http://localhost:1234';
|
|
1462
|
-
process.env.TEST_OAUTH2_CLIENT_ID = 'id';
|
|
1463
|
-
process.env.TEST_OAUTH2_CLIENT_SECRET = 'secret';
|
|
1464
|
-
process.env.TEST_SCIM_TOKEN = 'token';
|
|
1465
|
-
process.env.TEST_SSL_KEY = 'key';
|
|
1466
|
-
process.env.TEST_SSL_CERTIFICATE = 'certificate';
|
|
1467
|
-
await updateApp({
|
|
1468
|
-
id: 1,
|
|
1469
|
-
path: resolveFixture('apps/test'),
|
|
1470
|
-
remote: testApp.defaults.baseURL,
|
|
1471
|
-
clientCredentials,
|
|
1472
|
-
visibility: 'unlisted',
|
|
1473
|
-
iconBackground: '#ffffff',
|
|
1474
|
-
force: true,
|
|
1442
|
+
const assets = await Asset.findAll();
|
|
1443
|
+
expect(assets.map((a) => a.data)).toStrictEqual([
|
|
1444
|
+
await readFixture('apps/test/variants/tux/assets/small-tux.png'),
|
|
1445
|
+
]);
|
|
1475
1446
|
});
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1447
|
+
it('should update app variables and secrets', async () => {
|
|
1448
|
+
vi.useRealTimers();
|
|
1449
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
1450
|
+
process.env.TEST_VARIABLE_1 = 'test-variable-1';
|
|
1451
|
+
process.env.TEST_VARIABLE_2 = 'test-variable-2';
|
|
1452
|
+
process.env.TEST_SECRET = 'test-secret';
|
|
1453
|
+
process.env.TEST_SERVICE_URL_PATTERNS = 'http://localhost:1234';
|
|
1454
|
+
process.env.TEST_SERVICE_IDENTIFIER = 'Authorization';
|
|
1455
|
+
process.env.TEST_SERVICE_SECRET = 'secret';
|
|
1456
|
+
process.env.TEST_SAML_IDP_CERTIFICATE = 'certificate';
|
|
1457
|
+
process.env.TEST_SAML_ENTITY_ID = 'http://localhost:1234';
|
|
1458
|
+
process.env.TEST_SAML_SSO_URL = 'http://localhost:1234';
|
|
1459
|
+
process.env.TEST_OAUTH2_AUTHORIZATION_URL = 'http://localhost:1234';
|
|
1460
|
+
process.env.TEST_OAUTH2_TOKEN_URL = 'http://localhost:1234';
|
|
1461
|
+
process.env.TEST_OAUTH2_USER_INFO_URL = 'http://localhost:1234';
|
|
1462
|
+
process.env.TEST_OAUTH2_CLIENT_ID = 'id';
|
|
1463
|
+
process.env.TEST_OAUTH2_CLIENT_SECRET = 'secret';
|
|
1464
|
+
process.env.TEST_SCIM_TOKEN = 'token';
|
|
1465
|
+
process.env.TEST_SSL_KEY = 'key';
|
|
1466
|
+
process.env.TEST_SSL_CERTIFICATE = 'certificate';
|
|
1467
|
+
await updateApp({
|
|
1480
1468
|
id: 1,
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
'
|
|
1528
|
-
'
|
|
1529
|
-
'
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1469
|
+
path: resolveFixture('apps/test'),
|
|
1470
|
+
remote: testApp.defaults.baseURL,
|
|
1471
|
+
clientCredentials,
|
|
1472
|
+
visibility: 'unlisted',
|
|
1473
|
+
iconBackground: '#ffffff',
|
|
1474
|
+
force: true,
|
|
1475
|
+
});
|
|
1476
|
+
vi.useFakeTimers();
|
|
1477
|
+
const updatedApp = await App.findOne({
|
|
1478
|
+
attributes: ['scimEnabled', 'scimToken', 'sslKey', 'sslCertificate'],
|
|
1479
|
+
where: {
|
|
1480
|
+
id: 1,
|
|
1481
|
+
},
|
|
1482
|
+
});
|
|
1483
|
+
expect({
|
|
1484
|
+
scimEnabled: updatedApp.scimEnabled,
|
|
1485
|
+
scimToken: updatedApp.scimToken,
|
|
1486
|
+
sslKey: updatedApp.sslKey,
|
|
1487
|
+
sslCertificate: updatedApp.sslCertificate,
|
|
1488
|
+
}).toStrictEqual({
|
|
1489
|
+
scimEnabled: true,
|
|
1490
|
+
scimToken: expect.any(Buffer),
|
|
1491
|
+
sslKey: 'key',
|
|
1492
|
+
sslCertificate: 'certificate',
|
|
1493
|
+
});
|
|
1494
|
+
const appVariables = await AppVariable.findAll({
|
|
1495
|
+
attributes: ['name', 'value'],
|
|
1496
|
+
where: {
|
|
1497
|
+
AppId: 1,
|
|
1498
|
+
},
|
|
1499
|
+
});
|
|
1500
|
+
expect(appVariables[0].toJSON()).toStrictEqual({
|
|
1501
|
+
name: 'test-variable-inline',
|
|
1502
|
+
value: 'inline',
|
|
1503
|
+
});
|
|
1504
|
+
expect(appVariables[1].toJSON()).toStrictEqual({
|
|
1505
|
+
name: 'test-variable',
|
|
1506
|
+
value: 'test-variable-1.test-variable-2',
|
|
1507
|
+
});
|
|
1508
|
+
const appServiceSecret = await AppServiceSecret.findOne({
|
|
1509
|
+
attributes: ['name', 'authenticationMethod', 'urlPatterns', 'identifier', 'secret'],
|
|
1510
|
+
where: {
|
|
1511
|
+
AppId: 1,
|
|
1512
|
+
},
|
|
1513
|
+
});
|
|
1514
|
+
expect(appServiceSecret.toJSON()).toStrictEqual({
|
|
1515
|
+
name: 'test-service-secret',
|
|
1516
|
+
authenticationMethod: 'custom-header',
|
|
1517
|
+
urlPatterns: 'http://localhost:1234',
|
|
1518
|
+
identifier: 'Authorization',
|
|
1519
|
+
secret: expect.any(Buffer),
|
|
1520
|
+
});
|
|
1521
|
+
const appSamlSecret = await AppSamlSecret.findOne({
|
|
1522
|
+
attributes: [
|
|
1523
|
+
'name',
|
|
1524
|
+
'icon',
|
|
1525
|
+
'nameAttribute',
|
|
1526
|
+
'emailAttribute',
|
|
1527
|
+
'idpCertificate',
|
|
1528
|
+
'entityId',
|
|
1529
|
+
'ssoUrl',
|
|
1530
|
+
],
|
|
1531
|
+
where: {
|
|
1532
|
+
AppId: 1,
|
|
1533
|
+
},
|
|
1534
|
+
});
|
|
1535
|
+
expect(appSamlSecret.toJSON()).toStrictEqual({
|
|
1536
|
+
emailAttribute: 'email',
|
|
1537
|
+
emailVerifiedAttribute: null,
|
|
1538
|
+
entityId: 'http://localhost:1234',
|
|
1539
|
+
icon: 'redhat',
|
|
1540
|
+
id: 1,
|
|
1541
|
+
idpCertificate: 'certificate',
|
|
1542
|
+
name: 'test-saml-secret',
|
|
1543
|
+
nameAttribute: 'name',
|
|
1544
|
+
ssoUrl: 'http://localhost:1234',
|
|
1545
|
+
spCertificate: expect.any(String),
|
|
1546
|
+
});
|
|
1547
|
+
const appOauth2Secret = await AppOAuth2Secret.findOne({
|
|
1548
|
+
attributes: [
|
|
1549
|
+
'name',
|
|
1550
|
+
'icon',
|
|
1551
|
+
'scope',
|
|
1552
|
+
'remapper',
|
|
1553
|
+
'authorizationUrl',
|
|
1554
|
+
'tokenUrl',
|
|
1555
|
+
'userInfoUrl',
|
|
1556
|
+
'clientId',
|
|
1557
|
+
'clientSecret',
|
|
1558
|
+
],
|
|
1559
|
+
where: {
|
|
1560
|
+
AppId: 1,
|
|
1561
|
+
},
|
|
1562
|
+
});
|
|
1563
|
+
expect({
|
|
1564
|
+
authorizationUrl: appOauth2Secret.authorizationUrl,
|
|
1565
|
+
clientId: appOauth2Secret.clientId,
|
|
1566
|
+
clientSecret: appOauth2Secret.clientSecret,
|
|
1567
|
+
icon: appOauth2Secret.icon,
|
|
1568
|
+
name: appOauth2Secret.name,
|
|
1569
|
+
remapper: appOauth2Secret.remapper,
|
|
1570
|
+
scope: appOauth2Secret.scope,
|
|
1571
|
+
tokenUrl: appOauth2Secret.tokenUrl,
|
|
1572
|
+
userInfoUrl: appOauth2Secret.userInfoUrl,
|
|
1573
|
+
}).toStrictEqual({
|
|
1574
|
+
authorizationUrl: 'http://localhost:1234',
|
|
1575
|
+
clientId: 'id',
|
|
1576
|
+
clientSecret: 'secret',
|
|
1577
|
+
icon: 'redhat',
|
|
1578
|
+
name: 'test-oauth2-secret',
|
|
1579
|
+
remapper: [{ prop: 'email' }],
|
|
1580
|
+
scope: 'email openid profile',
|
|
1581
|
+
tokenUrl: 'http://localhost:1234',
|
|
1582
|
+
userInfoUrl: 'http://localhost:1234',
|
|
1583
|
+
});
|
|
1546
1584
|
});
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
'
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
'
|
|
1557
|
-
'
|
|
1585
|
+
it('should update an app with `app.locked` set to `fullLock` if force is specified', async () => {
|
|
1586
|
+
await app.update({ locked: 'fullLock' });
|
|
1587
|
+
const clientCredentials = await authorizeCLI('apps:write', testApp);
|
|
1588
|
+
await updateApp({
|
|
1589
|
+
path: resolveFixture('apps/test'),
|
|
1590
|
+
force: true,
|
|
1591
|
+
remote: testApp.defaults.baseURL,
|
|
1592
|
+
id: app.id,
|
|
1593
|
+
clientCredentials,
|
|
1594
|
+
visibility: 'public',
|
|
1595
|
+
iconBackground: '#fff999',
|
|
1596
|
+
});
|
|
1597
|
+
await app.reload();
|
|
1598
|
+
expect(app).toMatchInlineSnapshot(`
|
|
1599
|
+
{
|
|
1600
|
+
"$created": "1970-01-01T00:00:00.000Z",
|
|
1601
|
+
"$updated": "1970-01-01T00:00:00.000Z",
|
|
1602
|
+
"OrganizationId": "testorganization",
|
|
1603
|
+
"OrganizationName": undefined,
|
|
1604
|
+
"controllerCode": null,
|
|
1605
|
+
"controllerImplementations": null,
|
|
1606
|
+
"coreStyle": ".tux {
|
|
1607
|
+
color: rgb(0 0 0);
|
|
1608
|
+
}
|
|
1609
|
+
",
|
|
1610
|
+
"definition": {
|
|
1611
|
+
"defaultPage": "Test Page",
|
|
1612
|
+
"name": "Test App",
|
|
1613
|
+
"pages": [
|
|
1614
|
+
{
|
|
1615
|
+
"blocks": [
|
|
1616
|
+
{
|
|
1617
|
+
"type": "test",
|
|
1618
|
+
"version": "0.0.0",
|
|
1619
|
+
},
|
|
1620
|
+
],
|
|
1621
|
+
"name": "Test Page",
|
|
1622
|
+
},
|
|
1558
1623
|
],
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
name: appOauth2Secret.name,
|
|
1569
|
-
remapper: appOauth2Secret.remapper,
|
|
1570
|
-
scope: appOauth2Secret.scope,
|
|
1571
|
-
tokenUrl: appOauth2Secret.tokenUrl,
|
|
1572
|
-
userInfoUrl: appOauth2Secret.userInfoUrl,
|
|
1573
|
-
}).toStrictEqual({
|
|
1574
|
-
authorizationUrl: 'http://localhost:1234',
|
|
1575
|
-
clientId: 'id',
|
|
1576
|
-
clientSecret: 'secret',
|
|
1577
|
-
icon: 'redhat',
|
|
1578
|
-
name: 'test-oauth2-secret',
|
|
1579
|
-
remapper: [{ prop: 'email' }],
|
|
1580
|
-
scope: 'email openid profile',
|
|
1581
|
-
tokenUrl: 'http://localhost:1234',
|
|
1582
|
-
userInfoUrl: 'http://localhost:1234',
|
|
1583
|
-
});
|
|
1584
|
-
});
|
|
1585
|
-
it('should update an app with `app.locked` set to `fullLock` if force is specified', async () => {
|
|
1586
|
-
await app.update({ locked: 'fullLock' });
|
|
1587
|
-
const clientCredentials = await authorizeCLI('apps:write', testApp);
|
|
1588
|
-
await updateApp({
|
|
1589
|
-
path: resolveFixture('apps/test'),
|
|
1590
|
-
force: true,
|
|
1591
|
-
remote: testApp.defaults.baseURL,
|
|
1592
|
-
id: app.id,
|
|
1593
|
-
clientCredentials,
|
|
1594
|
-
visibility: 'public',
|
|
1595
|
-
iconBackground: '#fff999',
|
|
1596
|
-
});
|
|
1597
|
-
await app.reload();
|
|
1598
|
-
expect(app).toMatchInlineSnapshot(`
|
|
1599
|
-
{
|
|
1600
|
-
"$created": "1970-01-01T00:00:00.000Z",
|
|
1601
|
-
"$updated": "1970-01-01T00:00:00.000Z",
|
|
1602
|
-
"OrganizationId": "testorganization",
|
|
1603
|
-
"OrganizationName": undefined,
|
|
1604
|
-
"controllerCode": null,
|
|
1605
|
-
"controllerImplementations": null,
|
|
1606
|
-
"coreStyle": ".tux {
|
|
1607
|
-
color: rgb(0 0 0);
|
|
1608
|
-
}
|
|
1609
|
-
",
|
|
1610
|
-
"definition": {
|
|
1611
|
-
"defaultPage": "Test Page",
|
|
1612
|
-
"name": "Test App",
|
|
1613
|
-
"pages": [
|
|
1614
|
-
{
|
|
1615
|
-
"blocks": [
|
|
1616
|
-
{
|
|
1617
|
-
"type": "test",
|
|
1618
|
-
"version": "0.0.0",
|
|
1619
|
-
},
|
|
1620
|
-
],
|
|
1621
|
-
"name": "Test Page",
|
|
1622
|
-
},
|
|
1623
|
-
],
|
|
1624
|
-
"resources": {
|
|
1625
|
-
"test": {
|
|
1626
|
-
"schema": {
|
|
1627
|
-
"additionalProperties": false,
|
|
1628
|
-
"properties": {
|
|
1629
|
-
"test": {
|
|
1630
|
-
"format": "binary",
|
|
1631
|
-
"type": "string",
|
|
1624
|
+
"resources": {
|
|
1625
|
+
"test": {
|
|
1626
|
+
"schema": {
|
|
1627
|
+
"additionalProperties": false,
|
|
1628
|
+
"properties": {
|
|
1629
|
+
"test": {
|
|
1630
|
+
"format": "binary",
|
|
1631
|
+
"type": "string",
|
|
1632
|
+
},
|
|
1632
1633
|
},
|
|
1634
|
+
"type": "object",
|
|
1633
1635
|
},
|
|
1634
|
-
"type": "object",
|
|
1635
1636
|
},
|
|
1636
1637
|
},
|
|
1637
1638
|
},
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
`);
|
|
1688
|
-
});
|
|
1689
|
-
it('should not update an app if the `app.locked` is set to `fullLock`', async () => {
|
|
1690
|
-
await app.update({ locked: 'fullLock' });
|
|
1691
|
-
const clientCredentials = await authorizeCLI('apps:write', testApp);
|
|
1692
|
-
await expect(updateApp({
|
|
1693
|
-
path: resolveFixture('apps/test'),
|
|
1694
|
-
force: false,
|
|
1695
|
-
remote: testApp.defaults.baseURL,
|
|
1696
|
-
id: app.id,
|
|
1697
|
-
clientCredentials,
|
|
1698
|
-
visibility: 'public',
|
|
1699
|
-
iconBackground: '#fff999',
|
|
1700
|
-
})).rejects.toThrow('Request failed with status code 403');
|
|
1701
|
-
await app.reload();
|
|
1702
|
-
expect(app).toMatchInlineSnapshot(`
|
|
1703
|
-
{
|
|
1704
|
-
"$created": "1970-01-01T00:00:00.000Z",
|
|
1705
|
-
"$updated": "1970-01-01T00:00:00.000Z",
|
|
1706
|
-
"OrganizationId": "testorganization",
|
|
1707
|
-
"OrganizationName": undefined,
|
|
1708
|
-
"controllerCode": null,
|
|
1709
|
-
"controllerImplementations": null,
|
|
1710
|
-
"coreStyle": undefined,
|
|
1711
|
-
"definition": {
|
|
1712
|
-
"defaultPage": "Test Page",
|
|
1713
|
-
"name": "Test App",
|
|
1714
|
-
},
|
|
1715
|
-
"demoMode": false,
|
|
1716
|
-
"domain": null,
|
|
1717
|
-
"emailName": null,
|
|
1718
|
-
"enableSelfRegistration": true,
|
|
1719
|
-
"enableUnsecuredServiceSecrets": false,
|
|
1720
|
-
"googleAnalyticsID": null,
|
|
1721
|
-
"hasClonableAssets": undefined,
|
|
1722
|
-
"hasClonableResources": undefined,
|
|
1723
|
-
"hasIcon": false,
|
|
1724
|
-
"hasMaskableIcon": false,
|
|
1725
|
-
"iconBackground": "#ffffff",
|
|
1726
|
-
"iconUrl": null,
|
|
1727
|
-
"id": 1,
|
|
1728
|
-
"locked": "fullLock",
|
|
1729
|
-
"messages": undefined,
|
|
1730
|
-
"path": "test-app",
|
|
1731
|
-
"rating": undefined,
|
|
1732
|
-
"readmeUrl": undefined,
|
|
1733
|
-
"screenshotUrls": undefined,
|
|
1734
|
-
"sentryDsn": null,
|
|
1735
|
-
"sentryEnvironment": null,
|
|
1736
|
-
"sharedStyle": undefined,
|
|
1737
|
-
"showAppDefinition": false,
|
|
1738
|
-
"showAppsembleLogin": false,
|
|
1739
|
-
"showAppsembleOAuth2Login": true,
|
|
1740
|
-
"template": false,
|
|
1741
|
-
"visibility": "public",
|
|
1742
|
-
"yaml": "name: Test App
|
|
1743
|
-
defaultPage: Test Page
|
|
1744
|
-
",
|
|
1745
|
-
}
|
|
1746
|
-
`);
|
|
1747
|
-
});
|
|
1748
|
-
it('should validate and throw if there’s an error before updating an app', async () => {
|
|
1749
|
-
await BlockVersion.destroy({
|
|
1750
|
-
where: {
|
|
1751
|
-
version: '0.0.0',
|
|
1752
|
-
OrganizationId: 'appsemble',
|
|
1753
|
-
name: 'test',
|
|
1754
|
-
},
|
|
1639
|
+
"demoMode": false,
|
|
1640
|
+
"domain": null,
|
|
1641
|
+
"emailName": null,
|
|
1642
|
+
"enableSelfRegistration": true,
|
|
1643
|
+
"enableUnsecuredServiceSecrets": false,
|
|
1644
|
+
"googleAnalyticsID": null,
|
|
1645
|
+
"hasClonableAssets": undefined,
|
|
1646
|
+
"hasClonableResources": undefined,
|
|
1647
|
+
"hasIcon": true,
|
|
1648
|
+
"hasMaskableIcon": true,
|
|
1649
|
+
"iconBackground": "#fff999",
|
|
1650
|
+
"iconUrl": "/api/apps/1/icon?maskable=true&updated=1970-01-01T00%3A00%3A00.000Z",
|
|
1651
|
+
"id": 1,
|
|
1652
|
+
"locked": "fullLock",
|
|
1653
|
+
"messages": undefined,
|
|
1654
|
+
"path": "test-app",
|
|
1655
|
+
"rating": undefined,
|
|
1656
|
+
"readmeUrl": undefined,
|
|
1657
|
+
"screenshotUrls": undefined,
|
|
1658
|
+
"sentryDsn": null,
|
|
1659
|
+
"sentryEnvironment": null,
|
|
1660
|
+
"sharedStyle": ".tux {
|
|
1661
|
+
color: rgb(0 0 0);
|
|
1662
|
+
}
|
|
1663
|
+
",
|
|
1664
|
+
"showAppDefinition": false,
|
|
1665
|
+
"showAppsembleLogin": false,
|
|
1666
|
+
"showAppsembleOAuth2Login": true,
|
|
1667
|
+
"template": false,
|
|
1668
|
+
"visibility": "public",
|
|
1669
|
+
"yaml": "name: Test App
|
|
1670
|
+
defaultPage: Test Page
|
|
1671
|
+
resources:
|
|
1672
|
+
test:
|
|
1673
|
+
schema:
|
|
1674
|
+
additionalProperties: false
|
|
1675
|
+
type: object
|
|
1676
|
+
properties:
|
|
1677
|
+
test:
|
|
1678
|
+
type: string
|
|
1679
|
+
format: binary
|
|
1680
|
+
pages:
|
|
1681
|
+
- name: Test Page
|
|
1682
|
+
blocks:
|
|
1683
|
+
- type: test
|
|
1684
|
+
version: 0.0.0
|
|
1685
|
+
",
|
|
1686
|
+
}
|
|
1687
|
+
`);
|
|
1755
1688
|
});
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
"
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
"vapidPublicKey": "a",
|
|
1815
|
-
"visibility": "public",
|
|
1816
|
-
}
|
|
1817
|
-
`);
|
|
1818
|
-
});
|
|
1819
|
-
});
|
|
1820
|
-
describe('patchApp', () => {
|
|
1821
|
-
it('should apply patches to app', async () => {
|
|
1822
|
-
const patches = {
|
|
1823
|
-
demoMode: true,
|
|
1824
|
-
enableSelfRegistration: true,
|
|
1825
|
-
iconBackground: '#FFFFFF',
|
|
1826
|
-
locked: 'fullLock',
|
|
1827
|
-
path: 'updated-path',
|
|
1828
|
-
showAppDefinition: true,
|
|
1829
|
-
showAppsembleLogin: true,
|
|
1830
|
-
showAppsembleOAuth2Login: true,
|
|
1831
|
-
template: true,
|
|
1832
|
-
visibility: 'private',
|
|
1833
|
-
};
|
|
1834
|
-
const app = await App.create({
|
|
1835
|
-
path: 'test-app',
|
|
1836
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
1837
|
-
vapidPublicKey: 'a',
|
|
1838
|
-
vapidPrivateKey: 'b',
|
|
1839
|
-
visibility: 'public',
|
|
1840
|
-
OrganizationId: organization.id,
|
|
1841
|
-
}, { raw: true });
|
|
1842
|
-
await authorizeCLI('apps:write', testApp);
|
|
1843
|
-
await patchApp({
|
|
1844
|
-
...patches,
|
|
1845
|
-
remote: testApp.defaults.baseURL,
|
|
1846
|
-
id: app.id,
|
|
1689
|
+
it('should not update an app if the `app.locked` is set to `fullLock`', async () => {
|
|
1690
|
+
await app.update({ locked: 'fullLock' });
|
|
1691
|
+
const clientCredentials = await authorizeCLI('apps:write', testApp);
|
|
1692
|
+
await expect(updateApp({
|
|
1693
|
+
path: resolveFixture('apps/test'),
|
|
1694
|
+
force: false,
|
|
1695
|
+
remote: testApp.defaults.baseURL,
|
|
1696
|
+
id: app.id,
|
|
1697
|
+
clientCredentials,
|
|
1698
|
+
visibility: 'public',
|
|
1699
|
+
iconBackground: '#fff999',
|
|
1700
|
+
})).rejects.toThrow('Request failed with status code 403');
|
|
1701
|
+
await app.reload();
|
|
1702
|
+
expect(app).toMatchInlineSnapshot(`
|
|
1703
|
+
{
|
|
1704
|
+
"$created": "1970-01-01T00:00:00.000Z",
|
|
1705
|
+
"$updated": "1970-01-01T00:00:00.000Z",
|
|
1706
|
+
"OrganizationId": "testorganization",
|
|
1707
|
+
"OrganizationName": undefined,
|
|
1708
|
+
"controllerCode": null,
|
|
1709
|
+
"controllerImplementations": null,
|
|
1710
|
+
"coreStyle": undefined,
|
|
1711
|
+
"definition": {
|
|
1712
|
+
"defaultPage": "Test Page",
|
|
1713
|
+
"name": "Test App",
|
|
1714
|
+
},
|
|
1715
|
+
"demoMode": false,
|
|
1716
|
+
"domain": null,
|
|
1717
|
+
"emailName": null,
|
|
1718
|
+
"enableSelfRegistration": true,
|
|
1719
|
+
"enableUnsecuredServiceSecrets": false,
|
|
1720
|
+
"googleAnalyticsID": null,
|
|
1721
|
+
"hasClonableAssets": undefined,
|
|
1722
|
+
"hasClonableResources": undefined,
|
|
1723
|
+
"hasIcon": false,
|
|
1724
|
+
"hasMaskableIcon": false,
|
|
1725
|
+
"iconBackground": "#ffffff",
|
|
1726
|
+
"iconUrl": null,
|
|
1727
|
+
"id": 1,
|
|
1728
|
+
"locked": "fullLock",
|
|
1729
|
+
"messages": undefined,
|
|
1730
|
+
"path": "test-app",
|
|
1731
|
+
"rating": undefined,
|
|
1732
|
+
"readmeUrl": undefined,
|
|
1733
|
+
"screenshotUrls": undefined,
|
|
1734
|
+
"sentryDsn": null,
|
|
1735
|
+
"sentryEnvironment": null,
|
|
1736
|
+
"sharedStyle": undefined,
|
|
1737
|
+
"showAppDefinition": false,
|
|
1738
|
+
"showAppsembleLogin": false,
|
|
1739
|
+
"showAppsembleOAuth2Login": true,
|
|
1740
|
+
"template": false,
|
|
1741
|
+
"visibility": "public",
|
|
1742
|
+
"yaml": "name: Test App
|
|
1743
|
+
defaultPage: Test Page
|
|
1744
|
+
",
|
|
1745
|
+
}
|
|
1746
|
+
`);
|
|
1847
1747
|
});
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
${'visibility'} | ${'public'} | ${'unlisted'}
|
|
1919
|
-
${'visibility'} | ${'public'} | ${'private'}
|
|
1920
|
-
${'visibility'} | ${'private'} | ${'public'}
|
|
1921
|
-
`('should patch $key from `$from` to `$to`', async ({ from, key, to }) => {
|
|
1922
|
-
const app = await App.create({
|
|
1923
|
-
path: 'test-app',
|
|
1924
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
1925
|
-
vapidPublicKey: 'a',
|
|
1926
|
-
vapidPrivateKey: 'b',
|
|
1927
|
-
visibility: 'public',
|
|
1928
|
-
OrganizationId: organization.id,
|
|
1929
|
-
[key]: from,
|
|
1930
|
-
}, { raw: true });
|
|
1931
|
-
await authorizeCLI('apps:write', testApp);
|
|
1932
|
-
await patchApp({
|
|
1933
|
-
[key]: to,
|
|
1934
|
-
remote: testApp.defaults.baseURL,
|
|
1935
|
-
id: app.id,
|
|
1748
|
+
it('should validate and throw if there’s an error before updating an app', async () => {
|
|
1749
|
+
await BlockVersion.destroy({
|
|
1750
|
+
where: {
|
|
1751
|
+
version: '0.0.0',
|
|
1752
|
+
OrganizationId: 'appsemble',
|
|
1753
|
+
name: 'test',
|
|
1754
|
+
},
|
|
1755
|
+
});
|
|
1756
|
+
vi.useRealTimers();
|
|
1757
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
1758
|
+
await expect(updateApp({
|
|
1759
|
+
path: resolveFixture('apps/test'),
|
|
1760
|
+
id: app.id,
|
|
1761
|
+
force: false,
|
|
1762
|
+
remote: testApp.defaults.baseURL,
|
|
1763
|
+
clientCredentials,
|
|
1764
|
+
// Required defaults
|
|
1765
|
+
visibility: 'unlisted',
|
|
1766
|
+
iconBackground: '#ffffff',
|
|
1767
|
+
})).rejects.toThrow('is not a known block type');
|
|
1768
|
+
vi.useFakeTimers();
|
|
1769
|
+
await app.reload();
|
|
1770
|
+
expect(app.dataValues).toMatchInlineSnapshot(`
|
|
1771
|
+
{
|
|
1772
|
+
"OrganizationId": "testorganization",
|
|
1773
|
+
"containers": null,
|
|
1774
|
+
"controllerCode": null,
|
|
1775
|
+
"controllerImplementations": null,
|
|
1776
|
+
"coreStyle": null,
|
|
1777
|
+
"created": 1970-01-01T00:00:00.000Z,
|
|
1778
|
+
"definition": {
|
|
1779
|
+
"defaultPage": "Test Page",
|
|
1780
|
+
"name": "Test App",
|
|
1781
|
+
},
|
|
1782
|
+
"deleted": null,
|
|
1783
|
+
"demoMode": false,
|
|
1784
|
+
"domain": null,
|
|
1785
|
+
"emailHost": null,
|
|
1786
|
+
"emailName": null,
|
|
1787
|
+
"emailPassword": null,
|
|
1788
|
+
"emailPort": 587,
|
|
1789
|
+
"emailSecure": true,
|
|
1790
|
+
"emailUser": null,
|
|
1791
|
+
"enableSelfRegistration": true,
|
|
1792
|
+
"enableUnsecuredServiceSecrets": false,
|
|
1793
|
+
"googleAnalyticsID": null,
|
|
1794
|
+
"icon": null,
|
|
1795
|
+
"iconBackground": null,
|
|
1796
|
+
"id": 1,
|
|
1797
|
+
"locked": "unlocked",
|
|
1798
|
+
"maskableIcon": null,
|
|
1799
|
+
"path": "test-app",
|
|
1800
|
+
"registry": null,
|
|
1801
|
+
"scimEnabled": false,
|
|
1802
|
+
"scimToken": null,
|
|
1803
|
+
"sentryDsn": null,
|
|
1804
|
+
"sentryEnvironment": null,
|
|
1805
|
+
"sharedStyle": null,
|
|
1806
|
+
"showAppDefinition": false,
|
|
1807
|
+
"showAppsembleLogin": false,
|
|
1808
|
+
"showAppsembleOAuth2Login": true,
|
|
1809
|
+
"sslCertificate": null,
|
|
1810
|
+
"sslKey": null,
|
|
1811
|
+
"template": false,
|
|
1812
|
+
"updated": 1970-01-01T00:00:00.000Z,
|
|
1813
|
+
"vapidPrivateKey": "b",
|
|
1814
|
+
"vapidPublicKey": "a",
|
|
1815
|
+
"visibility": "public",
|
|
1816
|
+
}
|
|
1817
|
+
`);
|
|
1936
1818
|
});
|
|
1937
|
-
expect(app.dataValues[key]).toStrictEqual(from);
|
|
1938
|
-
await app.reload();
|
|
1939
|
-
expect(app.dataValues[key]).toStrictEqual(to);
|
|
1940
1819
|
});
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1820
|
+
describe('patchApp', () => {
|
|
1821
|
+
it('should apply patches to app', async () => {
|
|
1822
|
+
const patches = {
|
|
1823
|
+
demoMode: true,
|
|
1824
|
+
enableSelfRegistration: true,
|
|
1825
|
+
iconBackground: '#FFFFFF',
|
|
1826
|
+
locked: 'fullLock',
|
|
1827
|
+
path: 'updated-path',
|
|
1828
|
+
showAppDefinition: true,
|
|
1829
|
+
showAppsembleLogin: true,
|
|
1830
|
+
showAppsembleOAuth2Login: true,
|
|
1831
|
+
template: true,
|
|
1832
|
+
visibility: 'private',
|
|
1833
|
+
};
|
|
1834
|
+
const app = await App.create({
|
|
1835
|
+
path: 'test-app',
|
|
1836
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
1837
|
+
vapidPublicKey: 'a',
|
|
1838
|
+
vapidPrivateKey: 'b',
|
|
1839
|
+
visibility: 'public',
|
|
1840
|
+
OrganizationId: organization.id,
|
|
1841
|
+
}, { raw: true });
|
|
1842
|
+
await authorizeCLI('apps:write', testApp);
|
|
1843
|
+
await patchApp({
|
|
1844
|
+
...patches,
|
|
1845
|
+
remote: testApp.defaults.baseURL,
|
|
1846
|
+
id: app.id,
|
|
1847
|
+
});
|
|
1848
|
+
await app.reload();
|
|
1849
|
+
expect(app.dataValues).toStrictEqual(expect.objectContaining({ ...app.dataValues, ...patches }));
|
|
1850
|
+
expect(app.dataValues).toMatchInlineSnapshot(`
|
|
1851
|
+
{
|
|
1852
|
+
"OrganizationId": "testorganization",
|
|
1853
|
+
"containers": null,
|
|
1854
|
+
"controllerCode": null,
|
|
1855
|
+
"controllerImplementations": null,
|
|
1856
|
+
"coreStyle": null,
|
|
1857
|
+
"created": 1970-01-01T00:00:00.000Z,
|
|
1858
|
+
"definition": {
|
|
1859
|
+
"defaultPage": "Test Page",
|
|
1860
|
+
"name": "Test App",
|
|
1861
|
+
},
|
|
1862
|
+
"deleted": null,
|
|
1863
|
+
"demoMode": true,
|
|
1864
|
+
"domain": null,
|
|
1865
|
+
"emailHost": null,
|
|
1866
|
+
"emailName": null,
|
|
1867
|
+
"emailPassword": null,
|
|
1868
|
+
"emailPort": 587,
|
|
1869
|
+
"emailSecure": true,
|
|
1870
|
+
"emailUser": null,
|
|
1871
|
+
"enableSelfRegistration": true,
|
|
1872
|
+
"enableUnsecuredServiceSecrets": false,
|
|
1873
|
+
"googleAnalyticsID": null,
|
|
1874
|
+
"icon": null,
|
|
1875
|
+
"iconBackground": "#FFFFFF",
|
|
1876
|
+
"id": 1,
|
|
1877
|
+
"locked": "fullLock",
|
|
1878
|
+
"maskableIcon": null,
|
|
1879
|
+
"path": "updated-path",
|
|
1880
|
+
"registry": null,
|
|
1881
|
+
"scimEnabled": false,
|
|
1882
|
+
"scimToken": null,
|
|
1883
|
+
"sentryDsn": null,
|
|
1884
|
+
"sentryEnvironment": null,
|
|
1885
|
+
"sharedStyle": null,
|
|
1886
|
+
"showAppDefinition": true,
|
|
1887
|
+
"showAppsembleLogin": true,
|
|
1888
|
+
"showAppsembleOAuth2Login": true,
|
|
1889
|
+
"sslCertificate": null,
|
|
1890
|
+
"sslKey": null,
|
|
1891
|
+
"template": true,
|
|
1892
|
+
"updated": 1970-01-01T00:00:00.000Z,
|
|
1893
|
+
"vapidPrivateKey": "b",
|
|
1894
|
+
"vapidPublicKey": "a",
|
|
1895
|
+
"visibility": "private",
|
|
1896
|
+
}
|
|
1897
|
+
`);
|
|
1957
1898
|
});
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1899
|
+
it.each `
|
|
1900
|
+
key | from | to
|
|
1901
|
+
${'demoMode'} | ${false} | ${true}
|
|
1902
|
+
${'demoMode'} | ${true} | ${false}
|
|
1903
|
+
${'enableSelfRegistration'} | ${false} | ${true}
|
|
1904
|
+
${'enableSelfRegistration'} | ${true} | ${false}
|
|
1905
|
+
${'iconBackground'} | ${''} | ${'#FFFFFF'}
|
|
1906
|
+
${'path'} | ${'before'} | ${'after'}
|
|
1907
|
+
${'locked'} | ${'unlocked'} | ${'studioLock'}
|
|
1908
|
+
${'locked'} | ${'unlocked'} | ${'fullLock'}
|
|
1909
|
+
${'locked'} | ${'fullLock'} | ${'unlocked'}
|
|
1910
|
+
${'showAppDefinition'} | ${false} | ${true}
|
|
1911
|
+
${'showAppDefinition'} | ${true} | ${false}
|
|
1912
|
+
${'showAppsembleLogin'} | ${false} | ${true}
|
|
1913
|
+
${'showAppsembleLogin'} | ${true} | ${false}
|
|
1914
|
+
${'showAppsembleOAuth2Login'} | ${false} | ${true}
|
|
1915
|
+
${'showAppsembleOAuth2Login'} | ${true} | ${false}
|
|
1916
|
+
${'template'} | ${false} | ${true}
|
|
1917
|
+
${'template'} | ${true} | ${false}
|
|
1918
|
+
${'visibility'} | ${'public'} | ${'unlisted'}
|
|
1919
|
+
${'visibility'} | ${'public'} | ${'private'}
|
|
1920
|
+
${'visibility'} | ${'private'} | ${'public'}
|
|
1921
|
+
`('should patch $key from `$from` to `$to`', async ({ from, key, to }) => {
|
|
1922
|
+
const app = await App.create({
|
|
1923
|
+
path: 'test-app',
|
|
1924
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
1925
|
+
vapidPublicKey: 'a',
|
|
1926
|
+
vapidPrivateKey: 'b',
|
|
1927
|
+
visibility: 'public',
|
|
1928
|
+
OrganizationId: organization.id,
|
|
1929
|
+
[key]: from,
|
|
1930
|
+
}, { raw: true });
|
|
1931
|
+
await authorizeCLI('apps:write', testApp);
|
|
1932
|
+
await patchApp({
|
|
1933
|
+
[key]: to,
|
|
1934
|
+
remote: testApp.defaults.baseURL,
|
|
1935
|
+
id: app.id,
|
|
1936
|
+
});
|
|
1937
|
+
expect(app.dataValues[key]).toStrictEqual(from);
|
|
1938
|
+
await app.reload();
|
|
1939
|
+
expect(app.dataValues[key]).toStrictEqual(to);
|
|
1940
|
+
});
|
|
1941
|
+
it('should not apply a patch if the `app.locked` is set to `fullLock`', async () => {
|
|
1942
|
+
const app = await App.create({
|
|
1943
|
+
path: 'test-app',
|
|
1944
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
1945
|
+
vapidPublicKey: 'a',
|
|
1946
|
+
vapidPrivateKey: 'b',
|
|
1947
|
+
visibility: 'public',
|
|
1948
|
+
OrganizationId: organization.id,
|
|
1949
|
+
locked: 'fullLock',
|
|
1950
|
+
showAppDefinition: false,
|
|
1951
|
+
}, { raw: true });
|
|
1952
|
+
await authorizeCLI('apps:write', testApp);
|
|
1953
|
+
await patchApp({
|
|
1954
|
+
remote: testApp.defaults.baseURL,
|
|
1955
|
+
id: app.id,
|
|
1956
|
+
showAppDefinition: true,
|
|
1957
|
+
});
|
|
1958
|
+
expect(app.dataValues.showAppDefinition).toBe(false);
|
|
1959
|
+
await app.reload();
|
|
1960
|
+
expect(app.dataValues.showAppDefinition).toBe(false);
|
|
1961
|
+
});
|
|
1962
|
+
it('should apply a patch if the `app.locked` is set to `fullLock` and `force` is specified', async () => {
|
|
1963
|
+
const app = await App.create({
|
|
1964
|
+
path: 'test-app',
|
|
1965
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
1966
|
+
vapidPublicKey: 'a',
|
|
1967
|
+
vapidPrivateKey: 'b',
|
|
1968
|
+
visibility: 'public',
|
|
1969
|
+
OrganizationId: organization.id,
|
|
1970
|
+
locked: 'fullLock',
|
|
1971
|
+
showAppDefinition: false,
|
|
1972
|
+
}, { raw: true });
|
|
1973
|
+
await authorizeCLI('apps:write', testApp);
|
|
1974
|
+
await patchApp({
|
|
1975
|
+
remote: testApp.defaults.baseURL,
|
|
1976
|
+
id: app.id,
|
|
1977
|
+
showAppDefinition: true,
|
|
1978
|
+
force: true,
|
|
1979
|
+
});
|
|
1980
|
+
expect(app.dataValues.showAppDefinition).toBe(false);
|
|
1981
|
+
await app.reload();
|
|
1982
|
+
expect(app.dataValues.showAppDefinition).toBe(true);
|
|
1979
1983
|
});
|
|
1980
|
-
expect(app.dataValues.showAppDefinition).toBe(false);
|
|
1981
|
-
await app.reload();
|
|
1982
|
-
expect(app.dataValues.showAppDefinition).toBe(true);
|
|
1983
1984
|
});
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
}, `
|
|
1985
|
+
describe('traverseAppDirectory', () => {
|
|
1986
|
+
it('should read the app definition and appsembleRC from the directory', async () => {
|
|
1987
|
+
const formData = new FormData();
|
|
1988
|
+
const [appsembleContext, appsembleRC, yaml, app] = await traverseAppDirectory(resolveFixture('apps/test'), 'test', formData);
|
|
1989
|
+
expect(appsembleContext).toMatchInlineSnapshot({
|
|
1990
|
+
icon: expect.any(String),
|
|
1991
|
+
maskableIcon: expect.any(String),
|
|
1992
|
+
}, `
|
|
1993
1993
|
{
|
|
1994
1994
|
"appLock": "studioLock",
|
|
1995
1995
|
"assets": true,
|
|
@@ -2012,14 +2012,14 @@ describe('traverseAppDirectory', () => {
|
|
|
2012
2012
|
"visibility": "public",
|
|
2013
2013
|
}
|
|
2014
2014
|
`);
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2015
|
+
expect(appsembleRC).toMatchInlineSnapshot({
|
|
2016
|
+
context: {
|
|
2017
|
+
test: {
|
|
2018
|
+
icon: expect.any(String),
|
|
2019
|
+
maskableIcon: expect.any(String),
|
|
2020
|
+
},
|
|
2020
2021
|
},
|
|
2021
|
-
},
|
|
2022
|
-
}, `
|
|
2022
|
+
}, `
|
|
2023
2023
|
{
|
|
2024
2024
|
"context": {
|
|
2025
2025
|
"notFound": {
|
|
@@ -2053,30 +2053,30 @@ describe('traverseAppDirectory', () => {
|
|
|
2053
2053
|
},
|
|
2054
2054
|
}
|
|
2055
2055
|
`);
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2056
|
+
expect(yaml).toMatchInlineSnapshot(`
|
|
2057
|
+
"name: Test App
|
|
2058
|
+
defaultPage: Test Page
|
|
2059
2059
|
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2060
|
+
resources:
|
|
2061
|
+
test:
|
|
2062
|
+
schema:
|
|
2063
|
+
additionalProperties: false
|
|
2064
|
+
type: object
|
|
2065
|
+
properties:
|
|
2066
|
+
test:
|
|
2067
|
+
type: string
|
|
2068
|
+
format: binary
|
|
2069
2069
|
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2070
|
+
pages:
|
|
2071
|
+
- name: Test Page
|
|
2072
|
+
blocks:
|
|
2073
|
+
- type: test
|
|
2074
|
+
version: 0.0.0
|
|
2075
|
+
"
|
|
2076
|
+
`);
|
|
2077
|
+
expect(app).toMatchInlineSnapshot({
|
|
2078
|
+
iconUrl: expect.any(String),
|
|
2079
|
+
}, `
|
|
2080
2080
|
{
|
|
2081
2081
|
"coreStyle": ".tux {
|
|
2082
2082
|
color: rgb(0 0 0);
|
|
@@ -2122,87 +2122,88 @@ describe('traverseAppDirectory', () => {
|
|
|
2122
2122
|
",
|
|
2123
2123
|
}
|
|
2124
2124
|
`);
|
|
2125
|
-
});
|
|
2126
|
-
it('should return an error if no app-definition is found in the given directory', async () => {
|
|
2127
|
-
const formData = new FormData();
|
|
2128
|
-
await expect(() => traverseAppDirectory(resolveFixture('apps/empty'), null, formData)).rejects.toThrow('No app definition found');
|
|
2129
|
-
});
|
|
2130
|
-
});
|
|
2131
|
-
describe('resolveAppIdAndRemote', () => {
|
|
2132
|
-
it('should find and return app id and remote from appsembleRC', async () => {
|
|
2133
|
-
const [appId, remote] = await resolveAppIdAndRemote(resolveFixture('apps/test'), 'resolve', 'http://localhost:8888', 55);
|
|
2134
|
-
expect(appId).toBe(5);
|
|
2135
|
-
expect(remote).toBe('http://localhost:5555/');
|
|
2136
|
-
});
|
|
2137
|
-
it('should fallback to default appId and remote if not found in context', async () => {
|
|
2138
|
-
const [appId, remote] = await resolveAppIdAndRemote(resolveFixture('apps/test'), 'notFound', 'http://localhost:8888', 55);
|
|
2139
|
-
expect(appId).toBe(55);
|
|
2140
|
-
expect(remote).toBe('http://localhost:8888/');
|
|
2141
|
-
});
|
|
2142
|
-
it('should throw if the appId is not found in context and defaultAppId is not specified', async () => {
|
|
2143
|
-
await expect(() => resolveAppIdAndRemote(resolveFixture('apps/test'), 'notFound', 'http://localhost:8888', null)).rejects.toThrow('App ID was not found');
|
|
2144
|
-
});
|
|
2145
|
-
it('should throw if the remote is not found in context and defaultAppRemote is not specified', async () => {
|
|
2146
|
-
const app = await App.create({
|
|
2147
|
-
path: 'test-app',
|
|
2148
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
2149
|
-
vapidPublicKey: 'a',
|
|
2150
|
-
vapidPrivateKey: 'b',
|
|
2151
|
-
visibility: 'public',
|
|
2152
|
-
OrganizationId: organization.id,
|
|
2153
2125
|
});
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
describe('deleteApp', () => {
|
|
2158
|
-
it('should throw if an error occurs', async () => {
|
|
2159
|
-
const clientCredentials = await authorizeCLI('apps:delete', testApp);
|
|
2160
|
-
await expect(() => deleteApp({ id: 1, remote: testApp.defaults.baseURL, clientCredentials })).rejects.toThrow('Request failed with status code 404');
|
|
2161
|
-
});
|
|
2162
|
-
it('should delete an app', async () => {
|
|
2163
|
-
const app = await App.create({
|
|
2164
|
-
path: 'test-app',
|
|
2165
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
2166
|
-
vapidPublicKey: 'a',
|
|
2167
|
-
vapidPrivateKey: 'b',
|
|
2168
|
-
visibility: 'public',
|
|
2169
|
-
OrganizationId: organization.id,
|
|
2126
|
+
it('should return an error if no app-definition is found in the given directory', async () => {
|
|
2127
|
+
const formData = new FormData();
|
|
2128
|
+
await expect(() => traverseAppDirectory(resolveFixture('apps/empty'), null, formData)).rejects.toThrow('No app definition found');
|
|
2170
2129
|
});
|
|
2171
|
-
const clientCredentials = await authorizeCLI('apps:delete', testApp);
|
|
2172
|
-
await deleteApp({ id: app.id, remote: testApp.defaults.baseURL, clientCredentials });
|
|
2173
|
-
const foundApps = await App.findAll();
|
|
2174
|
-
expect(foundApps).toStrictEqual([]);
|
|
2175
2130
|
});
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
app: {},
|
|
2131
|
+
describe('resolveAppIdAndRemote', () => {
|
|
2132
|
+
it('should find and return app id and remote from appsembleRC', async () => {
|
|
2133
|
+
const [appId, remote] = await resolveAppIdAndRemote(resolveFixture('apps/test'), 'resolve', 'http://localhost:8888', 55);
|
|
2134
|
+
expect(appId).toBe(5);
|
|
2135
|
+
expect(remote).toBe('http://localhost:5555/');
|
|
2182
2136
|
});
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2137
|
+
it('should fallback to default appId and remote if not found in context', async () => {
|
|
2138
|
+
const [appId, remote] = await resolveAppIdAndRemote(resolveFixture('apps/test'), 'notFound', 'http://localhost:8888', 55);
|
|
2139
|
+
expect(appId).toBe(55);
|
|
2140
|
+
expect(remote).toBe('http://localhost:8888/');
|
|
2141
|
+
});
|
|
2142
|
+
it('should throw if the appId is not found in context and defaultAppId is not specified', async () => {
|
|
2143
|
+
await expect(() => resolveAppIdAndRemote(resolveFixture('apps/test'), 'notFound', 'http://localhost:8888', null)).rejects.toThrow('App ID was not found');
|
|
2144
|
+
});
|
|
2145
|
+
it('should throw if the remote is not found in context and defaultAppRemote is not specified', async () => {
|
|
2146
|
+
const app = await App.create({
|
|
2147
|
+
path: 'test-app',
|
|
2148
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
2149
|
+
vapidPublicKey: 'a',
|
|
2150
|
+
vapidPrivateKey: 'b',
|
|
2151
|
+
visibility: 'public',
|
|
2152
|
+
OrganizationId: organization.id,
|
|
2153
|
+
});
|
|
2154
|
+
await expect(() => resolveAppIdAndRemote(resolveFixture('apps/test'), 'notFound', null, app.id)).rejects.toThrow('App remote was not found');
|
|
2191
2155
|
});
|
|
2192
|
-
await writeFile(resolveFixture('apps/test-messages/i18n/nl.json'), JSON.stringify(initialMessages, null, '\t'));
|
|
2193
|
-
});
|
|
2194
|
-
it('should throw if the language file does not exist', async () => {
|
|
2195
|
-
await expect(() => writeAppMessages(resolveFixture('apps/test-messages'), ['hr'], [], 'json')).rejects.toThrow('Missing translations file');
|
|
2196
2156
|
});
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2157
|
+
describe('deleteApp', () => {
|
|
2158
|
+
it('should throw if an error occurs', async () => {
|
|
2159
|
+
const clientCredentials = await authorizeCLI('apps:delete', testApp);
|
|
2160
|
+
await expect(() => deleteApp({ id: 1, remote: testApp.defaults.baseURL, clientCredentials })).rejects.toThrow('Request failed with status code 404');
|
|
2161
|
+
});
|
|
2162
|
+
it('should delete an app', async () => {
|
|
2163
|
+
const app = await App.create({
|
|
2164
|
+
path: 'test-app',
|
|
2165
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
2166
|
+
vapidPublicKey: 'a',
|
|
2167
|
+
vapidPrivateKey: 'b',
|
|
2168
|
+
visibility: 'public',
|
|
2169
|
+
OrganizationId: organization.id,
|
|
2170
|
+
});
|
|
2171
|
+
const clientCredentials = await authorizeCLI('apps:delete', testApp);
|
|
2172
|
+
await deleteApp({ id: app.id, remote: testApp.defaults.baseURL, clientCredentials });
|
|
2173
|
+
const foundApps = await App.findAll();
|
|
2174
|
+
expect(foundApps).toStrictEqual([]);
|
|
2201
2175
|
});
|
|
2202
|
-
await expect(() => writeAppMessages(resolveFixture('apps/test-messages'), ['nl'], ['nl'], 'json')).rejects.toThrow('Missing translation');
|
|
2203
2176
|
});
|
|
2204
|
-
|
|
2205
|
-
|
|
2177
|
+
describe('writeAppMessages', () => {
|
|
2178
|
+
it('should extract messages from app-definition and write to file in i18n directory', async () => {
|
|
2179
|
+
const initialMessages = JSON.parse(String(await readFixture('apps/test-messages/i18n/nl.json')));
|
|
2180
|
+
expect(initialMessages).toMatchObject({
|
|
2181
|
+
app: {},
|
|
2182
|
+
});
|
|
2183
|
+
await writeAppMessages(resolveFixture('apps/test-messages'), ['nl'], [], 'json');
|
|
2184
|
+
const messages = JSON.parse(String(await readFixture('apps/test-messages/i18n/nl.json')));
|
|
2185
|
+
expect(messages).toMatchObject({
|
|
2186
|
+
app: {
|
|
2187
|
+
description: '',
|
|
2188
|
+
name: '',
|
|
2189
|
+
'pages.test-page': '',
|
|
2190
|
+
},
|
|
2191
|
+
});
|
|
2192
|
+
await writeFile(resolveFixture('apps/test-messages/i18n/nl.json'), JSON.stringify(initialMessages, null, '\t'));
|
|
2193
|
+
});
|
|
2194
|
+
it('should throw if the language file does not exist', async () => {
|
|
2195
|
+
await expect(() => writeAppMessages(resolveFixture('apps/test-messages'), ['hr'], [], 'json')).rejects.toThrow('Missing translations file');
|
|
2196
|
+
});
|
|
2197
|
+
it('should throw if there are empty messages in a verified file', async () => {
|
|
2198
|
+
const initialMessages = JSON.parse(String(await readFixture('apps/test-messages/i18n/nl.json')));
|
|
2199
|
+
expect(initialMessages).toMatchObject({
|
|
2200
|
+
app: {},
|
|
2201
|
+
});
|
|
2202
|
+
await expect(() => writeAppMessages(resolveFixture('apps/test-messages'), ['nl'], ['nl'], 'json')).rejects.toThrow('Missing translation');
|
|
2203
|
+
});
|
|
2204
|
+
it('should throw if app definition does not exist in the app folder', async () => {
|
|
2205
|
+
await expect(() => writeAppMessages(resolveFixture('apps/empty'), ['nl'], [], 'json')).rejects.toThrow('Couldn’t find app definition');
|
|
2206
|
+
});
|
|
2206
2207
|
});
|
|
2207
2208
|
});
|
|
2208
2209
|
//# sourceMappingURL=app.test.js.map
|