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
312 lines
11 KiB
TypeScript
312 lines
11 KiB
TypeScript
import * as assert from 'node:assert';
|
|
import { afterEach, beforeEach, describe, it, mock } from 'node:test';
|
|
|
|
import { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
|
|
import type { IUIActionButtonDescriptor } from '@rocket.chat/apps-engine/definition/ui';
|
|
import { UIActionButtonContext } from '@rocket.chat/apps-engine/definition/ui';
|
|
|
|
import type { AppManager } from '../../../src/server/AppManager';
|
|
import type { ProxiedApp } from '../../../src/server/ProxiedApp';
|
|
import type { AppActivationBridge, AppBridges } from '../../../src/server/bridges';
|
|
import { AppPermissionManager } from '../../../src/server/managers/AppPermissionManager';
|
|
import { UIActionButtonManager } from '../../../src/server/managers/UIActionButtonManager';
|
|
import { AppPermissions } from '../../../src/server/permissions/AppPermissions';
|
|
import { TestsAppBridges } from '../../test-data/bridges/appBridges';
|
|
|
|
describe('UIActionButtonManager', () => {
|
|
let mockBridges: TestsAppBridges;
|
|
let mockApp: ProxiedApp;
|
|
let mockApp2: ProxiedApp;
|
|
let mockManager: AppManager;
|
|
let mockActivationBridge: AppActivationBridge;
|
|
let hasPermissionSpy: ReturnType<typeof mock.method>;
|
|
let notifyAboutErrorSpy: ReturnType<typeof mock.method>;
|
|
let doActionsChangedSpy: ReturnType<typeof mock.method>;
|
|
|
|
beforeEach(() => {
|
|
mockBridges = new TestsAppBridges();
|
|
mockActivationBridge = mockBridges.getAppActivationBridge();
|
|
|
|
mockApp = {
|
|
getID() {
|
|
return 'testing-app';
|
|
},
|
|
getName() {
|
|
return 'Test App';
|
|
},
|
|
getStatus() {
|
|
return Promise.resolve(AppStatus.AUTO_ENABLED);
|
|
},
|
|
} as ProxiedApp;
|
|
|
|
mockApp2 = {
|
|
getID() {
|
|
return 'testing-app-2';
|
|
},
|
|
getName() {
|
|
return 'Test App 2';
|
|
},
|
|
getStatus() {
|
|
return Promise.resolve(AppStatus.AUTO_ENABLED);
|
|
},
|
|
} as ProxiedApp;
|
|
|
|
const bri = mockBridges;
|
|
const app = mockApp;
|
|
const app2 = mockApp2;
|
|
mockManager = {
|
|
getBridges(): AppBridges {
|
|
return bri;
|
|
},
|
|
getOneById: (appId: string): ProxiedApp | undefined => {
|
|
if (appId === 'testing-app') {
|
|
return app;
|
|
}
|
|
if (appId === 'testing-app-2') {
|
|
return app2;
|
|
}
|
|
return undefined;
|
|
},
|
|
} as AppManager;
|
|
|
|
notifyAboutErrorSpy = mock.method(AppPermissionManager, 'notifyAboutError');
|
|
hasPermissionSpy = mock.method(AppPermissionManager, 'hasPermission');
|
|
doActionsChangedSpy = mock.method(mockActivationBridge, 'doActionsChanged');
|
|
});
|
|
|
|
afterEach(() => {
|
|
mock.restoreAll();
|
|
});
|
|
|
|
it('basicUIActionButtonManager', () => {
|
|
assert.doesNotThrow(() => new UIActionButtonManager(mockManager));
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
assert.strictEqual((manager as any).manager, mockManager);
|
|
assert.strictEqual((manager as any).activationBridge, mockActivationBridge);
|
|
assert.ok((manager as any).registeredActionButtons !== undefined);
|
|
assert.strictEqual((manager as any).registeredActionButtons.size, 0);
|
|
});
|
|
|
|
it('registerActionButtonWithPermission', () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button: IUIActionButtonDescriptor = {
|
|
actionId: 'test-action',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label',
|
|
};
|
|
|
|
const result = manager.registerActionButton('testing-app', button);
|
|
|
|
assert.strictEqual(result, true);
|
|
assert.strictEqual(hasPermissionSpy.mock.calls.length, 1);
|
|
assert.deepStrictEqual(hasPermissionSpy.mock.calls[0].arguments, ['testing-app', AppPermissions.ui.registerButtons]);
|
|
assert.ok(doActionsChangedSpy.mock.calls.length > 0);
|
|
assert.strictEqual((manager as any).registeredActionButtons.size, 1);
|
|
assert.strictEqual((manager as any).registeredActionButtons.get('testing-app').size, 1);
|
|
assert.strictEqual((manager as any).registeredActionButtons.get('testing-app').get('test-action'), button);
|
|
});
|
|
|
|
it('registerActionButtonWithoutPermission', () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => false);
|
|
notifyAboutErrorSpy.mock.mockImplementation(() => {});
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button: IUIActionButtonDescriptor = {
|
|
actionId: 'test-action',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label',
|
|
};
|
|
|
|
const result = manager.registerActionButton('testing-app', button);
|
|
|
|
assert.strictEqual(result, false);
|
|
assert.strictEqual(hasPermissionSpy.mock.calls.length, 1);
|
|
assert.deepStrictEqual(hasPermissionSpy.mock.calls[0].arguments, ['testing-app', AppPermissions.ui.registerButtons]);
|
|
assert.ok(notifyAboutErrorSpy.mock.calls.length > 0);
|
|
assert.strictEqual(doActionsChangedSpy.mock.calls.length, 0);
|
|
assert.strictEqual((manager as any).registeredActionButtons.size, 0);
|
|
});
|
|
|
|
it('registerMultipleButtonsForSameApp', () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button1: IUIActionButtonDescriptor = {
|
|
actionId: 'action-1',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label1',
|
|
};
|
|
const button2: IUIActionButtonDescriptor = {
|
|
actionId: 'action-2',
|
|
context: UIActionButtonContext.ROOM_ACTION,
|
|
labelI18n: 'test.label2',
|
|
};
|
|
|
|
manager.registerActionButton('testing-app', button1);
|
|
manager.registerActionButton('testing-app', button2);
|
|
|
|
assert.strictEqual((manager as any).registeredActionButtons.size, 1);
|
|
assert.strictEqual((manager as any).registeredActionButtons.get('testing-app').size, 2);
|
|
assert.strictEqual((manager as any).registeredActionButtons.get('testing-app').get('action-1'), button1);
|
|
assert.strictEqual((manager as any).registeredActionButtons.get('testing-app').get('action-2'), button2);
|
|
});
|
|
|
|
it('clearAppActionButtons', () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button: IUIActionButtonDescriptor = {
|
|
actionId: 'test-action',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label',
|
|
};
|
|
|
|
manager.registerActionButton('testing-app', button);
|
|
assert.strictEqual((manager as any).registeredActionButtons.get('testing-app').size, 1);
|
|
|
|
manager.clearAppActionButtons('testing-app');
|
|
|
|
assert.strictEqual((manager as any).registeredActionButtons.get('testing-app').size, 0);
|
|
assert.strictEqual(doActionsChangedSpy.mock.calls.length, 2);
|
|
});
|
|
|
|
it('getAppActionButtons', () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button: IUIActionButtonDescriptor = {
|
|
actionId: 'test-action',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label',
|
|
};
|
|
|
|
manager.registerActionButton('testing-app', button);
|
|
|
|
const buttons = manager.getAppActionButtons('testing-app');
|
|
assert.ok(buttons !== undefined);
|
|
assert.strictEqual(buttons?.size, 1);
|
|
assert.strictEqual(buttons?.get('test-action'), button);
|
|
|
|
const nonExistentButtons = manager.getAppActionButtons('non-existent');
|
|
assert.strictEqual(nonExistentButtons, undefined);
|
|
});
|
|
|
|
it('getAllActionButtonsFromEnabledApp', async () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
mock.method(mockApp, 'getStatus', () => Promise.resolve(AppStatus.AUTO_ENABLED));
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button: IUIActionButtonDescriptor = {
|
|
actionId: 'test-action',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label',
|
|
};
|
|
|
|
manager.registerActionButton('testing-app', button);
|
|
|
|
const allButtons = await manager.getAllActionButtons();
|
|
|
|
assert.ok(allButtons !== undefined);
|
|
assert.strictEqual(allButtons.length, 1);
|
|
assert.strictEqual(allButtons[0].actionId, 'test-action');
|
|
assert.strictEqual(allButtons[0].appId, 'testing-app');
|
|
assert.strictEqual(allButtons[0].context, UIActionButtonContext.MESSAGE_ACTION);
|
|
assert.strictEqual(allButtons[0].labelI18n, 'test.label');
|
|
});
|
|
|
|
it('getAllActionButtonsFromDisabledApp', async () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
mock.method(mockApp, 'getStatus', () => Promise.resolve(AppStatus.DISABLED));
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button: IUIActionButtonDescriptor = {
|
|
actionId: 'test-action',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label',
|
|
};
|
|
|
|
manager.registerActionButton('testing-app', button);
|
|
|
|
const allButtons = await manager.getAllActionButtons();
|
|
|
|
assert.ok(allButtons !== undefined);
|
|
assert.strictEqual(allButtons.length, 0);
|
|
});
|
|
|
|
it('getAllActionButtonsFromNonExistentApp', async () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button: IUIActionButtonDescriptor = {
|
|
actionId: 'test-action',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label',
|
|
};
|
|
|
|
manager.registerActionButton('non-existent-app', button);
|
|
|
|
const allButtons = await manager.getAllActionButtons();
|
|
|
|
assert.ok(allButtons !== undefined);
|
|
assert.strictEqual(allButtons.length, 0);
|
|
});
|
|
|
|
it('getAllActionButtonsWithStatusError', async () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
mock.method(mockApp, 'getStatus', () => Promise.reject(new Error('Status error')));
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
const button: IUIActionButtonDescriptor = {
|
|
actionId: 'test-action',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label',
|
|
};
|
|
|
|
manager.registerActionButton('testing-app', button);
|
|
|
|
const allButtons = await manager.getAllActionButtons();
|
|
|
|
assert.ok(allButtons !== undefined);
|
|
assert.strictEqual(allButtons.length, 0);
|
|
});
|
|
|
|
it('getAllActionButtonsFromMultipleApps', async () => {
|
|
hasPermissionSpy.mock.mockImplementation(() => true);
|
|
|
|
const button1: IUIActionButtonDescriptor = {
|
|
actionId: 'action-1',
|
|
context: UIActionButtonContext.MESSAGE_ACTION,
|
|
labelI18n: 'test.label1',
|
|
};
|
|
const button2: IUIActionButtonDescriptor = {
|
|
actionId: 'action-2',
|
|
context: UIActionButtonContext.ROOM_ACTION,
|
|
labelI18n: 'test.label2',
|
|
};
|
|
|
|
const manager = new UIActionButtonManager(mockManager);
|
|
|
|
manager.registerActionButton('testing-app', button1);
|
|
manager.registerActionButton('testing-app-2', button2);
|
|
|
|
const allButtons = await manager.getAllActionButtons();
|
|
|
|
assert.ok(allButtons !== undefined);
|
|
assert.strictEqual(allButtons.length, 2);
|
|
|
|
const app1Button = allButtons.find((b) => b.appId === 'testing-app');
|
|
const app2Button = allButtons.find((b) => b.appId === 'testing-app-2');
|
|
|
|
assert.ok(app1Button !== undefined);
|
|
assert.strictEqual(app1Button!.actionId, 'action-1');
|
|
assert.ok(app2Button !== undefined);
|
|
assert.strictEqual(app2Button!.actionId, 'action-2');
|
|
});
|
|
});
|