Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/meteor/client/views/room/Room/Room.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const Room = (): ReactElement => {
viewId={appsContextualBarContext.viewId}
roomId={appsContextualBarContext.roomId}
payload={appsContextualBarContext.payload}
appInfo={appsContextualBarContext.appInfo}
appId={appsContextualBarContext.appId}
/>
</ErrorBoundary>
</SelectedMessagesProvider>
Expand Down
6 changes: 3 additions & 3 deletions apps/meteor/client/views/room/contextualBar/Apps/Apps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ type AppsProps = {
onSubmit: (e: any) => void;
onCancel: (e: any) => Promise<void>;
onClose: (e: any) => Promise<void>;
appInfo: { name: string; id: string };
appId: string;
};

const Apps = ({ view, onSubmit, onClose, onCancel, appInfo }: AppsProps): JSX.Element => (
const Apps = ({ view, onSubmit, onClose, onCancel, appId }: AppsProps): JSX.Element => (
<>
<VerticalBar.Header>
<Avatar url={getURL(`/api/apps/${appInfo.id}/icon`)} />
<Avatar url={getURL(`/api/apps/${appId}/icon`)} />
<VerticalBar.Text>{modalParser.text(view.title)}</VerticalBar.Text>
{onClose && <VerticalBar.Close onClick={onClose} />}
</VerticalBar.Header>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { kitContext } from '@rocket.chat/fuselage-ui-kit';
import React, { memo, useState, useEffect, useReducer, Dispatch, SyntheticEvent, ContextType } from 'react';

import { triggerBlockAction, triggerCancel, triggerSubmitView, on, off } from '../../../../../app/ui-message/client/ActionManager';
import { App } from '../../../admin/apps/types';
import { useTabBarClose } from '../../providers/ToolboxProvider';
import Apps from './Apps';

Expand Down Expand Up @@ -93,16 +92,15 @@ const AppsWithData = ({
viewId,
roomId,
payload,
appInfo,
appId,
}: {
viewId: string;
roomId: string;
payload: IUIKitContextualBarInteraction;
appInfo: App;
appId: string;
}): JSX.Element => {
const closeTabBar = useTabBarClose();

const { id: appId, name: appName } = appInfo;
const [state, setState] = useState<ViewState>(payload);
const { view } = state;
const [values, updateValues] = useValues(view);
Expand Down Expand Up @@ -231,7 +229,7 @@ const AppsWithData = ({

return (
<kitContext.Provider value={context}>
<Apps onClose={handleClose} onCancel={handleCancel} onSubmit={handleSubmit} view={view} appInfo={{ name: appName, id: appId }} />
<Apps onClose={handleClose} onCancel={handleCancel} onSubmit={handleSubmit} view={view} appId={appId} />
</kitContext.Provider>
);
};
Expand Down
19 changes: 6 additions & 13 deletions apps/meteor/client/views/room/hooks/useAppsContextualBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,46 @@ import { IUIKitContextualBarInteraction } from '@rocket.chat/apps-engine/definit
import { useCurrentRoute } from '@rocket.chat/ui-contexts';
import { useEffect, useState } from 'react';

import { Apps } from '../../../../app/apps/client/orchestrator';
import { getUserInteractionPayloadByViewId } from '../../../../app/ui-message/client/ActionManager';
import { App } from '../../admin/apps/types';
import { useRoom } from '../contexts/RoomContext';

type AppsContextualBarData = {
viewId: string;
roomId: string;
payload: IUIKitContextualBarInteraction;
appInfo: App;
appId: string;
};

export const useAppsContextualBar = (): AppsContextualBarData | undefined => {
const [, params] = useCurrentRoute();
const [payload, setPayload] = useState<IUIKitContextualBarInteraction>();
const [appInfo, setAppInfo] = useState<App>();
const [appId, setAppId] = useState<string>();

const { _id: roomId } = useRoom();

const viewId = params?.context;

useEffect(() => {
async function getAppData(appId: string): Promise<void> {
const app = await Apps.getApp(appId);
setAppInfo(app);
}

if (viewId) {
setPayload(getUserInteractionPayloadByViewId(viewId) as IUIKitContextualBarInteraction);
}

if (payload?.appId) {
getAppData(payload.appId);
setAppId(payload.appId);
}

return (): void => {
setPayload(undefined);
setAppInfo(undefined);
setAppId(undefined);
};
}, [viewId, payload?.appId]);

if (viewId && payload && appInfo) {
if (viewId && payload && appId) {
return {
viewId,
roomId,
payload,
appInfo,
appId,
};
}

Expand Down
41 changes: 41 additions & 0 deletions apps/meteor/tests/e2e/apps.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { expect, test } from './utils/test';
import { HomeChannel, AcrossPage } from './page-objects';
import { installTestApp, cleanupTesterApp } from './utils';

test.use({ storageState: 'user1-session.json' });

test.describe.parallel('Apps', () => {
let poHomeChannel: HomeChannel;
let acrossPage: AcrossPage;

test.beforeAll(async ({ api }) => {
await api.post('/settings/Apps_Framework_enabled', { value: true });
await api.post('/settings/Apps_Framework_Development_Mode', { value: true });
await installTestApp(api);
});

test.beforeEach(async ({ page }) => {
poHomeChannel = new HomeChannel(page);
acrossPage = new AcrossPage(page);

await page.goto('/home');
await poHomeChannel.sidenav.openChat('general');
});

test('expect allow user open app contextualbar', async () => {
await poHomeChannel.content.dispatchSlashCommand('/contextualbar');
await expect(acrossPage.btnVerticalBarClose).toBeVisible();
});

test('expect app contextualbar to be closed', async () => {
await poHomeChannel.content.dispatchSlashCommand('/contextualbar');
await acrossPage.btnVerticalBarClose.click();
await expect(acrossPage.btnVerticalBarClose).toBeHidden();
});

test.afterAll(async ({ api }) => {
await cleanupTesterApp(api);
await api.post('/settings/Apps_Framework_enabled', { value: false });
await api.post('/settings/Apps_Framework_Development_Mode', { value: false });
});
});
4 changes: 3 additions & 1 deletion apps/meteor/tests/e2e/config/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export const BASE_URL = process.env.BASE_URL ?? 'http://localhost:3000';

export const BASE_API_URL = `${BASE_URL}/api/v1`;
export const API_PREFIX = '/api/v1';

export const BASE_API_URL = BASE_URL + API_PREFIX;

export const IS_LOCALHOST = BASE_URL.startsWith('http://localhost');

Expand Down
13 changes: 13 additions & 0 deletions apps/meteor/tests/e2e/page-objects/across-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Locator, Page } from '@playwright/test';

export class AcrossPage {
private readonly page: Page;

constructor(page: Page) {
this.page = page;
}

get btnVerticalBarClose(): Locator {
return this.page.locator('[data-qa="VerticalBarActionClose"]');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export class HomeContent {
await this.page.keyboard.press('Enter');
}

async dispatchSlashCommand(text: string): Promise<void> {
await this.page.locator('[name="msg"]').type(text);
await this.page.keyboard.press('Enter');
await this.page.keyboard.press('Enter');
}

get btnModalCancel(): Locator {
return this.page.locator('#modal-root .rcx-button-group--align-end .rcx-button--secondary');
}
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/tests/e2e/page-objects/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './account-profile';
export * from './across-page';
export * from './admin';
export * from './auth';
export * from './home-channel';
Expand Down
5 changes: 5 additions & 0 deletions apps/meteor/tests/e2e/utils/apps/apps-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const APP_URL = 'https://github.com/RocketChat/Apps.RocketChat.Tester/blob/master/dist/appsrocketchattester_0.0.5.zip?raw=true';
export const APP_ID = 'bc4dd4a1-bf9b-408e-83a4-aba7eba0bf02';
export const APP_NAME = 'Apps.RocketChat.Tester';
export const APP_USERNAME = 'appsrocketchattester.bot';
export const appsEndpoint = (path = '') => `/api/apps${path}`;
12 changes: 12 additions & 0 deletions apps/meteor/tests/e2e/utils/apps/cleanup-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { APP_ID } from './apps-data';
import type { BaseTest } from '../test';
import { removeAppById } from './remove-app';

/**
* cleanupApp:
* - This helper remove the tester app from the workspace
*/

export const cleanupTesterApp = async (api: BaseTest['api']) => {
await removeAppById(api, APP_ID);
};
3 changes: 3 additions & 0 deletions apps/meteor/tests/e2e/utils/apps/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './install-test-app';
export * from './remove-app';
export * from './cleanup-app';
11 changes: 11 additions & 0 deletions apps/meteor/tests/e2e/utils/apps/install-test-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { BaseTest } from '../test';
import { appsEndpoint, APP_URL } from './apps-data';

/**
* installTestApp:
* - Usefull to test apps functionalities
*/

export async function installTestApp(api: BaseTest['api']): Promise<void> {
await api.post(appsEndpoint(), { url: APP_URL }, '');
}
11 changes: 11 additions & 0 deletions apps/meteor/tests/e2e/utils/apps/remove-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { BaseTest } from '../test';
import { appsEndpoint } from './apps-data';

/**
* removeAppById:
* - This helper remove the desirable app from the workspace
*/

export const removeAppById = async (api: BaseTest['api'], id: string) => {
await api.delete(appsEndpoint(`/${id}`), '');
};
1 change: 1 addition & 0 deletions apps/meteor/tests/e2e/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './create-target-channel';
export * from './create-aux-context';
export * from './apps';
26 changes: 13 additions & 13 deletions apps/meteor/tests/e2e/utils/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import { v4 as uuid } from 'uuid';
import type { APIResponse } from '@playwright/test';
import { test as baseTest } from '@playwright/test';

import { BASE_API_URL, ADMIN_CREDENTIALS } from '../config/constants';
import { BASE_API_URL, BASE_URL, API_PREFIX, ADMIN_CREDENTIALS } from '../config/constants';

const PATH_NYC_OUTPUT = path.join(process.cwd(), '.nyc_output');

export type AnyObj = { [key: string]: any };

export type BaseTest = {
api: {
get(uri: string): Promise<APIResponse>;
post(uri: string, data: AnyObj): Promise<APIResponse>;
put(uri: string, data: AnyObj): Promise<APIResponse>;
delete(uri: string): Promise<APIResponse>;
get(uri: string, prefix?: string): Promise<APIResponse>;
post(uri: string, data: AnyObj, prefix?: string): Promise<APIResponse>;
put(uri: string, data: AnyObj, prefix?: string): Promise<APIResponse>;
delete(uri: string, prefix?: string): Promise<APIResponse>;
};
};

Expand Down Expand Up @@ -61,17 +61,17 @@ export const test = baseTest.extend<BaseTest>({
};

await use({
get(uri: string) {
return request.get(BASE_API_URL + uri, { headers });
get(uri: string, prefix = API_PREFIX) {
return request.get(BASE_API_URL + prefix + uri, { headers });
},
post(uri: string, data: AnyObj) {
return request.post(BASE_API_URL + uri, { headers, data });
post(uri: string, data: AnyObj, prefix = API_PREFIX) {
return request.post(BASE_URL + prefix + uri, { headers, data });
},
put(uri: string, data: AnyObj) {
return request.put(BASE_API_URL + uri, { headers, data });
put(uri: string, data: AnyObj, prefix = API_PREFIX) {
return request.put(BASE_API_URL + prefix + uri, { headers, data });
},
delete(uri: string) {
return request.delete(BASE_API_URL + uri, { headers });
delete(uri: string, prefix = API_PREFIX) {
return request.delete(BASE_API_URL + prefix + uri, { headers });
},
});
},
Expand Down