159 lines
5.8 KiB
TypeScript
159 lines
5.8 KiB
TypeScript
/**
|
|
* DevSettings E2E Tests
|
|
*
|
|
* Covers: DevTools toggle, CDP switch, CDP URL display, MCP config collapse.
|
|
* Only visible in dev mode — gracefully skips when hidden.
|
|
* All operations via UI — zero invokeBridge, zero mock.
|
|
*/
|
|
|
|
import { test, expect } from '../../../fixtures';
|
|
import { goToSettings, waitForSettle, waitForClassChange } from '../../../helpers/navigation';
|
|
import { takeScreenshot } from '../../../helpers/screenshots';
|
|
import { ARCO_SWITCH } from '../../../helpers/selectors';
|
|
|
|
async function scrollToDevSettings(page: import('@playwright/test').Page): Promise<boolean> {
|
|
const btn = page.locator('button:has-text("DevTools")').first();
|
|
await btn.scrollIntoViewIfNeeded().catch(() => {});
|
|
return btn.isVisible({ timeout: 3_000 }).catch(() => false);
|
|
}
|
|
|
|
function devSection(page: import('@playwright/test').Page) {
|
|
const btn = page.locator('button:has-text("DevTools")').first();
|
|
return btn.locator('xpath=ancestor::div[contains(@class,"space-y-12px")]').first();
|
|
}
|
|
|
|
test.describe('DevSettings', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await goToSettings(page, 'system');
|
|
await waitForSettle(page);
|
|
});
|
|
|
|
test('TC-DEV-01: DevTools button is visible with correct label', async ({ page }) => {
|
|
const visible = await scrollToDevSettings(page);
|
|
if (!visible) {
|
|
test.skip(true, 'DevSettings not visible — not in dev mode');
|
|
return;
|
|
}
|
|
|
|
const btn = page.locator('button:has-text("DevTools")').first();
|
|
await expect(btn).toBeVisible();
|
|
const text = await btn.textContent();
|
|
expect(text).toBeTruthy();
|
|
expect(text).toMatch(/DevTools/i);
|
|
await takeScreenshot(page, 'dev-settings/tc-dev-01/01-visible.png');
|
|
});
|
|
|
|
test('TC-DEV-02: should toggle CDP switch', async ({ page }) => {
|
|
const visible = await scrollToDevSettings(page);
|
|
if (!visible) {
|
|
test.skip(true, 'DevSettings not visible — not in dev mode');
|
|
return;
|
|
}
|
|
|
|
const section = devSection(page);
|
|
const cdpSwitch = section.locator(ARCO_SWITCH).first();
|
|
await expect(cdpSwitch).toBeVisible();
|
|
const wasChecked = await cdpSwitch.evaluate((el) => el.classList.contains('arco-switch-checked'));
|
|
await takeScreenshot(page, 'dev-settings/tc-dev-02/01-before.png');
|
|
|
|
await cdpSwitch.click();
|
|
await waitForClassChange(cdpSwitch);
|
|
expect(await cdpSwitch.evaluate((el) => el.classList.contains('arco-switch-checked'))).toBe(!wasChecked);
|
|
await takeScreenshot(page, 'dev-settings/tc-dev-02/02-toggled.png');
|
|
|
|
await cdpSwitch.click();
|
|
await waitForClassChange(cdpSwitch);
|
|
expect(await cdpSwitch.evaluate((el) => el.classList.contains('arco-switch-checked'))).toBe(wasChecked);
|
|
await takeScreenshot(page, 'dev-settings/tc-dev-02/03-restored.png');
|
|
});
|
|
|
|
test('TC-DEV-03: should display CDP URL with port, Link and Copy buttons', async ({ page }) => {
|
|
const visible = await scrollToDevSettings(page);
|
|
if (!visible) {
|
|
test.skip(true, 'DevSettings not visible — not in dev mode');
|
|
return;
|
|
}
|
|
|
|
const section = devSection(page);
|
|
const cdpSwitch = section.locator(ARCO_SWITCH).first();
|
|
const wasChecked = await cdpSwitch.evaluate((el) => el.classList.contains('arco-switch-checked'));
|
|
if (!wasChecked) {
|
|
await cdpSwitch.click();
|
|
await waitForClassChange(cdpSwitch);
|
|
}
|
|
|
|
const portText = section.locator('text=/127\\.0\\.0\\.1:\\d+/').first();
|
|
const portVisible = await portText.isVisible({ timeout: 3_000 }).catch(() => false);
|
|
if (!portVisible) {
|
|
if (!wasChecked) {
|
|
await cdpSwitch.click();
|
|
await waitForClassChange(cdpSwitch);
|
|
}
|
|
test.skip(true, 'CDP port not available');
|
|
return;
|
|
}
|
|
|
|
await expect(portText).toBeVisible();
|
|
const urlRow = portText.locator('xpath=ancestor::div[contains(@class,"flex")]').first();
|
|
const btnCount = await urlRow.locator('button').count();
|
|
expect(btnCount).toBe(2);
|
|
await takeScreenshot(page, 'dev-settings/tc-dev-03/01-url-and-buttons.png');
|
|
|
|
if (!wasChecked) {
|
|
await cdpSwitch.click();
|
|
await waitForClassChange(cdpSwitch);
|
|
}
|
|
});
|
|
|
|
test('TC-DEV-04: should expand MCP config and show code block with Copy', async ({ page }) => {
|
|
const visible = await scrollToDevSettings(page);
|
|
if (!visible) {
|
|
test.skip(true, 'DevSettings not visible — not in dev mode');
|
|
return;
|
|
}
|
|
|
|
const section = devSection(page);
|
|
const cdpSwitch = section.locator(ARCO_SWITCH).first();
|
|
const wasChecked = await cdpSwitch.evaluate((el) => el.classList.contains('arco-switch-checked'));
|
|
if (!wasChecked) {
|
|
await cdpSwitch.click();
|
|
await waitForClassChange(cdpSwitch);
|
|
}
|
|
|
|
const collapseHeaders = section.locator('.arco-collapse-item-header');
|
|
const headerCount = await collapseHeaders.count().catch(() => 0);
|
|
if (headerCount === 0) {
|
|
if (!wasChecked) {
|
|
await cdpSwitch.click();
|
|
await waitForClassChange(cdpSwitch);
|
|
}
|
|
test.skip(true, 'MCP Collapse not available — CDP port may not be active');
|
|
return;
|
|
}
|
|
|
|
const firstHeader = collapseHeaders.first();
|
|
await expect(firstHeader).toBeVisible();
|
|
const copyBtn = firstHeader.locator('button').first();
|
|
await expect(copyBtn).toBeVisible();
|
|
await takeScreenshot(page, 'dev-settings/tc-dev-04/01-collapsed.png');
|
|
|
|
await firstHeader.click();
|
|
const preBlock = section.locator('pre').first();
|
|
await expect(preBlock).toBeVisible();
|
|
expect(await preBlock.textContent()).toContain('mcpServers');
|
|
await takeScreenshot(page, 'dev-settings/tc-dev-04/02-expanded.png');
|
|
|
|
await firstHeader.click();
|
|
await page
|
|
.waitForFunction((sel) => document.querySelector(sel)?.clientHeight === 0, '.arco-collapse-item-content', {
|
|
timeout: 3_000,
|
|
})
|
|
.catch(() => {});
|
|
|
|
if (!wasChecked) {
|
|
await cdpSwitch.click();
|
|
await waitForClassChange(cdpSwitch);
|
|
}
|
|
});
|
|
});
|