@appsemble/cli 0.27.11 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/commands/app/delete.js +2 -10
- package/commands/app/export.js +2 -3
- package/commands/block/delete.js +2 -3
- package/commands/serve.js +20 -1
- package/commands/team/create.js +1 -2
- package/commands/team/delete.js +1 -2
- package/lib/app.d.ts +11 -2
- package/lib/app.js +199 -4
- package/lib/app.test.js +767 -22
- package/lib/asset.test.d.ts +1 -0
- package/lib/asset.test.js +101 -0
- package/lib/block.d.ts +2 -1
- package/lib/block.js +3 -2
- package/lib/block.test.js +52 -1
- package/lib/organization.js +5 -3
- package/lib/organization.test.d.ts +1 -0
- package/lib/organization.test.js +222 -0
- package/lib/resource.test.d.ts +1 -0
- package/lib/resource.test.js +391 -0
- package/lib/team.d.ts +6 -2
- package/lib/team.js +6 -4
- package/lib/team.test.d.ts +1 -0
- package/lib/team.test.js +606 -0
- package/lib/testUtils.d.ts +2 -0
- package/lib/testUtils.js +11 -0
- package/package.json +6 -6
- package/server/options/getAppVariables.d.ts +3 -0
- package/server/options/getAppVariables.js +4 -0
- package/server/options/index.d.ts +1 -0
- package/server/options/index.js +1 -0
- package/server/options/options.js +2 -1
- package/server/options/parseQuery.test.js +2 -0
- 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/lib/app.test.js
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { readFixture, resolveFixture } from '@appsemble/node-utils';
|
|
2
|
+
import { createServer, createTestUser, models, setArgv, useTestDatabase } from '@appsemble/server';
|
|
3
3
|
import { ISODateTimePattern } from '@appsemble/utils';
|
|
4
4
|
import { setTestApp } from 'axios-test-instance';
|
|
5
|
-
import
|
|
5
|
+
import FormData from 'form-data';
|
|
6
6
|
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
-
import { patchApp, publishApp, updateApp } from './app.js';
|
|
7
|
+
import { deleteApp, patchApp, publishApp, traverseAppDirectory, updateApp } from './app.js';
|
|
8
8
|
import { initAxios } from './initAxios.js';
|
|
9
|
-
|
|
9
|
+
import { authorizeCLI } from './testUtils.js';
|
|
10
|
+
const { App, AppBlockStyle, AppCollection, AppCollectionApp, AppMessages, AppOAuth2Secret, AppSamlSecret, AppScreenshot, AppServiceSecret, AppVariable, Asset, BlockVersion, Organization, OrganizationMember, Resource, } = models;
|
|
10
11
|
const argv = { host: 'http://localhost', secret: 'test', aesSecret: 'testSecret' };
|
|
11
12
|
let user;
|
|
12
13
|
let organization;
|
|
13
14
|
let testApp;
|
|
14
|
-
async function authorizeCLI(scopes) {
|
|
15
|
-
const OAuth2AuthorizationCode = await authorizeClientCredentials(scopes);
|
|
16
|
-
const { id, secret } = OAuth2AuthorizationCode;
|
|
17
|
-
await OAuth2AuthorizationCode.update({ secret: await hash(secret, 10) });
|
|
18
|
-
await authenticate(testApp.defaults.baseURL, scopes, `${id}:${secret}`);
|
|
19
|
-
return `${id}:${secret}`;
|
|
20
|
-
}
|
|
21
15
|
useTestDatabase(import.meta);
|
|
22
16
|
beforeAll(() => {
|
|
23
17
|
vi.useFakeTimers();
|
|
@@ -60,7 +54,7 @@ afterAll(() => {
|
|
|
60
54
|
describe('publishApp', () => {
|
|
61
55
|
it('should publish app', async () => {
|
|
62
56
|
vi.useRealTimers();
|
|
63
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write');
|
|
57
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
64
58
|
await publishApp({
|
|
65
59
|
path: resolveFixture('apps/test'),
|
|
66
60
|
organization: organization.id,
|
|
@@ -145,6 +139,7 @@ describe('publishApp', () => {
|
|
|
145
139
|
"showAppDefinition": true,
|
|
146
140
|
"showAppsembleLogin": false,
|
|
147
141
|
"showAppsembleOAuth2Login": true,
|
|
142
|
+
"template": false,
|
|
148
143
|
"visibility": "unlisted",
|
|
149
144
|
"yaml": "name: Test App
|
|
150
145
|
defaultPage: Test Page
|
|
@@ -183,9 +178,23 @@ describe('publishApp', () => {
|
|
|
183
178
|
const asset = await Asset.findAll();
|
|
184
179
|
expect(asset).toStrictEqual([]);
|
|
185
180
|
});
|
|
181
|
+
it('should throw an error if the user doesn’t have enough scope permissions', async () => {
|
|
182
|
+
const clientCredentials = await authorizeCLI('blocks:write resources:write', testApp);
|
|
183
|
+
await expect(() => publishApp({
|
|
184
|
+
path: resolveFixture('apps/test'),
|
|
185
|
+
organization: organization.id,
|
|
186
|
+
remote: testApp.defaults.baseURL,
|
|
187
|
+
clientCredentials,
|
|
188
|
+
// Required defaults
|
|
189
|
+
visibility: 'unlisted',
|
|
190
|
+
iconBackground: '#ffffff',
|
|
191
|
+
})).rejects.toThrow('write EPIPE');
|
|
192
|
+
const app = await App.findOne();
|
|
193
|
+
expect(app).toBeNull();
|
|
194
|
+
});
|
|
186
195
|
it('should publish app with resources and assets', async () => {
|
|
187
196
|
vi.useRealTimers();
|
|
188
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write');
|
|
197
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
189
198
|
await publishApp({
|
|
190
199
|
path: resolveFixture('apps/test'),
|
|
191
200
|
organization: organization.id,
|
|
@@ -273,6 +282,7 @@ describe('publishApp', () => {
|
|
|
273
282
|
"showAppDefinition": true,
|
|
274
283
|
"showAppsembleLogin": false,
|
|
275
284
|
"showAppsembleOAuth2Login": true,
|
|
285
|
+
"template": false,
|
|
276
286
|
"visibility": "unlisted",
|
|
277
287
|
"yaml": "name: Test App
|
|
278
288
|
defaultPage: Test Page
|
|
@@ -339,7 +349,7 @@ describe('publishApp', () => {
|
|
|
339
349
|
visibility: 'public',
|
|
340
350
|
});
|
|
341
351
|
vi.useRealTimers();
|
|
342
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write');
|
|
352
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
343
353
|
await publishApp({
|
|
344
354
|
path: resolveFixture('apps/test'),
|
|
345
355
|
organization: organization.id,
|
|
@@ -426,6 +436,7 @@ describe('publishApp', () => {
|
|
|
426
436
|
"showAppDefinition": true,
|
|
427
437
|
"showAppsembleLogin": false,
|
|
428
438
|
"showAppsembleOAuth2Login": true,
|
|
439
|
+
"template": true,
|
|
429
440
|
"visibility": "public",
|
|
430
441
|
"yaml": "name: Test App
|
|
431
442
|
defaultPage: Test Page
|
|
@@ -497,7 +508,7 @@ describe('publishApp', () => {
|
|
|
497
508
|
});
|
|
498
509
|
it('should publish app with app variant patches applied', async () => {
|
|
499
510
|
vi.useRealTimers();
|
|
500
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write');
|
|
511
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
501
512
|
await publishApp({
|
|
502
513
|
path: resolveFixture('apps/test'),
|
|
503
514
|
organization: organization.id,
|
|
@@ -580,6 +591,7 @@ describe('publishApp', () => {
|
|
|
580
591
|
"showAppDefinition": true,
|
|
581
592
|
"showAppsembleLogin": false,
|
|
582
593
|
"showAppsembleOAuth2Login": true,
|
|
594
|
+
"template": false,
|
|
583
595
|
"visibility": "unlisted",
|
|
584
596
|
"yaml": "name: Test App
|
|
585
597
|
defaultPage: Test Page
|
|
@@ -633,6 +645,164 @@ describe('publishApp', () => {
|
|
|
633
645
|
await readFixture('apps/test/variants/tux/assets/small-tux.png'),
|
|
634
646
|
]);
|
|
635
647
|
});
|
|
648
|
+
it('should publish app variables and secrets', async () => {
|
|
649
|
+
vi.useRealTimers();
|
|
650
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
651
|
+
process.env.TEST_VARIABLE_1 = 'test-variable-1';
|
|
652
|
+
process.env.TEST_VARIABLE_2 = 'test-variable-2';
|
|
653
|
+
process.env.TEST_SECRET = 'test-secret';
|
|
654
|
+
process.env.TEST_SERVICE_URL_PATTERNS = 'http://localhost:1234';
|
|
655
|
+
process.env.TEST_SERVICE_IDENTIFIER = 'Authorization';
|
|
656
|
+
process.env.TEST_SERVICE_SECRET = 'secret';
|
|
657
|
+
process.env.TEST_SAML_IDP_CERTIFICATE = 'certificate';
|
|
658
|
+
process.env.TEST_SAML_ENTITY_ID = 'http://localhost:1234';
|
|
659
|
+
process.env.TEST_SAML_SSO_URL = 'http://localhost:1234';
|
|
660
|
+
process.env.TEST_OAUTH2_AUTHORIZATION_URL = 'http://localhost:1234';
|
|
661
|
+
process.env.TEST_OAUTH2_TOKEN_URL = 'http://localhost:1234';
|
|
662
|
+
process.env.TEST_OAUTH2_USER_INFO_URL = 'http://localhost:1234';
|
|
663
|
+
process.env.TEST_OAUTH2_CLIENT_ID = 'id';
|
|
664
|
+
process.env.TEST_OAUTH2_CLIENT_SECRET = 'secret';
|
|
665
|
+
process.env.TEST_SCIM_TOKEN = 'token';
|
|
666
|
+
process.env.TEST_SSL_KEY = 'key';
|
|
667
|
+
process.env.TEST_SSL_CERTIFICATE = 'certificate';
|
|
668
|
+
await publishApp({
|
|
669
|
+
path: resolveFixture('apps/test'),
|
|
670
|
+
organization: organization.id,
|
|
671
|
+
remote: testApp.defaults.baseURL,
|
|
672
|
+
clientCredentials,
|
|
673
|
+
visibility: 'unlisted',
|
|
674
|
+
iconBackground: '#ffffff',
|
|
675
|
+
});
|
|
676
|
+
vi.useFakeTimers();
|
|
677
|
+
const app = await App.findOne({
|
|
678
|
+
attributes: ['scimEnabled', 'scimToken', 'sslKey', 'sslCertificate'],
|
|
679
|
+
where: {
|
|
680
|
+
id: 1,
|
|
681
|
+
},
|
|
682
|
+
});
|
|
683
|
+
expect({
|
|
684
|
+
scimEnabled: app.scimEnabled,
|
|
685
|
+
scimToken: app.scimToken,
|
|
686
|
+
sslKey: app.sslKey,
|
|
687
|
+
sslCertificate: app.sslCertificate,
|
|
688
|
+
}).toStrictEqual({
|
|
689
|
+
scimEnabled: true,
|
|
690
|
+
scimToken: expect.any(Buffer),
|
|
691
|
+
sslKey: 'key',
|
|
692
|
+
sslCertificate: 'certificate',
|
|
693
|
+
});
|
|
694
|
+
const appVariables = await AppVariable.findAll({
|
|
695
|
+
attributes: ['name', 'value'],
|
|
696
|
+
where: {
|
|
697
|
+
AppId: 1,
|
|
698
|
+
},
|
|
699
|
+
});
|
|
700
|
+
expect(appVariables[0].toJSON()).toStrictEqual({
|
|
701
|
+
name: 'test-variable-inline',
|
|
702
|
+
value: 'inline',
|
|
703
|
+
});
|
|
704
|
+
expect(appVariables[1].toJSON()).toStrictEqual({
|
|
705
|
+
name: 'test-variable',
|
|
706
|
+
value: 'test-variable-1.test-variable-2',
|
|
707
|
+
});
|
|
708
|
+
const appServiceSecret = await AppServiceSecret.findOne({
|
|
709
|
+
attributes: ['name', 'authenticationMethod', 'urlPatterns', 'identifier', 'secret'],
|
|
710
|
+
where: {
|
|
711
|
+
AppId: 1,
|
|
712
|
+
},
|
|
713
|
+
});
|
|
714
|
+
expect(appServiceSecret.toJSON()).toStrictEqual({
|
|
715
|
+
name: 'test-service-secret',
|
|
716
|
+
authenticationMethod: 'custom-header',
|
|
717
|
+
urlPatterns: 'http://localhost:1234',
|
|
718
|
+
identifier: 'Authorization',
|
|
719
|
+
secret: expect.any(Buffer),
|
|
720
|
+
});
|
|
721
|
+
const appSamlSecret = await AppSamlSecret.findOne({
|
|
722
|
+
attributes: [
|
|
723
|
+
'name',
|
|
724
|
+
'icon',
|
|
725
|
+
'nameAttribute',
|
|
726
|
+
'emailAttribute',
|
|
727
|
+
'idpCertificate',
|
|
728
|
+
'entityId',
|
|
729
|
+
'ssoUrl',
|
|
730
|
+
],
|
|
731
|
+
where: {
|
|
732
|
+
AppId: 1,
|
|
733
|
+
},
|
|
734
|
+
});
|
|
735
|
+
expect(appSamlSecret.toJSON()).toStrictEqual({
|
|
736
|
+
emailAttribute: 'email',
|
|
737
|
+
entityId: 'http://localhost:1234',
|
|
738
|
+
icon: 'redhat',
|
|
739
|
+
id: 1,
|
|
740
|
+
idpCertificate: 'certificate',
|
|
741
|
+
name: 'test-saml-secret',
|
|
742
|
+
nameAttribute: 'name',
|
|
743
|
+
ssoUrl: 'http://localhost:1234',
|
|
744
|
+
spCertificate: expect.any(String),
|
|
745
|
+
});
|
|
746
|
+
const appOauth2Secret = await AppOAuth2Secret.findOne({
|
|
747
|
+
attributes: [
|
|
748
|
+
'name',
|
|
749
|
+
'icon',
|
|
750
|
+
'scope',
|
|
751
|
+
'remapper',
|
|
752
|
+
'authorizationUrl',
|
|
753
|
+
'tokenUrl',
|
|
754
|
+
'userInfoUrl',
|
|
755
|
+
'clientId',
|
|
756
|
+
'clientSecret',
|
|
757
|
+
],
|
|
758
|
+
where: {
|
|
759
|
+
AppId: 1,
|
|
760
|
+
},
|
|
761
|
+
});
|
|
762
|
+
expect({
|
|
763
|
+
authorizationUrl: appOauth2Secret.authorizationUrl,
|
|
764
|
+
clientId: appOauth2Secret.clientId,
|
|
765
|
+
clientSecret: appOauth2Secret.clientSecret,
|
|
766
|
+
icon: appOauth2Secret.icon,
|
|
767
|
+
name: appOauth2Secret.name,
|
|
768
|
+
remapper: appOauth2Secret.remapper,
|
|
769
|
+
scope: appOauth2Secret.scope,
|
|
770
|
+
tokenUrl: appOauth2Secret.tokenUrl,
|
|
771
|
+
userInfoUrl: appOauth2Secret.userInfoUrl,
|
|
772
|
+
}).toStrictEqual({
|
|
773
|
+
authorizationUrl: 'http://localhost:1234',
|
|
774
|
+
clientId: 'id',
|
|
775
|
+
clientSecret: 'secret',
|
|
776
|
+
icon: 'redhat',
|
|
777
|
+
name: 'test-oauth2-secret',
|
|
778
|
+
remapper: [{ prop: 'email' }],
|
|
779
|
+
scope: 'email openid profile',
|
|
780
|
+
tokenUrl: 'http://localhost:1234',
|
|
781
|
+
userInfoUrl: 'http://localhost:1234',
|
|
782
|
+
});
|
|
783
|
+
});
|
|
784
|
+
it('should validate and throw if there’s an error before publishing an app', async () => {
|
|
785
|
+
await BlockVersion.destroy({
|
|
786
|
+
where: {
|
|
787
|
+
version: '0.0.0',
|
|
788
|
+
OrganizationId: 'appsemble',
|
|
789
|
+
name: 'test',
|
|
790
|
+
},
|
|
791
|
+
});
|
|
792
|
+
vi.useRealTimers();
|
|
793
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
794
|
+
await expect(() => publishApp({
|
|
795
|
+
path: resolveFixture('apps/test'),
|
|
796
|
+
organization: organization.id,
|
|
797
|
+
remote: testApp.defaults.baseURL,
|
|
798
|
+
clientCredentials,
|
|
799
|
+
// Required defaults
|
|
800
|
+
visibility: 'unlisted',
|
|
801
|
+
iconBackground: '#ffffff',
|
|
802
|
+
})).rejects.toThrow('is not a known block type');
|
|
803
|
+
const app = await App.findOne();
|
|
804
|
+
expect(app).toBeNull();
|
|
805
|
+
});
|
|
636
806
|
});
|
|
637
807
|
describe('updateApp', () => {
|
|
638
808
|
let app;
|
|
@@ -648,7 +818,7 @@ describe('updateApp', () => {
|
|
|
648
818
|
});
|
|
649
819
|
it('should update app', async () => {
|
|
650
820
|
vi.useRealTimers();
|
|
651
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write');
|
|
821
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
652
822
|
await updateApp({
|
|
653
823
|
id: app.id,
|
|
654
824
|
path: resolveFixture('apps/test'),
|
|
@@ -734,6 +904,7 @@ describe('updateApp', () => {
|
|
|
734
904
|
"showAppDefinition": false,
|
|
735
905
|
"showAppsembleLogin": false,
|
|
736
906
|
"showAppsembleOAuth2Login": true,
|
|
907
|
+
"template": false,
|
|
737
908
|
"visibility": "unlisted",
|
|
738
909
|
"yaml": "name: Test App
|
|
739
910
|
defaultPage: Test Page
|
|
@@ -774,7 +945,7 @@ describe('updateApp', () => {
|
|
|
774
945
|
});
|
|
775
946
|
it('should update app with resources and assets', async () => {
|
|
776
947
|
vi.useRealTimers();
|
|
777
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write');
|
|
948
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
778
949
|
await updateApp({
|
|
779
950
|
id: app.id,
|
|
780
951
|
path: resolveFixture('apps/test'),
|
|
@@ -863,6 +1034,7 @@ describe('updateApp', () => {
|
|
|
863
1034
|
"showAppDefinition": false,
|
|
864
1035
|
"showAppsembleLogin": false,
|
|
865
1036
|
"showAppsembleOAuth2Login": true,
|
|
1037
|
+
"template": false,
|
|
866
1038
|
"visibility": "unlisted",
|
|
867
1039
|
"yaml": "name: Test App
|
|
868
1040
|
defaultPage: Test Page
|
|
@@ -929,7 +1101,7 @@ describe('updateApp', () => {
|
|
|
929
1101
|
visibility: 'public',
|
|
930
1102
|
});
|
|
931
1103
|
vi.useRealTimers();
|
|
932
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write');
|
|
1104
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
933
1105
|
await updateApp({
|
|
934
1106
|
path: resolveFixture('apps/test'),
|
|
935
1107
|
id: app.id,
|
|
@@ -1017,6 +1189,7 @@ describe('updateApp', () => {
|
|
|
1017
1189
|
"showAppDefinition": false,
|
|
1018
1190
|
"showAppsembleLogin": false,
|
|
1019
1191
|
"showAppsembleOAuth2Login": true,
|
|
1192
|
+
"template": true,
|
|
1020
1193
|
"visibility": "public",
|
|
1021
1194
|
"yaml": "name: Test App
|
|
1022
1195
|
defaultPage: Test Page
|
|
@@ -1089,7 +1262,7 @@ describe('updateApp', () => {
|
|
|
1089
1262
|
});
|
|
1090
1263
|
it('should update app with app variant patches applied', async () => {
|
|
1091
1264
|
vi.useRealTimers();
|
|
1092
|
-
const clientCredentials = await authorizeCLI('apps:write resources:write');
|
|
1265
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
1093
1266
|
await updateApp({
|
|
1094
1267
|
path: resolveFixture('apps/test'),
|
|
1095
1268
|
id: app.id,
|
|
@@ -1173,6 +1346,7 @@ describe('updateApp', () => {
|
|
|
1173
1346
|
"showAppDefinition": false,
|
|
1174
1347
|
"showAppsembleLogin": false,
|
|
1175
1348
|
"showAppsembleOAuth2Login": true,
|
|
1349
|
+
"template": false,
|
|
1176
1350
|
"visibility": "unlisted",
|
|
1177
1351
|
"yaml": "name: Test App
|
|
1178
1352
|
defaultPage: Test Page
|
|
@@ -1226,6 +1400,375 @@ describe('updateApp', () => {
|
|
|
1226
1400
|
await readFixture('apps/test/variants/tux/assets/small-tux.png'),
|
|
1227
1401
|
]);
|
|
1228
1402
|
});
|
|
1403
|
+
it('should update app variables and secrets', async () => {
|
|
1404
|
+
vi.useRealTimers();
|
|
1405
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
1406
|
+
process.env.TEST_VARIABLE_1 = 'test-variable-1';
|
|
1407
|
+
process.env.TEST_VARIABLE_2 = 'test-variable-2';
|
|
1408
|
+
process.env.TEST_SECRET = 'test-secret';
|
|
1409
|
+
process.env.TEST_SERVICE_URL_PATTERNS = 'http://localhost:1234';
|
|
1410
|
+
process.env.TEST_SERVICE_IDENTIFIER = 'Authorization';
|
|
1411
|
+
process.env.TEST_SERVICE_SECRET = 'secret';
|
|
1412
|
+
process.env.TEST_SAML_IDP_CERTIFICATE = 'certificate';
|
|
1413
|
+
process.env.TEST_SAML_ENTITY_ID = 'http://localhost:1234';
|
|
1414
|
+
process.env.TEST_SAML_SSO_URL = 'http://localhost:1234';
|
|
1415
|
+
process.env.TEST_OAUTH2_AUTHORIZATION_URL = 'http://localhost:1234';
|
|
1416
|
+
process.env.TEST_OAUTH2_TOKEN_URL = 'http://localhost:1234';
|
|
1417
|
+
process.env.TEST_OAUTH2_USER_INFO_URL = 'http://localhost:1234';
|
|
1418
|
+
process.env.TEST_OAUTH2_CLIENT_ID = 'id';
|
|
1419
|
+
process.env.TEST_OAUTH2_CLIENT_SECRET = 'secret';
|
|
1420
|
+
process.env.TEST_SCIM_TOKEN = 'token';
|
|
1421
|
+
process.env.TEST_SSL_KEY = 'key';
|
|
1422
|
+
process.env.TEST_SSL_CERTIFICATE = 'certificate';
|
|
1423
|
+
await updateApp({
|
|
1424
|
+
id: 1,
|
|
1425
|
+
path: resolveFixture('apps/test'),
|
|
1426
|
+
remote: testApp.defaults.baseURL,
|
|
1427
|
+
clientCredentials,
|
|
1428
|
+
visibility: 'unlisted',
|
|
1429
|
+
iconBackground: '#ffffff',
|
|
1430
|
+
force: true,
|
|
1431
|
+
});
|
|
1432
|
+
vi.useFakeTimers();
|
|
1433
|
+
const updatedApp = await App.findOne({
|
|
1434
|
+
attributes: ['scimEnabled', 'scimToken', 'sslKey', 'sslCertificate'],
|
|
1435
|
+
where: {
|
|
1436
|
+
id: 1,
|
|
1437
|
+
},
|
|
1438
|
+
});
|
|
1439
|
+
expect({
|
|
1440
|
+
scimEnabled: updatedApp.scimEnabled,
|
|
1441
|
+
scimToken: updatedApp.scimToken,
|
|
1442
|
+
sslKey: updatedApp.sslKey,
|
|
1443
|
+
sslCertificate: updatedApp.sslCertificate,
|
|
1444
|
+
}).toStrictEqual({
|
|
1445
|
+
scimEnabled: true,
|
|
1446
|
+
scimToken: expect.any(Buffer),
|
|
1447
|
+
sslKey: 'key',
|
|
1448
|
+
sslCertificate: 'certificate',
|
|
1449
|
+
});
|
|
1450
|
+
const appVariables = await AppVariable.findAll({
|
|
1451
|
+
attributes: ['name', 'value'],
|
|
1452
|
+
where: {
|
|
1453
|
+
AppId: 1,
|
|
1454
|
+
},
|
|
1455
|
+
});
|
|
1456
|
+
expect(appVariables[0].toJSON()).toStrictEqual({
|
|
1457
|
+
name: 'test-variable-inline',
|
|
1458
|
+
value: 'inline',
|
|
1459
|
+
});
|
|
1460
|
+
expect(appVariables[1].toJSON()).toStrictEqual({
|
|
1461
|
+
name: 'test-variable',
|
|
1462
|
+
value: 'test-variable-1.test-variable-2',
|
|
1463
|
+
});
|
|
1464
|
+
const appServiceSecret = await AppServiceSecret.findOne({
|
|
1465
|
+
attributes: ['name', 'authenticationMethod', 'urlPatterns', 'identifier', 'secret'],
|
|
1466
|
+
where: {
|
|
1467
|
+
AppId: 1,
|
|
1468
|
+
},
|
|
1469
|
+
});
|
|
1470
|
+
expect(appServiceSecret.toJSON()).toStrictEqual({
|
|
1471
|
+
name: 'test-service-secret',
|
|
1472
|
+
authenticationMethod: 'custom-header',
|
|
1473
|
+
urlPatterns: 'http://localhost:1234',
|
|
1474
|
+
identifier: 'Authorization',
|
|
1475
|
+
secret: expect.any(Buffer),
|
|
1476
|
+
});
|
|
1477
|
+
const appSamlSecret = await AppSamlSecret.findOne({
|
|
1478
|
+
attributes: [
|
|
1479
|
+
'name',
|
|
1480
|
+
'icon',
|
|
1481
|
+
'nameAttribute',
|
|
1482
|
+
'emailAttribute',
|
|
1483
|
+
'idpCertificate',
|
|
1484
|
+
'entityId',
|
|
1485
|
+
'ssoUrl',
|
|
1486
|
+
],
|
|
1487
|
+
where: {
|
|
1488
|
+
AppId: 1,
|
|
1489
|
+
},
|
|
1490
|
+
});
|
|
1491
|
+
expect(appSamlSecret.toJSON()).toStrictEqual({
|
|
1492
|
+
emailAttribute: 'email',
|
|
1493
|
+
entityId: 'http://localhost:1234',
|
|
1494
|
+
icon: 'redhat',
|
|
1495
|
+
id: 1,
|
|
1496
|
+
idpCertificate: 'certificate',
|
|
1497
|
+
name: 'test-saml-secret',
|
|
1498
|
+
nameAttribute: 'name',
|
|
1499
|
+
ssoUrl: 'http://localhost:1234',
|
|
1500
|
+
spCertificate: expect.any(String),
|
|
1501
|
+
});
|
|
1502
|
+
const appOauth2Secret = await AppOAuth2Secret.findOne({
|
|
1503
|
+
attributes: [
|
|
1504
|
+
'name',
|
|
1505
|
+
'icon',
|
|
1506
|
+
'scope',
|
|
1507
|
+
'remapper',
|
|
1508
|
+
'authorizationUrl',
|
|
1509
|
+
'tokenUrl',
|
|
1510
|
+
'userInfoUrl',
|
|
1511
|
+
'clientId',
|
|
1512
|
+
'clientSecret',
|
|
1513
|
+
],
|
|
1514
|
+
where: {
|
|
1515
|
+
AppId: 1,
|
|
1516
|
+
},
|
|
1517
|
+
});
|
|
1518
|
+
expect({
|
|
1519
|
+
authorizationUrl: appOauth2Secret.authorizationUrl,
|
|
1520
|
+
clientId: appOauth2Secret.clientId,
|
|
1521
|
+
clientSecret: appOauth2Secret.clientSecret,
|
|
1522
|
+
icon: appOauth2Secret.icon,
|
|
1523
|
+
name: appOauth2Secret.name,
|
|
1524
|
+
remapper: appOauth2Secret.remapper,
|
|
1525
|
+
scope: appOauth2Secret.scope,
|
|
1526
|
+
tokenUrl: appOauth2Secret.tokenUrl,
|
|
1527
|
+
userInfoUrl: appOauth2Secret.userInfoUrl,
|
|
1528
|
+
}).toStrictEqual({
|
|
1529
|
+
authorizationUrl: 'http://localhost:1234',
|
|
1530
|
+
clientId: 'id',
|
|
1531
|
+
clientSecret: 'secret',
|
|
1532
|
+
icon: 'redhat',
|
|
1533
|
+
name: 'test-oauth2-secret',
|
|
1534
|
+
remapper: [{ prop: 'email' }],
|
|
1535
|
+
scope: 'email openid profile',
|
|
1536
|
+
tokenUrl: 'http://localhost:1234',
|
|
1537
|
+
userInfoUrl: 'http://localhost:1234',
|
|
1538
|
+
});
|
|
1539
|
+
});
|
|
1540
|
+
it('should update an app with `app.locked` set to `fullLock` if force is specified', async () => {
|
|
1541
|
+
await app.update({ locked: 'fullLock' });
|
|
1542
|
+
const clientCredentials = await authorizeCLI('apps:write', testApp);
|
|
1543
|
+
await updateApp({
|
|
1544
|
+
path: resolveFixture('apps/test'),
|
|
1545
|
+
force: true,
|
|
1546
|
+
remote: testApp.defaults.baseURL,
|
|
1547
|
+
id: app.id,
|
|
1548
|
+
clientCredentials,
|
|
1549
|
+
visibility: 'public',
|
|
1550
|
+
iconBackground: '#fff999',
|
|
1551
|
+
});
|
|
1552
|
+
await app.reload();
|
|
1553
|
+
expect(app).toMatchInlineSnapshot(`
|
|
1554
|
+
{
|
|
1555
|
+
"$created": "1970-01-01T00:00:00.000Z",
|
|
1556
|
+
"$updated": "1970-01-01T00:00:00.000Z",
|
|
1557
|
+
"OrganizationId": "testorganization",
|
|
1558
|
+
"OrganizationName": undefined,
|
|
1559
|
+
"controllerCode": null,
|
|
1560
|
+
"controllerImplementations": null,
|
|
1561
|
+
"coreStyle": ".tux {
|
|
1562
|
+
color: rgb(0 0 0);
|
|
1563
|
+
}
|
|
1564
|
+
",
|
|
1565
|
+
"definition": {
|
|
1566
|
+
"defaultPage": "Test Page",
|
|
1567
|
+
"name": "Test App",
|
|
1568
|
+
"pages": [
|
|
1569
|
+
{
|
|
1570
|
+
"blocks": [
|
|
1571
|
+
{
|
|
1572
|
+
"type": "test",
|
|
1573
|
+
"version": "0.0.0",
|
|
1574
|
+
},
|
|
1575
|
+
],
|
|
1576
|
+
"name": "Test Page",
|
|
1577
|
+
},
|
|
1578
|
+
],
|
|
1579
|
+
"resources": {
|
|
1580
|
+
"test": {
|
|
1581
|
+
"schema": {
|
|
1582
|
+
"additionalProperties": false,
|
|
1583
|
+
"properties": {
|
|
1584
|
+
"test": {
|
|
1585
|
+
"format": "binary",
|
|
1586
|
+
"type": "string",
|
|
1587
|
+
},
|
|
1588
|
+
},
|
|
1589
|
+
"type": "object",
|
|
1590
|
+
},
|
|
1591
|
+
},
|
|
1592
|
+
},
|
|
1593
|
+
},
|
|
1594
|
+
"demoMode": false,
|
|
1595
|
+
"domain": null,
|
|
1596
|
+
"emailName": null,
|
|
1597
|
+
"enableSelfRegistration": true,
|
|
1598
|
+
"enableUnsecuredServiceSecrets": false,
|
|
1599
|
+
"googleAnalyticsID": null,
|
|
1600
|
+
"hasClonableAssets": undefined,
|
|
1601
|
+
"hasClonableResources": undefined,
|
|
1602
|
+
"hasIcon": true,
|
|
1603
|
+
"hasMaskableIcon": true,
|
|
1604
|
+
"iconBackground": "#fff999",
|
|
1605
|
+
"iconUrl": "/api/apps/1/icon?maskable=true&updated=1970-01-01T00%3A00%3A00.000Z",
|
|
1606
|
+
"id": 1,
|
|
1607
|
+
"locked": "fullLock",
|
|
1608
|
+
"messages": undefined,
|
|
1609
|
+
"path": "test-app",
|
|
1610
|
+
"rating": undefined,
|
|
1611
|
+
"readmeUrl": undefined,
|
|
1612
|
+
"screenshotUrls": undefined,
|
|
1613
|
+
"sentryDsn": null,
|
|
1614
|
+
"sentryEnvironment": null,
|
|
1615
|
+
"sharedStyle": ".tux {
|
|
1616
|
+
color: rgb(0 0 0);
|
|
1617
|
+
}
|
|
1618
|
+
",
|
|
1619
|
+
"showAppDefinition": false,
|
|
1620
|
+
"showAppsembleLogin": false,
|
|
1621
|
+
"showAppsembleOAuth2Login": true,
|
|
1622
|
+
"template": false,
|
|
1623
|
+
"visibility": "public",
|
|
1624
|
+
"yaml": "name: Test App
|
|
1625
|
+
defaultPage: Test Page
|
|
1626
|
+
resources:
|
|
1627
|
+
test:
|
|
1628
|
+
schema:
|
|
1629
|
+
additionalProperties: false
|
|
1630
|
+
type: object
|
|
1631
|
+
properties:
|
|
1632
|
+
test:
|
|
1633
|
+
type: string
|
|
1634
|
+
format: binary
|
|
1635
|
+
pages:
|
|
1636
|
+
- name: Test Page
|
|
1637
|
+
blocks:
|
|
1638
|
+
- type: test
|
|
1639
|
+
version: 0.0.0
|
|
1640
|
+
",
|
|
1641
|
+
}
|
|
1642
|
+
`);
|
|
1643
|
+
});
|
|
1644
|
+
it('should not update an app if the `app.locked` is set to `fullLock`', async () => {
|
|
1645
|
+
await app.update({ locked: 'fullLock' });
|
|
1646
|
+
const clientCredentials = await authorizeCLI('apps:write', testApp);
|
|
1647
|
+
await expect(updateApp({
|
|
1648
|
+
path: resolveFixture('apps/test'),
|
|
1649
|
+
force: false,
|
|
1650
|
+
remote: testApp.defaults.baseURL,
|
|
1651
|
+
id: app.id,
|
|
1652
|
+
clientCredentials,
|
|
1653
|
+
visibility: 'public',
|
|
1654
|
+
iconBackground: '#fff999',
|
|
1655
|
+
})).rejects.toThrow('Request failed with status code 403');
|
|
1656
|
+
await app.reload();
|
|
1657
|
+
expect(app).toMatchInlineSnapshot(`
|
|
1658
|
+
{
|
|
1659
|
+
"$created": "1970-01-01T00:00:00.000Z",
|
|
1660
|
+
"$updated": "1970-01-01T00:00:00.000Z",
|
|
1661
|
+
"OrganizationId": "testorganization",
|
|
1662
|
+
"OrganizationName": undefined,
|
|
1663
|
+
"controllerCode": null,
|
|
1664
|
+
"controllerImplementations": null,
|
|
1665
|
+
"coreStyle": undefined,
|
|
1666
|
+
"definition": {
|
|
1667
|
+
"defaultPage": "Test Page",
|
|
1668
|
+
"name": "Test App",
|
|
1669
|
+
},
|
|
1670
|
+
"demoMode": false,
|
|
1671
|
+
"domain": null,
|
|
1672
|
+
"emailName": null,
|
|
1673
|
+
"enableSelfRegistration": true,
|
|
1674
|
+
"enableUnsecuredServiceSecrets": false,
|
|
1675
|
+
"googleAnalyticsID": null,
|
|
1676
|
+
"hasClonableAssets": undefined,
|
|
1677
|
+
"hasClonableResources": undefined,
|
|
1678
|
+
"hasIcon": false,
|
|
1679
|
+
"hasMaskableIcon": false,
|
|
1680
|
+
"iconBackground": "#ffffff",
|
|
1681
|
+
"iconUrl": null,
|
|
1682
|
+
"id": 1,
|
|
1683
|
+
"locked": "fullLock",
|
|
1684
|
+
"messages": undefined,
|
|
1685
|
+
"path": "test-app",
|
|
1686
|
+
"rating": undefined,
|
|
1687
|
+
"readmeUrl": undefined,
|
|
1688
|
+
"screenshotUrls": undefined,
|
|
1689
|
+
"sentryDsn": null,
|
|
1690
|
+
"sentryEnvironment": null,
|
|
1691
|
+
"sharedStyle": undefined,
|
|
1692
|
+
"showAppDefinition": false,
|
|
1693
|
+
"showAppsembleLogin": false,
|
|
1694
|
+
"showAppsembleOAuth2Login": true,
|
|
1695
|
+
"template": false,
|
|
1696
|
+
"visibility": "public",
|
|
1697
|
+
"yaml": "name: Test App
|
|
1698
|
+
defaultPage: Test Page
|
|
1699
|
+
",
|
|
1700
|
+
}
|
|
1701
|
+
`);
|
|
1702
|
+
});
|
|
1703
|
+
it('should validate and throw if there’s an error before updating an app', async () => {
|
|
1704
|
+
await BlockVersion.destroy({
|
|
1705
|
+
where: {
|
|
1706
|
+
version: '0.0.0',
|
|
1707
|
+
OrganizationId: 'appsemble',
|
|
1708
|
+
name: 'test',
|
|
1709
|
+
},
|
|
1710
|
+
});
|
|
1711
|
+
vi.useRealTimers();
|
|
1712
|
+
const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
|
|
1713
|
+
await expect(updateApp({
|
|
1714
|
+
path: resolveFixture('apps/test'),
|
|
1715
|
+
id: app.id,
|
|
1716
|
+
force: false,
|
|
1717
|
+
remote: testApp.defaults.baseURL,
|
|
1718
|
+
clientCredentials,
|
|
1719
|
+
// Required defaults
|
|
1720
|
+
visibility: 'unlisted',
|
|
1721
|
+
iconBackground: '#ffffff',
|
|
1722
|
+
})).rejects.toThrow('is not a known block type');
|
|
1723
|
+
vi.useFakeTimers();
|
|
1724
|
+
await app.reload();
|
|
1725
|
+
expect(app.dataValues).toMatchInlineSnapshot(`
|
|
1726
|
+
{
|
|
1727
|
+
"OrganizationId": "testorganization",
|
|
1728
|
+
"controllerCode": null,
|
|
1729
|
+
"controllerImplementations": null,
|
|
1730
|
+
"coreStyle": null,
|
|
1731
|
+
"created": 1970-01-01T00:00:00.000Z,
|
|
1732
|
+
"definition": {
|
|
1733
|
+
"defaultPage": "Test Page",
|
|
1734
|
+
"name": "Test App",
|
|
1735
|
+
},
|
|
1736
|
+
"deleted": null,
|
|
1737
|
+
"demoMode": false,
|
|
1738
|
+
"domain": null,
|
|
1739
|
+
"emailHost": null,
|
|
1740
|
+
"emailName": null,
|
|
1741
|
+
"emailPassword": null,
|
|
1742
|
+
"emailPort": 587,
|
|
1743
|
+
"emailSecure": true,
|
|
1744
|
+
"emailUser": null,
|
|
1745
|
+
"enableSelfRegistration": true,
|
|
1746
|
+
"enableUnsecuredServiceSecrets": false,
|
|
1747
|
+
"googleAnalyticsID": null,
|
|
1748
|
+
"icon": null,
|
|
1749
|
+
"iconBackground": null,
|
|
1750
|
+
"id": 1,
|
|
1751
|
+
"locked": "unlocked",
|
|
1752
|
+
"maskableIcon": null,
|
|
1753
|
+
"path": "test-app",
|
|
1754
|
+
"scimEnabled": false,
|
|
1755
|
+
"scimToken": null,
|
|
1756
|
+
"sentryDsn": null,
|
|
1757
|
+
"sentryEnvironment": null,
|
|
1758
|
+
"sharedStyle": null,
|
|
1759
|
+
"showAppDefinition": false,
|
|
1760
|
+
"showAppsembleLogin": false,
|
|
1761
|
+
"showAppsembleOAuth2Login": true,
|
|
1762
|
+
"sslCertificate": null,
|
|
1763
|
+
"sslKey": null,
|
|
1764
|
+
"template": false,
|
|
1765
|
+
"updated": 1970-01-01T00:00:00.000Z,
|
|
1766
|
+
"vapidPrivateKey": "b",
|
|
1767
|
+
"vapidPublicKey": "a",
|
|
1768
|
+
"visibility": "public",
|
|
1769
|
+
}
|
|
1770
|
+
`);
|
|
1771
|
+
});
|
|
1229
1772
|
});
|
|
1230
1773
|
describe('patchApp', () => {
|
|
1231
1774
|
it('should apply patches to app', async () => {
|
|
@@ -1249,7 +1792,7 @@ describe('patchApp', () => {
|
|
|
1249
1792
|
visibility: 'public',
|
|
1250
1793
|
OrganizationId: organization.id,
|
|
1251
1794
|
}, { raw: true });
|
|
1252
|
-
await authorizeCLI('apps:write');
|
|
1795
|
+
await authorizeCLI('apps:write', testApp);
|
|
1253
1796
|
await patchApp({
|
|
1254
1797
|
...patches,
|
|
1255
1798
|
remote: testApp.defaults.baseURL,
|
|
@@ -1336,7 +1879,7 @@ describe('patchApp', () => {
|
|
|
1336
1879
|
OrganizationId: organization.id,
|
|
1337
1880
|
[key]: from,
|
|
1338
1881
|
}, { raw: true });
|
|
1339
|
-
await authorizeCLI('apps:write');
|
|
1882
|
+
await authorizeCLI('apps:write', testApp);
|
|
1340
1883
|
await patchApp({
|
|
1341
1884
|
[key]: to,
|
|
1342
1885
|
remote: testApp.defaults.baseURL,
|
|
@@ -1346,5 +1889,207 @@ describe('patchApp', () => {
|
|
|
1346
1889
|
await app.reload();
|
|
1347
1890
|
expect(app.dataValues[key]).toStrictEqual(to);
|
|
1348
1891
|
});
|
|
1892
|
+
it('should not apply a patch if the `app.locked` is set to `fullLock`', async () => {
|
|
1893
|
+
const app = await App.create({
|
|
1894
|
+
path: 'test-app',
|
|
1895
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
1896
|
+
vapidPublicKey: 'a',
|
|
1897
|
+
vapidPrivateKey: 'b',
|
|
1898
|
+
visibility: 'public',
|
|
1899
|
+
OrganizationId: organization.id,
|
|
1900
|
+
locked: 'fullLock',
|
|
1901
|
+
showAppDefinition: false,
|
|
1902
|
+
}, { raw: true });
|
|
1903
|
+
await authorizeCLI('apps:write', testApp);
|
|
1904
|
+
await patchApp({
|
|
1905
|
+
remote: testApp.defaults.baseURL,
|
|
1906
|
+
id: app.id,
|
|
1907
|
+
showAppDefinition: true,
|
|
1908
|
+
});
|
|
1909
|
+
expect(app.dataValues.showAppDefinition).toBe(false);
|
|
1910
|
+
await app.reload();
|
|
1911
|
+
expect(app.dataValues.showAppDefinition).toBe(false);
|
|
1912
|
+
});
|
|
1913
|
+
it('should apply a patch if the `app.locked` is set to `fullLock` and `force` is specified', async () => {
|
|
1914
|
+
const app = await App.create({
|
|
1915
|
+
path: 'test-app',
|
|
1916
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
1917
|
+
vapidPublicKey: 'a',
|
|
1918
|
+
vapidPrivateKey: 'b',
|
|
1919
|
+
visibility: 'public',
|
|
1920
|
+
OrganizationId: organization.id,
|
|
1921
|
+
locked: 'fullLock',
|
|
1922
|
+
showAppDefinition: false,
|
|
1923
|
+
}, { raw: true });
|
|
1924
|
+
await authorizeCLI('apps:write', testApp);
|
|
1925
|
+
await patchApp({
|
|
1926
|
+
remote: testApp.defaults.baseURL,
|
|
1927
|
+
id: app.id,
|
|
1928
|
+
showAppDefinition: true,
|
|
1929
|
+
force: true,
|
|
1930
|
+
});
|
|
1931
|
+
expect(app.dataValues.showAppDefinition).toBe(false);
|
|
1932
|
+
await app.reload();
|
|
1933
|
+
expect(app.dataValues.showAppDefinition).toBe(true);
|
|
1934
|
+
});
|
|
1935
|
+
});
|
|
1936
|
+
describe('traverseAppDirectory', () => {
|
|
1937
|
+
it('should read the app definition and appsembleRC from the directory', async () => {
|
|
1938
|
+
const formData = new FormData();
|
|
1939
|
+
const [appsembleContext, appsembleRC, yaml, app] = await traverseAppDirectory(resolveFixture('apps/test'), 'test', formData);
|
|
1940
|
+
expect(appsembleContext).toMatchInlineSnapshot({
|
|
1941
|
+
icon: expect.any(String),
|
|
1942
|
+
maskableIcon: expect.any(String),
|
|
1943
|
+
}, `
|
|
1944
|
+
{
|
|
1945
|
+
"appLock": "studioLock",
|
|
1946
|
+
"assets": true,
|
|
1947
|
+
"assetsClonable": true,
|
|
1948
|
+
"collections": [
|
|
1949
|
+
1,
|
|
1950
|
+
],
|
|
1951
|
+
"demoMode": true,
|
|
1952
|
+
"googleAnalyticsId": "test",
|
|
1953
|
+
"icon": Any<String>,
|
|
1954
|
+
"iconBackground": "#000000",
|
|
1955
|
+
"id": 1,
|
|
1956
|
+
"maskableIcon": Any<String>,
|
|
1957
|
+
"organization": "testorganization",
|
|
1958
|
+
"resources": true,
|
|
1959
|
+
"sentryDsn": "https://public@sentry.example.com/1",
|
|
1960
|
+
"sentryEnvironment": "test",
|
|
1961
|
+
"showAppDefinition": true,
|
|
1962
|
+
"template": true,
|
|
1963
|
+
"visibility": "public",
|
|
1964
|
+
}
|
|
1965
|
+
`);
|
|
1966
|
+
expect(appsembleRC).toMatchInlineSnapshot({
|
|
1967
|
+
context: {
|
|
1968
|
+
test: {
|
|
1969
|
+
icon: expect.any(String),
|
|
1970
|
+
maskableIcon: expect.any(String),
|
|
1971
|
+
},
|
|
1972
|
+
},
|
|
1973
|
+
}, `
|
|
1974
|
+
{
|
|
1975
|
+
"context": {
|
|
1976
|
+
"test": {
|
|
1977
|
+
"appLock": "studioLock",
|
|
1978
|
+
"assets": true,
|
|
1979
|
+
"assetsClonable": true,
|
|
1980
|
+
"collections": [
|
|
1981
|
+
1,
|
|
1982
|
+
],
|
|
1983
|
+
"demoMode": true,
|
|
1984
|
+
"googleAnalyticsId": "test",
|
|
1985
|
+
"icon": Any<String>,
|
|
1986
|
+
"iconBackground": "#000000",
|
|
1987
|
+
"id": 1,
|
|
1988
|
+
"maskableIcon": Any<String>,
|
|
1989
|
+
"organization": "testorganization",
|
|
1990
|
+
"resources": true,
|
|
1991
|
+
"sentryDsn": "https://public@sentry.example.com/1",
|
|
1992
|
+
"sentryEnvironment": "test",
|
|
1993
|
+
"showAppDefinition": true,
|
|
1994
|
+
"template": true,
|
|
1995
|
+
"visibility": "public",
|
|
1996
|
+
},
|
|
1997
|
+
},
|
|
1998
|
+
}
|
|
1999
|
+
`);
|
|
2000
|
+
expect(yaml).toMatchInlineSnapshot(`
|
|
2001
|
+
"name: Test App
|
|
2002
|
+
defaultPage: Test Page
|
|
2003
|
+
|
|
2004
|
+
resources:
|
|
2005
|
+
test:
|
|
2006
|
+
schema:
|
|
2007
|
+
additionalProperties: false
|
|
2008
|
+
type: object
|
|
2009
|
+
properties:
|
|
2010
|
+
test:
|
|
2011
|
+
type: string
|
|
2012
|
+
format: binary
|
|
2013
|
+
|
|
2014
|
+
pages:
|
|
2015
|
+
- name: Test Page
|
|
2016
|
+
blocks:
|
|
2017
|
+
- type: test
|
|
2018
|
+
version: 0.0.0
|
|
2019
|
+
"
|
|
2020
|
+
`);
|
|
2021
|
+
expect(app).toMatchInlineSnapshot({
|
|
2022
|
+
iconUrl: expect.any(String),
|
|
2023
|
+
}, `
|
|
2024
|
+
{
|
|
2025
|
+
"coreStyle": ".tux {
|
|
2026
|
+
color: rgb(0 0 0);
|
|
2027
|
+
}
|
|
2028
|
+
",
|
|
2029
|
+
"definition": {
|
|
2030
|
+
"defaultPage": "Test Page",
|
|
2031
|
+
"name": "Test App",
|
|
2032
|
+
"pages": [
|
|
2033
|
+
{
|
|
2034
|
+
"blocks": [
|
|
2035
|
+
{
|
|
2036
|
+
"type": "test",
|
|
2037
|
+
"version": "0.0.0",
|
|
2038
|
+
},
|
|
2039
|
+
],
|
|
2040
|
+
"name": "Test Page",
|
|
2041
|
+
},
|
|
2042
|
+
],
|
|
2043
|
+
"resources": {
|
|
2044
|
+
"test": {
|
|
2045
|
+
"schema": {
|
|
2046
|
+
"additionalProperties": false,
|
|
2047
|
+
"properties": {
|
|
2048
|
+
"test": {
|
|
2049
|
+
"format": "binary",
|
|
2050
|
+
"type": "string",
|
|
2051
|
+
},
|
|
2052
|
+
},
|
|
2053
|
+
"type": "object",
|
|
2054
|
+
},
|
|
2055
|
+
},
|
|
2056
|
+
},
|
|
2057
|
+
},
|
|
2058
|
+
"iconUrl": Any<String>,
|
|
2059
|
+
"readmeUrl": "README.md",
|
|
2060
|
+
"screenshotUrls": [
|
|
2061
|
+
"test_en-us.png",
|
|
2062
|
+
],
|
|
2063
|
+
"sharedStyle": ".tux {
|
|
2064
|
+
color: rgb(0 0 0);
|
|
2065
|
+
}
|
|
2066
|
+
",
|
|
2067
|
+
}
|
|
2068
|
+
`);
|
|
2069
|
+
});
|
|
2070
|
+
it('should return an error if no app-definition is found in the given directory', async () => {
|
|
2071
|
+
const formData = new FormData();
|
|
2072
|
+
await expect(() => traverseAppDirectory(resolveFixture('apps/empty'), null, formData)).rejects.toThrow('No app definition found');
|
|
2073
|
+
});
|
|
2074
|
+
});
|
|
2075
|
+
describe('deleteApp', () => {
|
|
2076
|
+
it('should throw if an error occurs', async () => {
|
|
2077
|
+
const clientCredentials = await authorizeCLI('apps:delete', testApp);
|
|
2078
|
+
await expect(() => deleteApp({ id: 1, remote: testApp.defaults.baseURL, clientCredentials })).rejects.toThrow('Request failed with status code 404');
|
|
2079
|
+
});
|
|
2080
|
+
it('should delete an app', async () => {
|
|
2081
|
+
const app = await App.create({
|
|
2082
|
+
path: 'test-app',
|
|
2083
|
+
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
2084
|
+
vapidPublicKey: 'a',
|
|
2085
|
+
vapidPrivateKey: 'b',
|
|
2086
|
+
visibility: 'public',
|
|
2087
|
+
OrganizationId: organization.id,
|
|
2088
|
+
});
|
|
2089
|
+
const clientCredentials = await authorizeCLI('apps:delete', testApp);
|
|
2090
|
+
await deleteApp({ id: app.id, remote: testApp.defaults.baseURL, clientCredentials });
|
|
2091
|
+
const foundApps = await App.findAll();
|
|
2092
|
+
expect(foundApps).toStrictEqual([]);
|
|
2093
|
+
});
|
|
1349
2094
|
});
|
|
1350
2095
|
//# sourceMappingURL=app.test.js.map
|