|
1 | | -import { mkdir, writeFile } from 'node:fs/promises' |
| 1 | +import { mkdir, readFile, writeFile } from 'node:fs/promises' |
2 | 2 | import { dirname, join } from 'node:path' |
3 | 3 | import { |
4 | 4 | type Browser, |
@@ -89,6 +89,10 @@ async function verifyClientMetadata(page: Page, path: string, title: string) { |
89 | 89 | 'content', |
90 | 90 | description ?? '' |
91 | 91 | ) |
| 92 | + await expect(page.locator('link[rel="alternate"][type="text/plain"]')).toHaveAttribute( |
| 93 | + 'href', |
| 94 | + `${canonicalOrigin}/llms.txt` |
| 95 | + ) |
92 | 96 | return { |
93 | 97 | path, |
94 | 98 | title: await page.title(), |
@@ -807,6 +811,99 @@ try { |
807 | 811 |
|
808 | 812 | const languageContext = await browser.newContext({ viewport: { width: 1440, height: 1000 } }) |
809 | 813 | try { |
| 814 | + await check( |
| 815 | + 'Later request variants stay selected and copy the chosen streaming example', |
| 816 | + async () => { |
| 817 | + const page = await languageContext.newPage() |
| 818 | + try { |
| 819 | + if (engine === 'chromium') |
| 820 | + await languageContext.grantPermissions(['clipboard-read', 'clipboard-write']) |
| 821 | + await open(page, '/api-reference/workflows/executeWorkflowV2') |
| 822 | + const picker = page.getByRole('button', { name: /^Request example:/ }) |
| 823 | + for (const language of ['Go', 'JavaScript']) { |
| 824 | + const label = `${language} — Request example 3` |
| 825 | + await picker.click() |
| 826 | + await page.getByRole('menuitemradio', { name: label, exact: true }).click() |
| 827 | + await expect(picker).toHaveAccessibleName(`Request example: ${label}`) |
| 828 | + const sample = page |
| 829 | + .getByRole('region', { name: 'Request', exact: true }) |
| 830 | + .filter({ visible: true }) |
| 831 | + .locator('code') |
| 832 | + await expect(sample).toContainText('stream') |
| 833 | + if (engine === 'chromium') { |
| 834 | + await page.getByRole('button', { name: 'Copy request', exact: true }).click() |
| 835 | + await expect |
| 836 | + .poll(() => page.evaluate(() => navigator.clipboard.readText())) |
| 837 | + .toBe(await sample.textContent()) |
| 838 | + } |
| 839 | + await picker.click() |
| 840 | + await expect( |
| 841 | + page.getByRole('menuitemradio', { name: label, exact: true }) |
| 842 | + ).toHaveAttribute('aria-checked', 'true') |
| 843 | + await page.keyboard.press('Escape') |
| 844 | + } |
| 845 | + } finally { |
| 846 | + await page.close() |
| 847 | + } |
| 848 | + } |
| 849 | + ) |
| 850 | + await check( |
| 851 | + 'MCP tabs with multiword labels retain accessible panel relationships', |
| 852 | + async () => { |
| 853 | + const page = await languageContext.newPage() |
| 854 | + try { |
| 855 | + await open(page, '/mcp/overview') |
| 856 | + for (const label of ['Claude Code', 'VS Code']) { |
| 857 | + const tab = page.getByRole('tab', { name: label, exact: true }) |
| 858 | + await tab.click() |
| 859 | + const id = await tab.getAttribute('aria-controls') |
| 860 | + expect(id).toBeTruthy() |
| 861 | + expect(id).not.toMatch(/\s/) |
| 862 | + const panel = page.locator(`[id="${id}"]`) |
| 863 | + await expect(panel).toBeVisible() |
| 864 | + await expect(panel).toHaveAccessibleName(label) |
| 865 | + } |
| 866 | + } finally { |
| 867 | + await page.close() |
| 868 | + } |
| 869 | + } |
| 870 | + ) |
| 871 | + await check( |
| 872 | + 'Workflow output copy, download and Markdown preserve typed data', |
| 873 | + async () => { |
| 874 | + const page = await languageContext.newPage() |
| 875 | + try { |
| 876 | + await languageContext.grantPermissions(['clipboard-read', 'clipboard-write']) |
| 877 | + await open(page, '/tables/using-in-workflows') |
| 878 | + const expected = { |
| 879 | + rows: [{ id: 'row_8f2c', data: { company: 'Acme', status: 'unprocessed' } }], |
| 880 | + rowCount: 1, |
| 881 | + totalCount: 42, |
| 882 | + } |
| 883 | + await page.getByRole('button', { name: 'Copy full output', exact: true }).click() |
| 884 | + await expect |
| 885 | + .poll(async () => JSON.parse(await page.evaluate(() => navigator.clipboard.readText()))) |
| 886 | + .toEqual(expected) |
| 887 | + const pending = page.waitForEvent('download') |
| 888 | + await page.getByRole('button', { name: 'Download full output', exact: true }).click() |
| 889 | + const download = await pending |
| 890 | + const file = await download.path() |
| 891 | + if (!file) throw new Error('Output download has no artifact') |
| 892 | + expect(JSON.parse(await readFile(file, 'utf8'))).toEqual(expected) |
| 893 | + const response = await page.request.get( |
| 894 | + new URL('/tables/using-in-workflows.md', target).href |
| 895 | + ) |
| 896 | + expect(response.ok()).toBe(true) |
| 897 | + const markdown = await response.text() |
| 898 | + const output = /Output from table1\s+```json\n([\s\S]*?)\n```/.exec(markdown)?.[1] |
| 899 | + expect(output).toBeTruthy() |
| 900 | + expect(JSON.parse(output ?? '')).toEqual(expected) |
| 901 | + } finally { |
| 902 | + await page.close() |
| 903 | + } |
| 904 | + }, |
| 905 | + engine === 'webkit' ? 'Clipboard readback requires Chromium permissions.' : undefined |
| 906 | + ) |
810 | 907 | await check('API language preference survives navigation and reload', async () => { |
811 | 908 | const page = await languageContext.newPage() |
812 | 909 | await open(page, '/api-reference/workflows/listWorkflows') |
@@ -958,6 +1055,7 @@ try { |
958 | 1055 | async () => { |
959 | 1056 | await legacy.addInitScript(() => { |
960 | 1057 | Object.defineProperty(window, 'ClipboardItem', { value: undefined }) |
| 1058 | + Object.defineProperty(AbortSignal, 'timeout', { value: undefined }) |
961 | 1059 | const write = navigator.clipboard.writeText.bind(navigator.clipboard) |
962 | 1060 | navigator.clipboard.writeText = (text) => { |
963 | 1061 | document.documentElement.dataset.clipboardActivation = String( |
|
0 commit comments