Skip to content

Commit 5e7c4e5

Browse files
committed
copy apps-engine tests
1 parent f9d22fd commit 5e7c4e5

104 files changed

Lines changed: 8056 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ export default [
338338
},
339339
},
340340
{
341-
files: ['packages/apps-engine/tests/**/*'],
341+
files: ['packages/apps-engine/tests/**/*', 'packages/apps/tests/**/*'],
342342
rules: {
343343
'@typescript-eslint/no-non-null-assertion': 'off',
344344
'testing-library/no-await-sync-queries': 'off',

packages/apps/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.deno-cache/
2+
/tests/test-data/dbs
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
import * as assert from 'node:assert';
2+
import { describe, it, afterEach, mock } from 'node:test';
3+
4+
import { AppManager } from '../../src/server/AppManager';
5+
import { AppBridges } from '../../src/server/bridges';
6+
import { AppCompiler, AppPackageParser } from '../../src/server/compiler';
7+
import {
8+
AppAccessorManager,
9+
AppApiManager,
10+
AppExternalComponentManager,
11+
AppListenerManager,
12+
AppSettingsManager,
13+
AppSlashCommandManager,
14+
AppVideoConfProviderManager,
15+
AppOutboundCommunicationProviderManager,
16+
} from '../../src/server/managers';
17+
import type { AppLogStorage, AppMetadataStorage, AppSourceStorage } from '../../src/server/storage';
18+
import { SimpleClass, TestData, TestInfastructureSetup } from '../test-data/utilities';
19+
20+
describe('AppManager', () => {
21+
const testingInfastructure = new TestInfastructureSetup();
22+
23+
afterEach(() => {
24+
AppManager.Instance = undefined;
25+
mock.restoreAll();
26+
});
27+
28+
it('Setup of the AppManager', () => {
29+
const manager = new AppManager({
30+
metadataStorage: testingInfastructure.getAppStorage(),
31+
logStorage: testingInfastructure.getLogStorage(),
32+
bridges: testingInfastructure.getAppBridges(),
33+
sourceStorage: testingInfastructure.getSourceStorage(),
34+
tempFilePath: testingInfastructure.getTempFilePath(),
35+
});
36+
37+
assert.strictEqual(manager.getStorage(), testingInfastructure.getAppStorage());
38+
assert.strictEqual(manager.getLogStorage(), testingInfastructure.getLogStorage());
39+
// NOTE: manager.getBridges() returns a proxy, so they are vlaue equality instead of reference equality
40+
assert.deepStrictEqual(manager.getBridges(), testingInfastructure.getAppBridges());
41+
assert.strictEqual(manager.areAppsLoaded(), false);
42+
43+
assert.throws(
44+
() =>
45+
new AppManager({
46+
metadataStorage: {} as AppMetadataStorage,
47+
logStorage: {} as AppLogStorage,
48+
bridges: {} as AppBridges,
49+
sourceStorage: {} as AppSourceStorage,
50+
tempFilePath: 'temp-file-path',
51+
}),
52+
{
53+
name: 'Error',
54+
message: 'There is already a valid AppManager instance',
55+
},
56+
);
57+
});
58+
59+
it('Invalid Storage and Bridge', () => {
60+
const invalid = new SimpleClass();
61+
62+
assert.throws(
63+
() =>
64+
new AppManager({
65+
metadataStorage: invalid as any,
66+
logStorage: invalid as any,
67+
bridges: invalid as any,
68+
sourceStorage: invalid as any,
69+
tempFilePath: 'temp-file-path',
70+
}),
71+
{
72+
name: 'Error',
73+
message: 'Invalid instance of the AppMetadataStorage',
74+
},
75+
);
76+
77+
assert.throws(
78+
() =>
79+
new AppManager({
80+
metadataStorage: testingInfastructure.getAppStorage(),
81+
logStorage: invalid as any,
82+
bridges: invalid as any,
83+
sourceStorage: invalid as any,
84+
tempFilePath: 'temp-file-path',
85+
}),
86+
{
87+
name: 'Error',
88+
message: 'Invalid instance of the AppLogStorage',
89+
},
90+
);
91+
92+
assert.throws(
93+
() =>
94+
new AppManager({
95+
metadataStorage: testingInfastructure.getAppStorage(),
96+
logStorage: testingInfastructure.getLogStorage(),
97+
bridges: invalid as any,
98+
sourceStorage: invalid as any,
99+
tempFilePath: 'temp-file-path',
100+
}),
101+
{
102+
name: 'Error',
103+
message: 'Invalid instance of the AppBridges',
104+
},
105+
);
106+
107+
assert.throws(
108+
() =>
109+
new AppManager({
110+
metadataStorage: testingInfastructure.getAppStorage(),
111+
logStorage: testingInfastructure.getLogStorage(),
112+
bridges: testingInfastructure.getAppBridges(),
113+
sourceStorage: invalid as any,
114+
tempFilePath: testingInfastructure.getTempFilePath(),
115+
}),
116+
{
117+
name: 'Error',
118+
message: 'Invalid instance of the AppSourceStorage',
119+
},
120+
);
121+
});
122+
123+
it('Ensure Managers are Valid Types', () => {
124+
const manager = new AppManager({
125+
metadataStorage: testingInfastructure.getAppStorage(),
126+
logStorage: testingInfastructure.getLogStorage(),
127+
bridges: testingInfastructure.getAppBridges(),
128+
sourceStorage: testingInfastructure.getSourceStorage(),
129+
tempFilePath: testingInfastructure.getTempFilePath(),
130+
});
131+
132+
assert.ok(manager.getParser() instanceof AppPackageParser);
133+
assert.ok(manager.getCompiler() instanceof AppCompiler);
134+
assert.ok(manager.getAccessorManager() instanceof AppAccessorManager);
135+
assert.ok(manager.getBridges() instanceof AppBridges);
136+
assert.ok(manager.getListenerManager() instanceof AppListenerManager);
137+
assert.ok(manager.getCommandManager() instanceof AppSlashCommandManager);
138+
assert.ok(manager.getExternalComponentManager() instanceof AppExternalComponentManager);
139+
assert.ok(manager.getApiManager() instanceof AppApiManager);
140+
assert.ok(manager.getSettingsManager() instanceof AppSettingsManager);
141+
assert.ok(manager.getVideoConfProviderManager() instanceof AppVideoConfProviderManager);
142+
assert.ok(manager.getOutboundCommunicationProviderManager() instanceof AppOutboundCommunicationProviderManager);
143+
});
144+
145+
it('Update Apps Marketplace Info - Apps without subscription info are skipped', async () => {
146+
const manager = new AppManager({
147+
metadataStorage: testingInfastructure.getAppStorage(),
148+
logStorage: testingInfastructure.getLogStorage(),
149+
bridges: testingInfastructure.getAppBridges(),
150+
sourceStorage: testingInfastructure.getSourceStorage(),
151+
tempFilePath: testingInfastructure.getTempFilePath(),
152+
});
153+
154+
const appsOverview = TestData.getAppsOverview();
155+
appsOverview[0].latest.subscriptionInfo = undefined; // No subscription info
156+
157+
// Mock the apps Map to return our mock app
158+
(manager as any).apps = new Map([['test-app', TestData.getMockApp(TestData.getAppStorageItem(), manager)]]);
159+
160+
const updatePartialAndReturnDocumentSpy = mock.method(manager.getStorage(), 'updatePartialAndReturnDocument', () => Promise.resolve());
161+
162+
// Should not throw and complete successfully
163+
await manager.updateAppsMarketplaceInfo(appsOverview);
164+
165+
assert.strictEqual(updatePartialAndReturnDocumentSpy.mock.calls.length, 0);
166+
});
167+
168+
it('Update Apps Marketplace Info - Apps not found in manager are skipped', async () => {
169+
const manager = new AppManager({
170+
metadataStorage: testingInfastructure.getAppStorage(),
171+
logStorage: testingInfastructure.getLogStorage(),
172+
bridges: testingInfastructure.getAppBridges(),
173+
sourceStorage: testingInfastructure.getSourceStorage(),
174+
tempFilePath: testingInfastructure.getTempFilePath(),
175+
});
176+
177+
const appsOverview = TestData.getAppsOverview();
178+
appsOverview[0].latest.id = 'nonexistent-app'; // App not in manager
179+
180+
// Mock the apps Map to return our mock app
181+
(manager as any).apps = new Map([['test-app', TestData.getMockApp(TestData.getAppStorageItem(), manager)]]);
182+
183+
const updatePartialAndReturnDocumentSpy = mock.method(manager.getStorage(), 'updatePartialAndReturnDocument', () => Promise.resolve());
184+
185+
// Should not throw and complete successfully
186+
await manager.updateAppsMarketplaceInfo(appsOverview);
187+
188+
assert.strictEqual(updatePartialAndReturnDocumentSpy.mock.calls.length, 0);
189+
});
190+
191+
it('Update Apps Marketplace Info - Apps with same license are skipped', async () => {
192+
const manager = new AppManager({
193+
metadataStorage: testingInfastructure.getAppStorage(),
194+
logStorage: testingInfastructure.getLogStorage(),
195+
bridges: testingInfastructure.getAppBridges(),
196+
sourceStorage: testingInfastructure.getSourceStorage(),
197+
tempFilePath: testingInfastructure.getTempFilePath(),
198+
});
199+
200+
const sameLicenseData = 'same-license-data';
201+
const existingSubscriptionInfo = TestData.getMarketplaceSubscriptionInfo({
202+
license: { license: sameLicenseData, version: 1, expireDate: new Date('2023-01-01') },
203+
});
204+
205+
const mockStorageItem = TestData.getAppStorageItem({
206+
marketplaceInfo: [TestData.getMarketplaceInfo({ subscriptionInfo: existingSubscriptionInfo })],
207+
});
208+
209+
const mockApp = TestData.getMockApp(mockStorageItem, manager);
210+
211+
// Mock the apps Map to return our mock app
212+
(manager as any).apps = new Map([['test-app', mockApp]]);
213+
214+
const appsOverview = TestData.getAppsOverview(
215+
TestData.getMarketplaceSubscriptionInfo({
216+
license: { license: sameLicenseData, version: 1, expireDate: new Date('2023-01-01') },
217+
}),
218+
);
219+
220+
const updatePartialAndReturnDocumentSpy = mock.method(manager.getStorage(), 'updatePartialAndReturnDocument', () => Promise.resolve());
221+
222+
// Should not throw and complete successfully
223+
await manager.updateAppsMarketplaceInfo(appsOverview);
224+
225+
// Verify the subscription info was not updated (should remain the same)
226+
assert.strictEqual(mockStorageItem.marketplaceInfo[0].subscriptionInfo.seats, 10); // Original value
227+
assert.strictEqual(updatePartialAndReturnDocumentSpy.mock.calls.length, 0);
228+
});
229+
230+
it('Update Apps Marketplace Info - Subscription info is updated and app is signed', async () => {
231+
const manager = new AppManager({
232+
metadataStorage: testingInfastructure.getAppStorage(),
233+
logStorage: testingInfastructure.getLogStorage(),
234+
bridges: testingInfastructure.getAppBridges(),
235+
sourceStorage: testingInfastructure.getSourceStorage(),
236+
tempFilePath: testingInfastructure.getTempFilePath(),
237+
});
238+
239+
const existingSubscriptionInfo = TestData.getMarketplaceSubscriptionInfo({
240+
license: { license: 'old-license-data', version: 1, expireDate: new Date('2023-01-01') },
241+
});
242+
243+
const newSubscriptionInfo = TestData.getMarketplaceSubscriptionInfo({
244+
seats: 20,
245+
maxSeats: 200,
246+
startDate: '2023-02-01',
247+
periodEnd: '2024-01-31',
248+
license: { license: 'new-license-data', version: 1, expireDate: new Date('2026-01-01') },
249+
});
250+
251+
const mockStorageItem = TestData.getAppStorageItem({
252+
marketplaceInfo: [TestData.getMarketplaceInfo({ subscriptionInfo: existingSubscriptionInfo })],
253+
});
254+
255+
const mockApp = TestData.getMockApp(mockStorageItem, manager);
256+
257+
mock.method(manager.getSignatureManager(), 'signApp', () => Promise.resolve('signed-app-data'));
258+
mock.method(mockApp, 'validateLicense', () => Promise.resolve());
259+
260+
const updatePartialAndReturnDocumentSpy = mock.method(manager.getStorage(), 'updatePartialAndReturnDocument', () =>
261+
Promise.resolve(mockStorageItem),
262+
);
263+
264+
// Mock the apps Map and dependencies
265+
(manager as any).apps = new Map([['test-app', mockApp]]);
266+
267+
const appsOverview = TestData.getAppsOverview(newSubscriptionInfo);
268+
269+
await manager.updateAppsMarketplaceInfo(appsOverview);
270+
271+
const expectedStorageItem = mockApp.getStorageItem();
272+
273+
// Verify the subscription info was updated
274+
assert.strictEqual(expectedStorageItem.marketplaceInfo[0].subscriptionInfo.seats, 20);
275+
assert.strictEqual(expectedStorageItem.marketplaceInfo[0].subscriptionInfo.license.license, 'new-license-data');
276+
assert.strictEqual(expectedStorageItem.signature, 'signed-app-data');
277+
assert.strictEqual(updatePartialAndReturnDocumentSpy.mock.calls.length, 1);
278+
});
279+
});

0 commit comments

Comments
 (0)