mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-23 00:45:25 +08:00
119 lines
4.1 KiB
TypeScript
119 lines
4.1 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
|
import { installLangBotApiMocks } from './fixtures/langbot-api';
|
|
|
|
for (const cleanup of ['close', 'expiry'] as const) {
|
|
test(`QR start, polling and ${cleanup} cleanup retain the session Workspace`, async ({
|
|
page,
|
|
}) => {
|
|
await installLangBotApiMocks(page, { authenticated: true });
|
|
const calls: Array<{
|
|
method: string;
|
|
origin: string;
|
|
path: string;
|
|
workspace?: string;
|
|
authorization?: string;
|
|
}> = [];
|
|
const endpoint = '/api/v1/platform/adapters/weixin/login';
|
|
await page.route(`**${endpoint}**`, async (route) => {
|
|
const request = route.request();
|
|
const path = new URL(request.url()).pathname;
|
|
calls.push({
|
|
method: request.method(),
|
|
origin: new URL(request.url()).origin,
|
|
path,
|
|
workspace: request.headers()['x-workspace-id'],
|
|
authorization: request.headers().authorization,
|
|
});
|
|
const data =
|
|
request.method() === 'POST'
|
|
? {
|
|
session_id: 'qr-session',
|
|
qr_url: 'https://scan.example/qr',
|
|
expire_at: Date.now() / 1000 + 8,
|
|
}
|
|
: { status: 'waiting' };
|
|
await route.fulfill({ json: { code: 0, data } });
|
|
});
|
|
await page.goto('/home/bots');
|
|
await expect(
|
|
page.getByRole('button', { name: 'Models', exact: true }),
|
|
).toBeVisible();
|
|
const modules = await page.evaluate(() => {
|
|
const resources = performance
|
|
.getEntriesByType('resource')
|
|
.map((entry) => entry.name);
|
|
return {
|
|
reactPath: resources.find((url) =>
|
|
new URL(url).pathname.endsWith('/react.js'),
|
|
)!,
|
|
domPath: resources.find((url) =>
|
|
new URL(url).pathname.endsWith('/react-dom_client.js'),
|
|
)!,
|
|
};
|
|
});
|
|
await page.clock.install();
|
|
await page.evaluate(async ({ reactPath, domPath }) => {
|
|
const reactModule = await import(reactPath);
|
|
const React = reactModule.default || reactModule;
|
|
const domModule = await import(domPath);
|
|
const { createRoot } = domModule.default || domModule;
|
|
const componentPath =
|
|
'/src/app/home/components/qrcode-login/QrCodeLoginDialog.tsx';
|
|
const { default: Dialog } = await import(componentPath);
|
|
const contextPath = '/src/app/infra/http/workspaceContext.ts';
|
|
(await import(contextPath)).setActiveWorkspaceUuid('qr-original');
|
|
const host = document.createElement('div');
|
|
document.body.appendChild(host);
|
|
function Harness() {
|
|
const [open, setOpen] = React.useState(true);
|
|
return React.createElement(Dialog, {
|
|
open,
|
|
onOpenChange: setOpen,
|
|
platform: 'weixin',
|
|
onSuccess: () => {},
|
|
});
|
|
}
|
|
createRoot(host).render(React.createElement(Harness));
|
|
}, modules);
|
|
await expect(page.getByRole('dialog').locator('img')).toBeVisible();
|
|
await page.evaluate(async () => {
|
|
const path = '/src/app/infra/http/workspaceContext.ts';
|
|
(await import(path)).setActiveWorkspaceUuid('qr-other');
|
|
});
|
|
await page.clock.runFor(3100);
|
|
await expect
|
|
.poll(() => calls.some((call) => call.method === 'GET'))
|
|
.toBe(true);
|
|
if (cleanup === 'close') await page.keyboard.press('Escape');
|
|
else await page.clock.runFor(6000);
|
|
await expect
|
|
.poll(() => calls.filter((call) => call.method === 'DELETE').length)
|
|
.toBe(1);
|
|
expect(calls).toEqual([
|
|
{
|
|
method: 'POST',
|
|
origin: new URL(page.url()).origin,
|
|
path: endpoint,
|
|
workspace: 'qr-original',
|
|
authorization: 'Bearer playwright-token',
|
|
},
|
|
...calls
|
|
.filter((call) => call.method === 'GET')
|
|
.map(() => ({
|
|
method: 'GET',
|
|
origin: new URL(page.url()).origin,
|
|
path: `${endpoint}/status/qr-session`,
|
|
workspace: 'qr-original',
|
|
authorization: 'Bearer playwright-token',
|
|
})),
|
|
{
|
|
method: 'DELETE',
|
|
origin: new URL(page.url()).origin,
|
|
path: `${endpoint}/qr-session`,
|
|
workspace: 'qr-original',
|
|
authorization: 'Bearer playwright-token',
|
|
},
|
|
]);
|
|
});
|
|
}
|