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
277 lines
12 KiB
TypeScript
277 lines
12 KiB
TypeScript
import * as assert from 'node:assert';
|
|
import { afterEach, beforeEach, describe, it, mock } from 'node:test';
|
|
|
|
import type { AppManager } from '../../../src/server/AppManager';
|
|
import type { ProxiedApp } from '../../../src/server/ProxiedApp';
|
|
import type { AppBridges } from '../../../src/server/bridges';
|
|
import type { AppApiManager, AppExternalComponentManager, AppSchedulerManager, AppSlashCommandManager } from '../../../src/server/managers';
|
|
import { AppOutboundCommunicationProviderManager } from '../../../src/server/managers';
|
|
import { OutboundMessageProvider } from '../../../src/server/managers/AppOutboundCommunicationProvider';
|
|
import { AppPermissionManager } from '../../../src/server/managers/AppPermissionManager';
|
|
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('AppOutboundCommunicationProviderManager', () => {
|
|
let mockBridges: TestsAppBridges;
|
|
let mockApp: ProxiedApp;
|
|
let mockManager: AppManager;
|
|
let hasPermissionSpy: ReturnType<typeof mock.method>;
|
|
|
|
beforeEach(() => {
|
|
mockBridges = new TestsAppBridges();
|
|
|
|
mockApp = TestData.getMockApp({ info: { id: 'testing', name: 'testing' } } as IAppStorageItem, {} as AppManager);
|
|
|
|
const bri = mockBridges;
|
|
const app = mockApp;
|
|
|
|
mockManager = {
|
|
getBridges(): AppBridges {
|
|
return bri;
|
|
},
|
|
getCommandManager() {
|
|
return {} as AppSlashCommandManager;
|
|
},
|
|
getExternalComponentManager(): AppExternalComponentManager {
|
|
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;
|
|
},
|
|
getOutboundCommunicationProviderManager() {
|
|
return {} as AppOutboundCommunicationProviderManager;
|
|
},
|
|
} as AppManager;
|
|
|
|
hasPermissionSpy = mock.method(AppPermissionManager, 'hasPermission', () => true);
|
|
});
|
|
|
|
afterEach(() => {
|
|
mock.restoreAll();
|
|
});
|
|
|
|
it('basicAppOutboundCommunicationProviderManager', () => {
|
|
assert.throws(() => new AppOutboundCommunicationProviderManager({} as AppManager));
|
|
assert.doesNotThrow(() => new AppOutboundCommunicationProviderManager(mockManager));
|
|
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
assert.strictEqual((manager as any).manager, mockManager);
|
|
assert.ok((manager as any).outboundMessageProviders !== undefined);
|
|
assert.strictEqual((manager as any).outboundMessageProviders.size, 0);
|
|
});
|
|
|
|
it('addProvider', () => {
|
|
const provider = TestData.getOutboundPhoneMessageProvider();
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
assert.doesNotThrow(() => manager.addProvider('testing', provider));
|
|
assert.strictEqual((manager as any).outboundMessageProviders.size, 1);
|
|
assert.throws(() => manager.addProvider('failMePlease', provider), {
|
|
name: 'Error',
|
|
message: 'App must exist in order for an outbound provider to be added.',
|
|
});
|
|
assert.strictEqual((manager as any).outboundMessageProviders.size, 1);
|
|
});
|
|
|
|
it('isAlreadyDefined', () => {
|
|
const provider = TestData.getOutboundPhoneMessageProvider();
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
assert.strictEqual(manager.isAlreadyDefined('testing', 'phone'), false);
|
|
|
|
manager.addProvider('testing', provider);
|
|
|
|
assert.strictEqual(manager.isAlreadyDefined('testing', 'phone'), true);
|
|
assert.strictEqual(manager.isAlreadyDefined('testing', 'email'), false);
|
|
assert.strictEqual(manager.isAlreadyDefined('another-app', 'phone'), false);
|
|
});
|
|
|
|
it('addProviderTwiceShouldOverwrite', () => {
|
|
const provider1 = TestData.getOutboundPhoneMessageProvider('provider1');
|
|
const provider2 = TestData.getOutboundPhoneMessageProvider('provider2');
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
manager.addProvider('testing', provider1);
|
|
const firstProviderInfo = (manager as any).outboundMessageProviders.get('testing').get('phone');
|
|
assert.strictEqual(firstProviderInfo.provider.name, 'provider1');
|
|
|
|
// Adding a provider of the same type should overwrite the previous one
|
|
manager.addProvider('testing', provider2);
|
|
const secondProviderInfo = (manager as any).outboundMessageProviders.get('testing').get('phone');
|
|
assert.strictEqual(secondProviderInfo.provider.name, 'provider2');
|
|
assert.strictEqual((manager as any).outboundMessageProviders.get('testing').size, 1);
|
|
});
|
|
|
|
it('addProviderWithoutPermission', () => {
|
|
const provider = TestData.getOutboundPhoneMessageProvider();
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
hasPermissionSpy.mock.mockImplementation(() => false);
|
|
|
|
assert.throws(() => manager.addProvider('testing', provider));
|
|
});
|
|
|
|
it('ignoreAppsWithoutProviders', async () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
await assert.doesNotReject(() => manager.registerProviders('non-existant'));
|
|
});
|
|
|
|
it('registerProviders', async () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
manager.addProvider('firstApp', TestData.getOutboundPhoneMessageProvider());
|
|
const appInfo = (manager as any).outboundMessageProviders.get('firstApp');
|
|
assert.ok(appInfo !== undefined);
|
|
const regInfo = appInfo.get('phone');
|
|
assert.ok(regInfo !== undefined);
|
|
|
|
assert.strictEqual(regInfo.isRegistered, false);
|
|
await assert.doesNotReject(async () => manager.registerProviders('firstApp'));
|
|
assert.strictEqual(regInfo.isRegistered, true);
|
|
});
|
|
|
|
it('registerTwoProviders', async () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
manager.addProvider('firstApp', TestData.getOutboundPhoneMessageProvider());
|
|
manager.addProvider('firstApp', TestData.getOutboundEmailMessageProvider());
|
|
const firstApp = (manager as any).outboundMessageProviders.get('firstApp');
|
|
assert.ok(firstApp !== undefined);
|
|
const firstRegInfo = firstApp.get('phone');
|
|
assert.ok(firstRegInfo !== undefined);
|
|
const secondRegInfo = firstApp.get('email');
|
|
assert.ok(secondRegInfo !== undefined);
|
|
|
|
assert.strictEqual(firstRegInfo.isRegistered, false);
|
|
assert.strictEqual(secondRegInfo.isRegistered, false);
|
|
await assert.doesNotReject(async () => manager.registerProviders('firstApp'));
|
|
assert.strictEqual(firstRegInfo.isRegistered, true);
|
|
assert.strictEqual(secondRegInfo.isRegistered, true);
|
|
});
|
|
|
|
it('registerProvidersFromMultipleApps', async () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
manager.addProvider('firstApp', TestData.getOutboundPhoneMessageProvider());
|
|
manager.addProvider('firstApp', TestData.getOutboundEmailMessageProvider());
|
|
manager.addProvider('secondApp', TestData.getOutboundPhoneMessageProvider('another-phone-provider'));
|
|
|
|
const firstApp = (manager as any).outboundMessageProviders.get('firstApp');
|
|
assert.ok(firstApp !== undefined);
|
|
const firstRegInfo = firstApp.get('phone');
|
|
const secondRegInfo = firstApp.get('email');
|
|
assert.ok(firstRegInfo !== undefined);
|
|
assert.ok(secondRegInfo !== undefined);
|
|
const secondApp = (manager as any).outboundMessageProviders.get('secondApp');
|
|
assert.ok(secondApp !== undefined);
|
|
const thirdRegInfo = secondApp.get('phone');
|
|
assert.ok(thirdRegInfo !== undefined);
|
|
|
|
assert.strictEqual(firstRegInfo.isRegistered, false);
|
|
assert.strictEqual(secondRegInfo.isRegistered, false);
|
|
await assert.doesNotReject(async () => manager.registerProviders('firstApp'));
|
|
assert.strictEqual(firstRegInfo.isRegistered, true);
|
|
assert.strictEqual(secondRegInfo.isRegistered, true);
|
|
assert.strictEqual(thirdRegInfo.isRegistered, false);
|
|
await assert.doesNotReject(async () => manager.registerProviders('secondApp'));
|
|
assert.strictEqual(thirdRegInfo.isRegistered, true);
|
|
});
|
|
|
|
it('unregisterProviders', async () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
manager.addProvider('testing', TestData.getOutboundPhoneMessageProvider());
|
|
const regInfo = (manager as any).outboundMessageProviders.get('testing').get('phone');
|
|
await assert.doesNotReject(async () => manager.registerProviders('testing'));
|
|
|
|
await assert.doesNotReject(async () => manager.unregisterProviders('non-existant'));
|
|
assert.strictEqual(regInfo.isRegistered, true);
|
|
await assert.doesNotReject(async () => manager.unregisterProviders('testing'));
|
|
assert.strictEqual(regInfo.isRegistered, false);
|
|
// It should be removed from the map
|
|
assert.strictEqual((manager as any).outboundMessageProviders.has('testing'), false);
|
|
});
|
|
|
|
it('unregisterProvidersWithKeepReferences', async () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
manager.addProvider('testing', TestData.getOutboundPhoneMessageProvider());
|
|
const appInfo = (manager as any).outboundMessageProviders.get('testing');
|
|
const regInfo = appInfo.get('phone');
|
|
|
|
await assert.doesNotReject(async () => manager.registerProviders('testing'));
|
|
assert.strictEqual(regInfo.isRegistered, true);
|
|
await assert.doesNotReject(async () => manager.unregisterProviders('testing', { keepReferences: true }));
|
|
assert.strictEqual(regInfo.isRegistered, false);
|
|
// It should not be removed from the map
|
|
assert.strictEqual((manager as any).outboundMessageProviders.has('testing'), true);
|
|
});
|
|
|
|
it('failToGetMetadataWithoutProvider', () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
|
|
assert.throws(() => manager.getProviderMetadata('testing', 'phone'), { name: 'Error', message: 'provider-not-registered' });
|
|
|
|
manager.addProvider('testing', TestData.getOutboundPhoneMessageProvider());
|
|
|
|
assert.throws(() => manager.getProviderMetadata('testing', 'email'), { name: 'Error', message: 'provider-not-registered' });
|
|
});
|
|
|
|
it('getProviderMetadata', async () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
manager.addProvider('testing', TestData.getOutboundPhoneMessageProvider());
|
|
|
|
mock.method(OutboundMessageProvider.prototype, 'runGetProviderMetadata', () =>
|
|
Promise.resolve({
|
|
name: 'test-provider',
|
|
capabilities: ['sms'],
|
|
}),
|
|
);
|
|
|
|
const metadata = await manager.getProviderMetadata('testing', 'phone');
|
|
assert.deepStrictEqual(metadata, {
|
|
name: 'test-provider',
|
|
capabilities: ['sms'],
|
|
});
|
|
});
|
|
|
|
it('failToSendOutboundMessageWithoutProvider', () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
const message = TestData.getOutboundMessage();
|
|
|
|
assert.throws(() => manager.sendOutboundMessage('testing', 'phone', message), { name: 'Error', message: 'provider-not-registered' });
|
|
|
|
manager.addProvider('testing', TestData.getOutboundPhoneMessageProvider());
|
|
|
|
assert.throws(() => manager.sendOutboundMessage('testing', 'email', message), { name: 'Error', message: 'provider-not-registered' });
|
|
});
|
|
|
|
it('sendOutboundMessage', async () => {
|
|
const manager = new AppOutboundCommunicationProviderManager(mockManager);
|
|
manager.addProvider('testing', TestData.getOutboundPhoneMessageProvider());
|
|
|
|
const message = TestData.getOutboundMessage();
|
|
|
|
mock.method(OutboundMessageProvider.prototype, 'runSendOutboundMessage', () => Promise.resolve('message-id'));
|
|
|
|
const result = await manager.sendOutboundMessage('testing', 'phone', message);
|
|
assert.strictEqual(result, 'message-id');
|
|
});
|
|
});
|