@appsemble/cli 0.27.12 → 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/lib/app.test.js CHANGED
@@ -1,23 +1,17 @@
1
- import { authenticate, readFixture, resolveFixture } from '@appsemble/node-utils';
2
- import { authorizeClientCredentials, createServer, createTestUser, models, setArgv, useTestDatabase, } from '@appsemble/server';
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 { hash } from 'bcrypt';
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
+ import { authorizeCLI } from './testUtils.js';
9
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
@@ -635,7 +647,7 @@ describe('publishApp', () => {
635
647
  });
636
648
  it('should publish app variables and secrets', async () => {
637
649
  vi.useRealTimers();
638
- const clientCredentials = await authorizeCLI('apps:write resources:write');
650
+ const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
639
651
  process.env.TEST_VARIABLE_1 = 'test-variable-1';
640
652
  process.env.TEST_VARIABLE_2 = 'test-variable-2';
641
653
  process.env.TEST_SECRET = 'test-secret';
@@ -769,6 +781,28 @@ describe('publishApp', () => {
769
781
  userInfoUrl: 'http://localhost:1234',
770
782
  });
771
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
+ });
772
806
  });
773
807
  describe('updateApp', () => {
774
808
  let app;
@@ -784,7 +818,7 @@ describe('updateApp', () => {
784
818
  });
785
819
  it('should update app', async () => {
786
820
  vi.useRealTimers();
787
- const clientCredentials = await authorizeCLI('apps:write resources:write');
821
+ const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
788
822
  await updateApp({
789
823
  id: app.id,
790
824
  path: resolveFixture('apps/test'),
@@ -870,6 +904,7 @@ describe('updateApp', () => {
870
904
  "showAppDefinition": false,
871
905
  "showAppsembleLogin": false,
872
906
  "showAppsembleOAuth2Login": true,
907
+ "template": false,
873
908
  "visibility": "unlisted",
874
909
  "yaml": "name: Test App
875
910
  defaultPage: Test Page
@@ -910,7 +945,7 @@ describe('updateApp', () => {
910
945
  });
911
946
  it('should update app with resources and assets', async () => {
912
947
  vi.useRealTimers();
913
- const clientCredentials = await authorizeCLI('apps:write resources:write');
948
+ const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
914
949
  await updateApp({
915
950
  id: app.id,
916
951
  path: resolveFixture('apps/test'),
@@ -999,6 +1034,7 @@ describe('updateApp', () => {
999
1034
  "showAppDefinition": false,
1000
1035
  "showAppsembleLogin": false,
1001
1036
  "showAppsembleOAuth2Login": true,
1037
+ "template": false,
1002
1038
  "visibility": "unlisted",
1003
1039
  "yaml": "name: Test App
1004
1040
  defaultPage: Test Page
@@ -1065,7 +1101,7 @@ describe('updateApp', () => {
1065
1101
  visibility: 'public',
1066
1102
  });
1067
1103
  vi.useRealTimers();
1068
- const clientCredentials = await authorizeCLI('apps:write resources:write');
1104
+ const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
1069
1105
  await updateApp({
1070
1106
  path: resolveFixture('apps/test'),
1071
1107
  id: app.id,
@@ -1153,6 +1189,7 @@ describe('updateApp', () => {
1153
1189
  "showAppDefinition": false,
1154
1190
  "showAppsembleLogin": false,
1155
1191
  "showAppsembleOAuth2Login": true,
1192
+ "template": true,
1156
1193
  "visibility": "public",
1157
1194
  "yaml": "name: Test App
1158
1195
  defaultPage: Test Page
@@ -1225,7 +1262,7 @@ describe('updateApp', () => {
1225
1262
  });
1226
1263
  it('should update app with app variant patches applied', async () => {
1227
1264
  vi.useRealTimers();
1228
- const clientCredentials = await authorizeCLI('apps:write resources:write');
1265
+ const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
1229
1266
  await updateApp({
1230
1267
  path: resolveFixture('apps/test'),
1231
1268
  id: app.id,
@@ -1309,6 +1346,7 @@ describe('updateApp', () => {
1309
1346
  "showAppDefinition": false,
1310
1347
  "showAppsembleLogin": false,
1311
1348
  "showAppsembleOAuth2Login": true,
1349
+ "template": false,
1312
1350
  "visibility": "unlisted",
1313
1351
  "yaml": "name: Test App
1314
1352
  defaultPage: Test Page
@@ -1364,7 +1402,7 @@ describe('updateApp', () => {
1364
1402
  });
1365
1403
  it('should update app variables and secrets', async () => {
1366
1404
  vi.useRealTimers();
1367
- const clientCredentials = await authorizeCLI('apps:write resources:write');
1405
+ const clientCredentials = await authorizeCLI('apps:write resources:write', testApp);
1368
1406
  process.env.TEST_VARIABLE_1 = 'test-variable-1';
1369
1407
  process.env.TEST_VARIABLE_2 = 'test-variable-2';
1370
1408
  process.env.TEST_SECRET = 'test-secret';
@@ -1499,6 +1537,238 @@ describe('updateApp', () => {
1499
1537
  userInfoUrl: 'http://localhost:1234',
1500
1538
  });
1501
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
+ });
1502
1772
  });
1503
1773
  describe('patchApp', () => {
1504
1774
  it('should apply patches to app', async () => {
@@ -1522,7 +1792,7 @@ describe('patchApp', () => {
1522
1792
  visibility: 'public',
1523
1793
  OrganizationId: organization.id,
1524
1794
  }, { raw: true });
1525
- await authorizeCLI('apps:write');
1795
+ await authorizeCLI('apps:write', testApp);
1526
1796
  await patchApp({
1527
1797
  ...patches,
1528
1798
  remote: testApp.defaults.baseURL,
@@ -1609,7 +1879,7 @@ describe('patchApp', () => {
1609
1879
  OrganizationId: organization.id,
1610
1880
  [key]: from,
1611
1881
  }, { raw: true });
1612
- await authorizeCLI('apps:write');
1882
+ await authorizeCLI('apps:write', testApp);
1613
1883
  await patchApp({
1614
1884
  [key]: to,
1615
1885
  remote: testApp.defaults.baseURL,
@@ -1619,5 +1889,207 @@ describe('patchApp', () => {
1619
1889
  await app.reload();
1620
1890
  expect(app.dataValues[key]).toStrictEqual(to);
1621
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
+ });
1622
2094
  });
1623
2095
  //# sourceMappingURL=app.test.js.map
@@ -0,0 +1 @@
1
+ export {};