@appsemble/cli 0.30.14-test.6 → 0.32.1-test.14
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/create.js +9 -4
- package/commands/app/delete.js +1 -1
- package/commands/app/export.js +1 -1
- package/commands/app/patch.d.ts +2 -0
- package/commands/app/patch.js +8 -0
- package/commands/app/update.js +1 -1
- package/commands/asset/publish.js +1 -1
- package/commands/cleanupSoftDeletedRecords.d.ts +6 -0
- package/commands/cleanupSoftDeletedRecords.js +40 -0
- package/commands/config/get.js +6 -2
- package/commands/config/set.js +6 -1
- package/commands/migrate.js +19 -0
- package/commands/serve.js +5 -1
- package/commands/start.js +19 -0
- package/commands/synchronizeTrainings.d.ts +6 -0
- package/commands/synchronizeTrainings.js +40 -0
- package/index.js +5 -0
- package/lib/app.d.ts +8 -0
- package/lib/app.js +59 -17
- package/lib/asset.d.ts +1 -1
- package/lib/authentication.js +4 -4
- package/lib/block.js +15 -6
- package/lib/coercers.js +1 -0
- package/lib/config.js +26 -18
- package/lib/createServers.js +3 -1
- package/lib/group.d.ts +1 -1
- package/lib/group.js +7 -6
- package/lib/output.js +3 -1
- package/lib/processCss.js +1 -1
- package/lib/project.js +3 -2
- package/lib/serverImport.d.ts +1 -1
- package/lib/serverImport.js +1 -1
- package/package.json +19 -16
- package/server/db/methods.js +3 -0
- package/server/options/createAppAsset.d.ts +1 -1
- package/server/options/createAppAsset.js +5 -6
- package/server/options/createAppResourcesWithAssets.js +4 -6
- package/server/options/createSettings.js +1 -1
- package/server/options/createTheme.js +2 -0
- package/server/options/getAppAsset.js +5 -10
- package/server/options/getAppAssets.js +5 -9
- package/server/options/getAppScreenshots.js +3 -3
- package/server/options/getBlockAsset.js +3 -0
- package/server/options/getTheme.js +1 -0
- package/server/options/options.js +2 -0
- package/templates/apps/empty/app-definition.yaml +2 -2
- package/templates/blocks/mini-jsx/package.json +4 -1
- package/templates/blocks/mini-jsx/src/index.tsx +1 -1
- package/templates/blocks/preact/package.json +5 -2
- package/templates/blocks/vanilla/package.json +4 -1
- package/vitest.setup.js +11 -2
- package/lib/app.test.d.ts +0 -1
- package/lib/app.test.js +0 -2212
- package/lib/asset.test.d.ts +0 -1
- package/lib/asset.test.js +0 -105
- package/lib/block.test.d.ts +0 -1
- package/lib/block.test.js +0 -235
- package/lib/coercers.test.d.ts +0 -1
- package/lib/coercers.test.js +0 -27
- package/lib/config.test.d.ts +0 -1
- package/lib/config.test.js +0 -239
- package/lib/group.test.d.ts +0 -1
- package/lib/group.test.js +0 -616
- package/lib/organization.test.d.ts +0 -1
- package/lib/organization.test.js +0 -222
- package/lib/resource.test.d.ts +0 -1
- package/lib/resource.test.js +0 -393
- package/server/db/methods.test.d.ts +0 -1
- package/server/db/methods.test.js +0 -366
- package/server/options/parseQuery.test.d.ts +0 -1
- package/server/options/parseQuery.test.js +0 -46
package/lib/asset.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/lib/asset.test.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { resolveFixture } from '@appsemble/node-utils';
|
|
2
|
-
import { createServer, createTestUser, models, setArgv } from '@appsemble/server';
|
|
3
|
-
import { PredefinedOrganizationRole } from '@appsemble/types';
|
|
4
|
-
import { setTestApp } from 'axios-test-instance';
|
|
5
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
-
import { publishAsset } from './asset.js';
|
|
7
|
-
import { initAxios } from './initAxios.js';
|
|
8
|
-
import { authorizeCLI } from './testUtils.js';
|
|
9
|
-
const argv = { host: 'http://localhost', secret: 'test', aesSecret: 'testSecret' };
|
|
10
|
-
let user;
|
|
11
|
-
let organization;
|
|
12
|
-
let testApp;
|
|
13
|
-
const { App, Asset, Organization, OrganizationMember } = models;
|
|
14
|
-
describe('asset', () => {
|
|
15
|
-
beforeAll(() => {
|
|
16
|
-
vi.useFakeTimers();
|
|
17
|
-
setArgv(argv);
|
|
18
|
-
});
|
|
19
|
-
beforeEach(async () => {
|
|
20
|
-
vi.clearAllTimers();
|
|
21
|
-
vi.setSystemTime(0);
|
|
22
|
-
const server = await createServer();
|
|
23
|
-
testApp = await setTestApp(server);
|
|
24
|
-
initAxios({ remote: testApp.defaults.baseURL });
|
|
25
|
-
user = await createTestUser();
|
|
26
|
-
organization = await Organization.create({
|
|
27
|
-
id: 'testorganization',
|
|
28
|
-
name: 'Test Organization',
|
|
29
|
-
});
|
|
30
|
-
await OrganizationMember.create({
|
|
31
|
-
OrganizationId: organization.id,
|
|
32
|
-
UserId: user.id,
|
|
33
|
-
role: PredefinedOrganizationRole.Owner,
|
|
34
|
-
});
|
|
35
|
-
await Organization.create({ id: 'appsemble', name: 'Appsemble' });
|
|
36
|
-
});
|
|
37
|
-
afterAll(() => {
|
|
38
|
-
vi.useRealTimers();
|
|
39
|
-
});
|
|
40
|
-
describe('publishAsset', () => {
|
|
41
|
-
it('should publish an asset from a file', async () => {
|
|
42
|
-
const app = await App.create({
|
|
43
|
-
path: 'test-app',
|
|
44
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
45
|
-
vapidPublicKey: 'a',
|
|
46
|
-
vapidPrivateKey: 'b',
|
|
47
|
-
visibility: 'public',
|
|
48
|
-
OrganizationId: organization.id,
|
|
49
|
-
});
|
|
50
|
-
await authorizeCLI('assets:write', testApp);
|
|
51
|
-
await publishAsset({
|
|
52
|
-
appId: app.id,
|
|
53
|
-
clonable: false,
|
|
54
|
-
name: 'test',
|
|
55
|
-
path: resolveFixture('apps/tux.png'),
|
|
56
|
-
remote: testApp.defaults.baseURL,
|
|
57
|
-
seed: false,
|
|
58
|
-
});
|
|
59
|
-
const asset = await Asset.findOne();
|
|
60
|
-
expect(asset.dataValues).toMatchInlineSnapshot({
|
|
61
|
-
id: expect.any(String),
|
|
62
|
-
data: expect.any(Buffer),
|
|
63
|
-
}, `
|
|
64
|
-
{
|
|
65
|
-
"AppId": 1,
|
|
66
|
-
"AppMemberId": null,
|
|
67
|
-
"GroupId": null,
|
|
68
|
-
"OriginalId": null,
|
|
69
|
-
"ResourceId": null,
|
|
70
|
-
"clonable": false,
|
|
71
|
-
"created": 1970-01-01T00:00:00.000Z,
|
|
72
|
-
"data": Any<Buffer>,
|
|
73
|
-
"ephemeral": false,
|
|
74
|
-
"filename": "tux.png",
|
|
75
|
-
"id": Any<String>,
|
|
76
|
-
"mime": "image/png",
|
|
77
|
-
"name": "test",
|
|
78
|
-
"seed": false,
|
|
79
|
-
"updated": 1970-01-01T00:00:00.000Z,
|
|
80
|
-
}
|
|
81
|
-
`);
|
|
82
|
-
});
|
|
83
|
-
it('should throw an error if the app does not exist', async () => {
|
|
84
|
-
const app = await App.create({
|
|
85
|
-
path: 'test-app',
|
|
86
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
87
|
-
vapidPublicKey: 'a',
|
|
88
|
-
vapidPrivateKey: 'b',
|
|
89
|
-
visibility: 'public',
|
|
90
|
-
OrganizationId: organization.id,
|
|
91
|
-
});
|
|
92
|
-
await app.destroy();
|
|
93
|
-
await authorizeCLI('assets:write', testApp);
|
|
94
|
-
await expect(() => publishAsset({
|
|
95
|
-
appId: app.id,
|
|
96
|
-
clonable: false,
|
|
97
|
-
name: 'test',
|
|
98
|
-
path: resolveFixture('apps/tux.png'),
|
|
99
|
-
remote: testApp.defaults.baseURL,
|
|
100
|
-
seed: false,
|
|
101
|
-
})).rejects.toThrow('Request failed with status code 404');
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
//# sourceMappingURL=asset.test.js.map
|
package/lib/block.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/lib/block.test.js
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { resolveFixture } from '@appsemble/node-utils';
|
|
2
|
-
import { createServer, createTestUser, models, setArgv } from '@appsemble/server';
|
|
3
|
-
import { PredefinedOrganizationRole } from '@appsemble/types';
|
|
4
|
-
import { setTestApp } from 'axios-test-instance';
|
|
5
|
-
import concat from 'concat-stream';
|
|
6
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
-
import { deleteBlock, traverseBlockThemes } from './block.js';
|
|
8
|
-
import { initAxios } from './initAxios.js';
|
|
9
|
-
import { makeProjectPayload } from './project.js';
|
|
10
|
-
import { authorizeCLI } from './testUtils.js';
|
|
11
|
-
const argv = { host: 'http://localhost', secret: 'test', aesSecret: 'testSecret' };
|
|
12
|
-
let testApp;
|
|
13
|
-
let user;
|
|
14
|
-
let organization;
|
|
15
|
-
const { App, AppBlockStyle, BlockVersion, Organization, OrganizationMember, Theme } = models;
|
|
16
|
-
describe('block', () => {
|
|
17
|
-
beforeAll(() => {
|
|
18
|
-
vi.useFakeTimers();
|
|
19
|
-
setArgv(argv);
|
|
20
|
-
});
|
|
21
|
-
beforeEach(async () => {
|
|
22
|
-
vi.clearAllTimers();
|
|
23
|
-
vi.setSystemTime(0);
|
|
24
|
-
const server = await createServer();
|
|
25
|
-
testApp = await setTestApp(server);
|
|
26
|
-
initAxios({ remote: testApp.defaults.baseURL });
|
|
27
|
-
user = await createTestUser();
|
|
28
|
-
organization = await Organization.create({
|
|
29
|
-
id: 'testorganization',
|
|
30
|
-
name: 'Test Organization',
|
|
31
|
-
});
|
|
32
|
-
await OrganizationMember.create({
|
|
33
|
-
OrganizationId: organization.id,
|
|
34
|
-
UserId: user.id,
|
|
35
|
-
role: PredefinedOrganizationRole.Owner,
|
|
36
|
-
});
|
|
37
|
-
await Organization.create({ id: 'appsemble', name: 'Appsemble' });
|
|
38
|
-
});
|
|
39
|
-
afterAll(() => {
|
|
40
|
-
vi.useRealTimers();
|
|
41
|
-
});
|
|
42
|
-
describe('makeProjectPayload', () => {
|
|
43
|
-
it('should create a form-data payload', async () => {
|
|
44
|
-
const payload = await makeProjectPayload({
|
|
45
|
-
webpack: 'webpack.config',
|
|
46
|
-
name: '@org/block',
|
|
47
|
-
output: 'output',
|
|
48
|
-
version: '1.2.3',
|
|
49
|
-
dir: resolveFixture('makeProjectPayload/no-icon'),
|
|
50
|
-
});
|
|
51
|
-
const [formData] = payload;
|
|
52
|
-
const boundary = formData.getBoundary();
|
|
53
|
-
const buffer = await new Promise((resolve) => {
|
|
54
|
-
formData.pipe(concat(resolve));
|
|
55
|
-
});
|
|
56
|
-
expect(String(buffer)).toBe(`--${boundary}\r
|
|
57
|
-
Content-Disposition: form-data; name="actions"\r
|
|
58
|
-
\r
|
|
59
|
-
{"onClick":{}}\r
|
|
60
|
-
--${boundary}\r
|
|
61
|
-
Content-Disposition: form-data; name="events"\r
|
|
62
|
-
\r
|
|
63
|
-
{"listen":{"test":{}}}\r
|
|
64
|
-
--${boundary}\r
|
|
65
|
-
Content-Disposition: form-data; name="name"\r
|
|
66
|
-
\r
|
|
67
|
-
@org/block\r
|
|
68
|
-
--${boundary}\r
|
|
69
|
-
Content-Disposition: form-data; name="parameters"\r
|
|
70
|
-
\r
|
|
71
|
-
{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"type":{"type":"object"}},"required":["type"],"additionalProperties":false}\r
|
|
72
|
-
--${boundary}\r
|
|
73
|
-
Content-Disposition: form-data; name="version"\r
|
|
74
|
-
\r
|
|
75
|
-
1.2.3\r
|
|
76
|
-
--${boundary}\r
|
|
77
|
-
Content-Disposition: form-data; name="files"; filename="block.js"\r
|
|
78
|
-
Content-Type: application/javascript\r
|
|
79
|
-
\r
|
|
80
|
-
export const string = 'no-icon';
|
|
81
|
-
\r
|
|
82
|
-
--${boundary}--\r
|
|
83
|
-
`);
|
|
84
|
-
});
|
|
85
|
-
it('should include an icon if one is present', async () => {
|
|
86
|
-
const payload = await makeProjectPayload({
|
|
87
|
-
webpack: 'webpack.config',
|
|
88
|
-
name: '@org/block',
|
|
89
|
-
output: 'output',
|
|
90
|
-
version: '1.2.3',
|
|
91
|
-
dir: resolveFixture('makeProjectPayload/with-icon'),
|
|
92
|
-
});
|
|
93
|
-
const [formData] = payload;
|
|
94
|
-
const boundary = formData.getBoundary();
|
|
95
|
-
const buffer = await new Promise((resolve) => {
|
|
96
|
-
formData.pipe(concat(resolve));
|
|
97
|
-
});
|
|
98
|
-
expect(String(buffer)).toBe(`--${boundary}\r
|
|
99
|
-
Content-Disposition: form-data; name="actions"\r
|
|
100
|
-
\r
|
|
101
|
-
{"onClick":{}}\r
|
|
102
|
-
--${boundary}\r
|
|
103
|
-
Content-Disposition: form-data; name="events"\r
|
|
104
|
-
\r
|
|
105
|
-
{"listen":{"test":{}}}\r
|
|
106
|
-
--${boundary}\r
|
|
107
|
-
Content-Disposition: form-data; name="name"\r
|
|
108
|
-
\r
|
|
109
|
-
@org/block\r
|
|
110
|
-
--${boundary}\r
|
|
111
|
-
Content-Disposition: form-data; name="parameters"\r
|
|
112
|
-
\r
|
|
113
|
-
{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"type":{"type":"object"}},"required":["type"],"additionalProperties":false}\r
|
|
114
|
-
--${boundary}\r
|
|
115
|
-
Content-Disposition: form-data; name="version"\r
|
|
116
|
-
\r
|
|
117
|
-
1.2.3\r
|
|
118
|
-
--${boundary}\r
|
|
119
|
-
Content-Disposition: form-data; name="icon"; filename="icon.svg"\r
|
|
120
|
-
Content-Type: image/svg+xml\r
|
|
121
|
-
\r
|
|
122
|
-
<?xml version="1.0" standalone="no"?>
|
|
123
|
-
<svg />
|
|
124
|
-
\r
|
|
125
|
-
--${boundary}\r
|
|
126
|
-
Content-Disposition: form-data; name="files"; filename="block.js"\r
|
|
127
|
-
Content-Type: application/javascript\r
|
|
128
|
-
\r
|
|
129
|
-
export const string = 'with-icon';
|
|
130
|
-
\r
|
|
131
|
-
--${boundary}--\r
|
|
132
|
-
`);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
describe('deleteBlock', () => {
|
|
136
|
-
it('should delete a block', async () => {
|
|
137
|
-
const block = await BlockVersion.create({
|
|
138
|
-
OrganizationId: organization.id,
|
|
139
|
-
name: 'test',
|
|
140
|
-
version: '0.0.0',
|
|
141
|
-
});
|
|
142
|
-
const clientCredentials = await authorizeCLI('blocks:delete', testApp);
|
|
143
|
-
await deleteBlock({
|
|
144
|
-
remote: testApp.defaults.baseURL,
|
|
145
|
-
clientCredentials,
|
|
146
|
-
blockName: block.name,
|
|
147
|
-
blockVersion: block.version,
|
|
148
|
-
organization: organization.id,
|
|
149
|
-
});
|
|
150
|
-
const foundBlocks = await BlockVersion.findAll();
|
|
151
|
-
expect(foundBlocks).toStrictEqual([]);
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
describe('traverseBlockThemes', () => {
|
|
155
|
-
it('should upload css from a file in the app directory', async () => {
|
|
156
|
-
const app = await App.create({
|
|
157
|
-
path: 'test-app',
|
|
158
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
159
|
-
vapidPublicKey: 'a',
|
|
160
|
-
vapidPrivateKey: 'b',
|
|
161
|
-
visibility: 'public',
|
|
162
|
-
OrganizationId: organization.id,
|
|
163
|
-
});
|
|
164
|
-
await BlockVersion.create({
|
|
165
|
-
name: 'test',
|
|
166
|
-
OrganizationId: 'appsemble',
|
|
167
|
-
version: '0.0.0',
|
|
168
|
-
parameters: {
|
|
169
|
-
type: 'object',
|
|
170
|
-
properties: {
|
|
171
|
-
foo: {
|
|
172
|
-
type: 'number',
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
});
|
|
177
|
-
await authorizeCLI('apps:write', testApp);
|
|
178
|
-
await traverseBlockThemes(resolveFixture('apps/test'), app.id, testApp.defaults.baseURL, false);
|
|
179
|
-
const style = await AppBlockStyle.findOne();
|
|
180
|
-
expect(style.dataValues).toMatchInlineSnapshot(`
|
|
181
|
-
{
|
|
182
|
-
"AppId": 1,
|
|
183
|
-
"block": "@appsemble/test",
|
|
184
|
-
"created": 1970-01-01T00:00:00.000Z,
|
|
185
|
-
"style": ".tux {
|
|
186
|
-
color: rgb(0 0 0);
|
|
187
|
-
}",
|
|
188
|
-
"updated": 1970-01-01T00:00:00.000Z,
|
|
189
|
-
}
|
|
190
|
-
`);
|
|
191
|
-
});
|
|
192
|
-
it('should throw if the block does not exist', async () => {
|
|
193
|
-
const app = await App.create({
|
|
194
|
-
path: 'test-app',
|
|
195
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
196
|
-
vapidPublicKey: 'a',
|
|
197
|
-
vapidPrivateKey: 'b',
|
|
198
|
-
visibility: 'public',
|
|
199
|
-
OrganizationId: organization.id,
|
|
200
|
-
});
|
|
201
|
-
await authorizeCLI('apps:write', testApp);
|
|
202
|
-
await expect(() => traverseBlockThemes(resolveFixture('apps/test'), app.id, testApp.defaults.baseURL, false)).rejects.toThrow('Request failed with status code 404');
|
|
203
|
-
const style = await AppBlockStyle.findOne();
|
|
204
|
-
expect(style).toBeNull();
|
|
205
|
-
});
|
|
206
|
-
it('should not upload css from core and shared directories', async () => {
|
|
207
|
-
const app = await App.create({
|
|
208
|
-
path: 'test-app',
|
|
209
|
-
definition: { name: 'Test App', defaultPage: 'Test Page' },
|
|
210
|
-
vapidPublicKey: 'a',
|
|
211
|
-
vapidPrivateKey: 'b',
|
|
212
|
-
visibility: 'public',
|
|
213
|
-
OrganizationId: organization.id,
|
|
214
|
-
});
|
|
215
|
-
await BlockVersion.create({
|
|
216
|
-
name: 'test',
|
|
217
|
-
OrganizationId: 'appsemble',
|
|
218
|
-
version: '0.0.0',
|
|
219
|
-
parameters: {
|
|
220
|
-
type: 'object',
|
|
221
|
-
properties: {
|
|
222
|
-
foo: {
|
|
223
|
-
type: 'number',
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
});
|
|
228
|
-
await authorizeCLI('apps:write', testApp);
|
|
229
|
-
await traverseBlockThemes(resolveFixture('apps/test'), app.id, testApp.defaults.baseURL, false);
|
|
230
|
-
const style = await Theme.findAll();
|
|
231
|
-
expect(style).toStrictEqual([]);
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
//# sourceMappingURL=block.test.js.map
|
package/lib/coercers.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/lib/coercers.test.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { coerceRemote } from './coercers.js';
|
|
3
|
-
describe('coerceRemote', () => {
|
|
4
|
-
const tests = [
|
|
5
|
-
['http://appsemble.app', 'http://appsemble.app/'],
|
|
6
|
-
['http://appsemble.app:80', 'http://appsemble.app/'],
|
|
7
|
-
['https://appsemble.app', 'https://appsemble.app/'],
|
|
8
|
-
['https://appsemble.app:443', 'https://appsemble.app/'],
|
|
9
|
-
['https://appsemble.app:1337', 'https://appsemble.app:1337/'],
|
|
10
|
-
['https://appsemble.app/pathname', 'https://appsemble.app/'],
|
|
11
|
-
['https://appsemble.app?query=param', 'https://appsemble.app/'],
|
|
12
|
-
['https://appsemble.app#hash', 'https://appsemble.app/'],
|
|
13
|
-
['appsemble.app', 'https://appsemble.app/'],
|
|
14
|
-
['https://localhost', 'https://localhost/'],
|
|
15
|
-
['https://127.0.0.1', 'https://127.0.0.1/'],
|
|
16
|
-
['foo.localhost', 'http://foo.localhost/'],
|
|
17
|
-
['localhost', 'http://localhost/'],
|
|
18
|
-
['127.0.0.1', 'http://127.0.0.1/'],
|
|
19
|
-
['localhost:1337', 'http://localhost:1337/'],
|
|
20
|
-
['127.0.0.1:1337', 'http://127.0.0.1:1337/'],
|
|
21
|
-
];
|
|
22
|
-
it.each(tests)('should convert %s to %s', (input, expected) => {
|
|
23
|
-
const output = coerceRemote(input);
|
|
24
|
-
expect(output).toBe(expected);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
//# sourceMappingURL=coercers.test.js.map
|
package/lib/config.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/lib/config.test.js
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import { readdirSync } from 'node:fs';
|
|
2
|
-
import process from 'node:process';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { AppsembleError, resolveFixture } from '@appsemble/node-utils';
|
|
5
|
-
import { ts } from 'ts-json-schema-generator';
|
|
6
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
-
import { getProjectImplementations } from './config.js';
|
|
8
|
-
describe('config', () => {
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
vi.spyOn(process, 'cwd').mockReturnValue(resolveFixture('.'));
|
|
11
|
-
});
|
|
12
|
-
describe('getProjectImplementations', () => {
|
|
13
|
-
it('should extract configuration from a TypeScript project', () => {
|
|
14
|
-
const result = getProjectImplementations({
|
|
15
|
-
name: '',
|
|
16
|
-
layout: 'float',
|
|
17
|
-
version: '1.33.7',
|
|
18
|
-
webpack: '',
|
|
19
|
-
output: '',
|
|
20
|
-
dir: resolveFixture('getProjectImplementations/valid'),
|
|
21
|
-
});
|
|
22
|
-
expect(result).toStrictEqual({
|
|
23
|
-
actions: { testAction: { description: undefined } },
|
|
24
|
-
events: {
|
|
25
|
-
emit: { testEmit: { description: undefined } },
|
|
26
|
-
listen: { testListener: { description: undefined } },
|
|
27
|
-
},
|
|
28
|
-
messages: undefined,
|
|
29
|
-
parameters: {
|
|
30
|
-
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
31
|
-
additionalProperties: false,
|
|
32
|
-
properties: {
|
|
33
|
-
param1: { type: 'string' },
|
|
34
|
-
param2: { type: 'number' },
|
|
35
|
-
param3: { type: 'boolean' },
|
|
36
|
-
param4: { type: 'string' },
|
|
37
|
-
param5: {
|
|
38
|
-
additionalProperties: false,
|
|
39
|
-
properties: {
|
|
40
|
-
nested1: { type: 'string' },
|
|
41
|
-
nested2: { type: 'number' },
|
|
42
|
-
nested3: { type: 'boolean' },
|
|
43
|
-
},
|
|
44
|
-
required: ['nested1', 'nested2', 'nested3'],
|
|
45
|
-
type: 'object',
|
|
46
|
-
},
|
|
47
|
-
param6: { items: { type: 'string' }, type: 'array' },
|
|
48
|
-
},
|
|
49
|
-
required: ['param1', 'param2', 'param3', 'param5', 'param6'],
|
|
50
|
-
type: 'object',
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
// Spying on TypeScript functions no longer works.
|
|
55
|
-
// eslint-disable-next-line vitest/no-disabled-tests
|
|
56
|
-
it.skip('should not use TypeScript if all metadata is present in the original config', () => {
|
|
57
|
-
vi.spyOn(ts, 'createProgram');
|
|
58
|
-
const input = {
|
|
59
|
-
actions: {},
|
|
60
|
-
events: { emit: { foo: {} }, listen: { bar: {} } },
|
|
61
|
-
layout: 'float',
|
|
62
|
-
parameters: { type: 'object' },
|
|
63
|
-
version: '1.33.7',
|
|
64
|
-
webpack: '',
|
|
65
|
-
output: '',
|
|
66
|
-
dir: resolveFixture('getProjectImplementations/valid'),
|
|
67
|
-
name: '',
|
|
68
|
-
};
|
|
69
|
-
const result = getProjectImplementations(input);
|
|
70
|
-
expect(result).toBe(input);
|
|
71
|
-
expect(ts.createProgram).not.toHaveBeenCalled();
|
|
72
|
-
});
|
|
73
|
-
it('should prefer actions overrides over TypeScript actions', () => {
|
|
74
|
-
const result = getProjectImplementations({
|
|
75
|
-
actions: {},
|
|
76
|
-
version: '1.33.7',
|
|
77
|
-
webpack: '',
|
|
78
|
-
output: '',
|
|
79
|
-
dir: resolveFixture('getProjectImplementations/valid'),
|
|
80
|
-
name: '',
|
|
81
|
-
});
|
|
82
|
-
expect(result.actions).toStrictEqual({});
|
|
83
|
-
});
|
|
84
|
-
it('should prefer events overrides over TypeScript events', () => {
|
|
85
|
-
const result = getProjectImplementations({
|
|
86
|
-
events: { emit: { onSuccess: {} } },
|
|
87
|
-
version: '1.33.7',
|
|
88
|
-
webpack: '',
|
|
89
|
-
output: '',
|
|
90
|
-
dir: resolveFixture('getProjectImplementations/valid'),
|
|
91
|
-
name: '',
|
|
92
|
-
});
|
|
93
|
-
expect(result.events).toStrictEqual({ emit: { onSuccess: {} } });
|
|
94
|
-
});
|
|
95
|
-
it('should prefer parameters overrides over TypeScript parameters', () => {
|
|
96
|
-
const result = getProjectImplementations({
|
|
97
|
-
parameters: { type: 'object' },
|
|
98
|
-
version: '1.33.7',
|
|
99
|
-
webpack: '',
|
|
100
|
-
output: '',
|
|
101
|
-
dir: resolveFixture('getProjectImplementations/valid'),
|
|
102
|
-
name: '',
|
|
103
|
-
});
|
|
104
|
-
expect(result.parameters).toStrictEqual({ type: 'object' });
|
|
105
|
-
});
|
|
106
|
-
it('should throw if duplicate Actions are found', () => {
|
|
107
|
-
expect(() => getProjectImplementations({
|
|
108
|
-
webpack: '',
|
|
109
|
-
output: '',
|
|
110
|
-
dir: resolveFixture('getProjectImplementations/duplicateActions'),
|
|
111
|
-
name: '',
|
|
112
|
-
version: '1.33.7',
|
|
113
|
-
})).toThrow(new AppsembleError("Found duplicate interface 'Actions' in 'getProjectImplementations/duplicateActions/index.ts:31'"));
|
|
114
|
-
});
|
|
115
|
-
it('should throw if duplicate EventEmitters are found', () => {
|
|
116
|
-
expect(() => getProjectImplementations({
|
|
117
|
-
webpack: '',
|
|
118
|
-
output: '',
|
|
119
|
-
dir: resolveFixture('getProjectImplementations/duplicateEventEmitters'),
|
|
120
|
-
name: '',
|
|
121
|
-
version: '1.33.7',
|
|
122
|
-
})).toThrow(new AppsembleError("Found duplicate interface 'EventEmitters' in 'getProjectImplementations/duplicateEventEmitters/index.ts:31'"));
|
|
123
|
-
});
|
|
124
|
-
it('should throw if duplicate EventListeners are found', () => {
|
|
125
|
-
expect(() => getProjectImplementations({
|
|
126
|
-
webpack: '',
|
|
127
|
-
output: '',
|
|
128
|
-
dir: resolveFixture('getProjectImplementations/duplicateEventListeners'),
|
|
129
|
-
name: '',
|
|
130
|
-
version: '1.33.7',
|
|
131
|
-
})).toThrow(new AppsembleError("Found duplicate interface 'EventListeners' in 'getProjectImplementations/duplicateEventListeners/index.ts:31'"));
|
|
132
|
-
});
|
|
133
|
-
it('should throw if duplicate Parameters are found', () => {
|
|
134
|
-
expect(() => getProjectImplementations({
|
|
135
|
-
webpack: '',
|
|
136
|
-
output: '',
|
|
137
|
-
dir: resolveFixture('getProjectImplementations/duplicateParameters'),
|
|
138
|
-
name: '',
|
|
139
|
-
version: '1.33.7',
|
|
140
|
-
})).toThrow(new AppsembleError("Found duplicate interface 'Parameters' in 'getProjectImplementations/duplicateParameters/index.ts:31'"));
|
|
141
|
-
});
|
|
142
|
-
it('should handle fontawesome icons', () => {
|
|
143
|
-
const result = getProjectImplementations({
|
|
144
|
-
webpack: '',
|
|
145
|
-
output: '',
|
|
146
|
-
dir: resolveFixture('getProjectImplementations/fontawesomeParameters'),
|
|
147
|
-
name: '',
|
|
148
|
-
version: '1.33.7',
|
|
149
|
-
});
|
|
150
|
-
expect(result).toStrictEqual({
|
|
151
|
-
actions: undefined,
|
|
152
|
-
events: undefined,
|
|
153
|
-
messages: undefined,
|
|
154
|
-
parameters: {
|
|
155
|
-
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
156
|
-
additionalProperties: false,
|
|
157
|
-
properties: {
|
|
158
|
-
icon: { description: 'This is an icon.', format: 'fontawesome', type: 'string' },
|
|
159
|
-
},
|
|
160
|
-
type: 'object',
|
|
161
|
-
},
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
it('should handle TypeScript pre emit diagnostics', () => {
|
|
165
|
-
function fn() {
|
|
166
|
-
getProjectImplementations({
|
|
167
|
-
name: '',
|
|
168
|
-
layout: 'float',
|
|
169
|
-
version: '1.33.7',
|
|
170
|
-
webpack: '',
|
|
171
|
-
output: '',
|
|
172
|
-
dir: resolveFixture('getProjectImplementations/tsError'),
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
expect(fn).toThrow(AppsembleError);
|
|
176
|
-
expect(fn).toThrow(/'unused' is declared but its value is never read/);
|
|
177
|
-
});
|
|
178
|
-
it('should extract comments', () => {
|
|
179
|
-
const result = getProjectImplementations({
|
|
180
|
-
name: '',
|
|
181
|
-
layout: 'float',
|
|
182
|
-
version: '1.33.7',
|
|
183
|
-
webpack: '',
|
|
184
|
-
output: '',
|
|
185
|
-
dir: resolveFixture('getProjectImplementations/comments'),
|
|
186
|
-
});
|
|
187
|
-
expect(result).toStrictEqual({
|
|
188
|
-
actions: {
|
|
189
|
-
comment: {
|
|
190
|
-
description: 'Valid action comment',
|
|
191
|
-
},
|
|
192
|
-
duplicate: {
|
|
193
|
-
description: 'Expected comment',
|
|
194
|
-
},
|
|
195
|
-
line: {
|
|
196
|
-
description: undefined,
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
events: {
|
|
200
|
-
emit: {
|
|
201
|
-
testEmit: {
|
|
202
|
-
description: 'Test event emitter.',
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
listen: {
|
|
206
|
-
testListener: {
|
|
207
|
-
description: 'Test event listener.',
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
messages: undefined,
|
|
212
|
-
parameters: {
|
|
213
|
-
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
214
|
-
additionalProperties: false,
|
|
215
|
-
properties: {
|
|
216
|
-
param: {},
|
|
217
|
-
},
|
|
218
|
-
required: ['param'],
|
|
219
|
-
type: 'object',
|
|
220
|
-
},
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
describe('official blocks', () => {
|
|
224
|
-
const blocksDir = new URL('../../../blocks/', import.meta.url);
|
|
225
|
-
it.each(readdirSync(blocksDir))('%s', (name) => {
|
|
226
|
-
const dir = fileURLToPath(new URL(name, blocksDir));
|
|
227
|
-
const result = getProjectImplementations({
|
|
228
|
-
name,
|
|
229
|
-
version: '',
|
|
230
|
-
output: '',
|
|
231
|
-
webpack: undefined,
|
|
232
|
-
dir,
|
|
233
|
-
});
|
|
234
|
-
expect(result).toMatchSnapshot();
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
//# sourceMappingURL=config.test.js.map
|
package/lib/group.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|