Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
220 lines
7.5 KiB
TypeScript
220 lines
7.5 KiB
TypeScript
import * as assert from 'node:assert';
|
|
import { afterEach, beforeEach, describe, it, mock } from 'node:test';
|
|
|
|
import { RequestMethod } from '@rocket.chat/apps-engine/definition/accessors';
|
|
import type { IApi, IApiRequest } from '@rocket.chat/apps-engine/definition/api';
|
|
|
|
import type { AppManager } from '../../../src/server/AppManager';
|
|
import type { ProxiedApp } from '../../../src/server/ProxiedApp';
|
|
import type { AppBridges } from '../../../src/server/bridges';
|
|
import type {
|
|
AppExternalComponentManager,
|
|
AppSchedulerManager,
|
|
AppSlashCommandManager,
|
|
AppVideoConfProviderManager,
|
|
} from '../../../src/server/managers';
|
|
import { AppApiManager } from '../../../src/server/managers';
|
|
import { AppApi } from '../../../src/server/managers/AppApi';
|
|
import type { UIActionButtonManager } from '../../../src/server/managers/UIActionButtonManager';
|
|
import type { AppLogStorage, IAppStorageItem } from '../../../src/server/storage';
|
|
import { TestsAppBridges } from '../../test-data/bridges/appBridges';
|
|
import { TestsAppLogStorage } from '../../test-data/storage/logStorage';
|
|
import { TestData } from '../../test-data/utilities';
|
|
|
|
describe('AppApiManager', () => {
|
|
let mockBridges: TestsAppBridges;
|
|
let mockApp: ProxiedApp;
|
|
let mockManager: AppManager;
|
|
|
|
beforeEach(() => {
|
|
mockBridges = new TestsAppBridges();
|
|
|
|
mockApp = TestData.getMockApp({ info: { id: 'testing', name: 'TestApp' } } as IAppStorageItem, {} as AppManager);
|
|
|
|
const bri = mockBridges;
|
|
const app = mockApp;
|
|
mockManager = {
|
|
getBridges(): AppBridges {
|
|
return bri;
|
|
},
|
|
getCommandManager() {
|
|
return {} as AppSlashCommandManager;
|
|
},
|
|
getExternalComponentManager() {
|
|
return {} as AppExternalComponentManager;
|
|
},
|
|
getApiManager() {
|
|
return {} as AppApiManager;
|
|
},
|
|
getOneById(appId: string): ProxiedApp {
|
|
return appId === 'failMePlease' ? undefined : app;
|
|
},
|
|
getLogStorage(): AppLogStorage {
|
|
return new TestsAppLogStorage();
|
|
},
|
|
getSchedulerManager() {
|
|
return {} as AppSchedulerManager;
|
|
},
|
|
getUIActionButtonManager() {
|
|
return {} as UIActionButtonManager;
|
|
},
|
|
getVideoConfProviderManager() {
|
|
return {} as AppVideoConfProviderManager;
|
|
},
|
|
} as AppManager;
|
|
});
|
|
|
|
afterEach(() => {
|
|
mock.restoreAll();
|
|
});
|
|
|
|
it('basicAppApiManager', () => {
|
|
assert.throws(() => new AppApiManager({} as AppManager));
|
|
assert.doesNotThrow(() => new AppApiManager(mockManager));
|
|
|
|
const ascm = new AppApiManager(mockManager);
|
|
assert.strictEqual((ascm as any).manager, mockManager);
|
|
assert.strictEqual((ascm as any).bridge, mockBridges.getApiBridge());
|
|
assert.ok((ascm as any).providedApis !== undefined);
|
|
assert.strictEqual((ascm as any).providedApis.size, 0);
|
|
});
|
|
|
|
it('registerApi', async () => {
|
|
const doRegisterApiSpy = mock.method(mockBridges.getApiBridge(), 'doRegisterApi');
|
|
const ascm = new AppApiManager(mockManager);
|
|
|
|
const api: IApi = TestData.getApi('path');
|
|
const regInfo = new AppApi(mockApp, api, api.endpoints[0]);
|
|
|
|
await assert.doesNotReject(() => (ascm as any).registerApi('testing', regInfo));
|
|
assert.strictEqual(doRegisterApiSpy.mock.calls.length, 1);
|
|
assert.deepStrictEqual(doRegisterApiSpy.mock.calls[0].arguments, [regInfo, 'testing']);
|
|
});
|
|
|
|
it('addApi', () => {
|
|
mockBridges = new TestsAppBridges();
|
|
const bri = mockBridges;
|
|
mockManager.getBridges = function _refreshedGetBridges(): AppBridges {
|
|
return bri;
|
|
};
|
|
|
|
const doRegisterApiSpy = mock.method(mockBridges.getApiBridge(), 'doRegisterApi');
|
|
void doRegisterApiSpy;
|
|
|
|
const api = TestData.getApi('apipath');
|
|
const ascm = new AppApiManager(mockManager);
|
|
assert.doesNotThrow(() => ascm.addApi('testing', api));
|
|
assert.strictEqual(mockBridges.getApiBridge().apis.size, 1);
|
|
assert.strictEqual((ascm as any).providedApis.size, 1);
|
|
assert.strictEqual((ascm as any).providedApis.get('testing').get('apipath').api, api);
|
|
|
|
assert.throws(() => ascm.addApi('testing', api), {
|
|
name: 'PathAlreadyExists',
|
|
message: 'The api path "apipath" already exists in the system.',
|
|
});
|
|
|
|
assert.throws(() => ascm.addApi('failMePlease', TestData.getApi('yet-another')), {
|
|
name: 'Error',
|
|
message: 'App must exist in order for an api to be added.',
|
|
});
|
|
assert.doesNotThrow(() => ascm.addApi('testing', TestData.getApi('another-api')));
|
|
assert.strictEqual((ascm as any).providedApis.size, 1);
|
|
assert.strictEqual((ascm as any).providedApis.get('testing').size, 2);
|
|
});
|
|
|
|
it('registerApis', async () => {
|
|
mockBridges = new TestsAppBridges();
|
|
const bri = mockBridges;
|
|
mockManager.getBridges = function _refreshedGetBridges(): AppBridges {
|
|
return bri;
|
|
};
|
|
const doRegisterApiSpy = mock.method(mockBridges.getApiBridge(), 'doRegisterApi');
|
|
|
|
const ascm = new AppApiManager(mockManager);
|
|
|
|
const registerApiSpy = mock.method(ascm as any, 'registerApi');
|
|
|
|
ascm.addApi('testing', TestData.getApi('apipath'));
|
|
const regInfo = (ascm as any).providedApis.get('testing').get('apipath') as AppApi;
|
|
|
|
await assert.doesNotReject(() => ascm.registerApis('non-existant'));
|
|
await assert.doesNotReject(() => ascm.registerApis('testing'));
|
|
assert.strictEqual(registerApiSpy.mock.calls.filter((c: any) => c.arguments[0] === 'testing' && c.arguments[1] === regInfo).length, 1);
|
|
assert.strictEqual(
|
|
doRegisterApiSpy.mock.calls.filter((c: any) => c.arguments[0] === regInfo && c.arguments[1] === 'testing').length,
|
|
1,
|
|
);
|
|
});
|
|
|
|
it('unregisterApis', async () => {
|
|
mockBridges = new TestsAppBridges();
|
|
const bri = mockBridges;
|
|
mockManager.getBridges = function _refreshedGetBridges(): AppBridges {
|
|
return bri;
|
|
};
|
|
const doUnregisterApisSpy = mock.method(mockBridges.getApiBridge(), 'doUnregisterApis');
|
|
|
|
const ascm = new AppApiManager(mockManager);
|
|
|
|
ascm.addApi('testing', TestData.getApi('apipath'));
|
|
|
|
await assert.doesNotReject(() => ascm.unregisterApis('non-existant'));
|
|
await assert.doesNotReject(() => ascm.unregisterApis('testing'));
|
|
assert.strictEqual(doUnregisterApisSpy.mock.calls.length, 1);
|
|
});
|
|
|
|
it('executeApis', async () => {
|
|
mockBridges = new TestsAppBridges();
|
|
const bri = mockBridges;
|
|
mockManager.getBridges = function _refreshedGetBridges(): AppBridges {
|
|
return bri;
|
|
};
|
|
|
|
const ascm = new AppApiManager(mockManager);
|
|
ascm.addApi('testing', TestData.getApi('api1'));
|
|
ascm.addApi('testing', TestData.getApi('api2'));
|
|
ascm.addApi('testing', TestData.getApi('api3'));
|
|
await ascm.registerApis('testing');
|
|
|
|
const request: IApiRequest = {
|
|
method: RequestMethod.GET,
|
|
headers: {},
|
|
query: {},
|
|
params: {},
|
|
content: '',
|
|
};
|
|
|
|
await assert.doesNotReject(() => ascm.executeApi('testing', 'nope', request));
|
|
await assert.doesNotReject(() => ascm.executeApi('testing', 'not-exists', request));
|
|
await assert.doesNotReject(() => ascm.executeApi('testing', 'api1', request));
|
|
await assert.doesNotReject(() => ascm.executeApi('testing', 'api2', request));
|
|
await assert.doesNotReject(() => ascm.executeApi('testing', 'api3', request));
|
|
});
|
|
|
|
it('listApis', async () => {
|
|
mockBridges = new TestsAppBridges();
|
|
const bri = mockBridges;
|
|
mockManager.getBridges = function _refreshedGetBridges(): AppBridges {
|
|
return bri;
|
|
};
|
|
|
|
const ascm = new AppApiManager(mockManager);
|
|
|
|
assert.deepStrictEqual(ascm.listApis('testing'), []);
|
|
|
|
ascm.addApi('testing', TestData.getApi('api1'));
|
|
await ascm.registerApis('testing');
|
|
|
|
assert.doesNotThrow(() => ascm.listApis('testing'));
|
|
assert.notDeepStrictEqual(ascm.listApis('testing'), []);
|
|
assert.deepStrictEqual(ascm.listApis('testing'), [
|
|
{
|
|
path: 'api1',
|
|
computedPath: '/api/apps/public/testing/api1',
|
|
methods: ['get'],
|
|
examples: {},
|
|
},
|
|
]);
|
|
});
|
|
});
|