|
| 1 | +import { test, expect } from '@playwright/test' |
| 2 | + |
| 3 | +// Exercises ADR-0016 Phase B/C: integration-http's Method field is an |
| 4 | +// open TextInput with a datalist of suggestions, not a closed Select -- |
| 5 | +// any value (including RFC 10008's QUERY, not one of the old 5-item |
| 6 | +// list) is accepted and persists, over real Go bindings (Wails3 server |
| 7 | +// mode), not mocks. |
| 8 | + |
| 9 | +function workflowRow(page: import('@playwright/test').Page, label: string) { |
| 10 | + return page.locator('[data-testid="workflow-row"]', { has: page.getByText(label, { exact: true }) }) |
| 11 | +} |
| 12 | + |
| 13 | +function activePanel(page: import('@playwright/test').Page) { |
| 14 | + return page.locator('[role="tabpanel"]:not([hidden])') |
| 15 | +} |
| 16 | + |
| 17 | +async function dragPaletteItemToCanvas(page: import('@playwright/test').Page, nodeTypeID: string) { |
| 18 | + await page.evaluate((id) => { |
| 19 | + const panel = document.querySelector('[role="tabpanel"]:not([hidden])') |
| 20 | + if (!panel) throw new Error('no active tabpanel') |
| 21 | + const palette = panel.querySelector(`[data-node-type-id="${id}"]`) |
| 22 | + const canvas = panel.querySelector('.react-flow__pane') |
| 23 | + if (!palette || !canvas) { |
| 24 | + throw new Error(`drag setup failed: palette found=${!!palette} canvas found=${!!canvas}`) |
| 25 | + } |
| 26 | + const dataTransfer = new DataTransfer() |
| 27 | + const rect = canvas.getBoundingClientRect() |
| 28 | + const clientX = rect.x + rect.width / 2 |
| 29 | + const clientY = rect.y + rect.height / 2 |
| 30 | + palette.dispatchEvent(new DragEvent('dragstart', { bubbles: true, cancelable: true, dataTransfer })) |
| 31 | + canvas.dispatchEvent(new DragEvent('dragover', { bubbles: true, cancelable: true, dataTransfer, clientX, clientY })) |
| 32 | + canvas.dispatchEvent(new DragEvent('drop', { bubbles: true, cancelable: true, dataTransfer, clientX, clientY })) |
| 33 | + }, nodeTypeID) |
| 34 | +} |
| 35 | + |
| 36 | +async function deleteStarterNode(page: import('@playwright/test').Page) { |
| 37 | + await activePanel(page).locator('.react-flow__node').click() |
| 38 | + await activePanel(page).getByRole('button', { name: 'Delete selected' }).click() |
| 39 | + await expect(activePanel(page).locator('.react-flow__node')).toHaveCount(0) |
| 40 | +} |
| 41 | + |
| 42 | +test('The Method field accepts QUERY, an offered suggestion outside the old closed list, and persists it', async ({ page }) => { |
| 43 | + await page.goto('/') |
| 44 | + await page.getByRole('link', { name: 'Composition' }).click() |
| 45 | + await page.getByTestId('new-workflow').click() |
| 46 | + await deleteStarterNode(page) |
| 47 | + await activePanel(page).getByTestId('toggle-palette').click() |
| 48 | + |
| 49 | + await dragPaletteItemToCanvas(page, 'integration-http') |
| 50 | + await activePanel(page).locator('.react-flow__node').click() |
| 51 | + |
| 52 | + const inspector = activePanel(page).getByTestId('composition-inspector') |
| 53 | + const methodField = inspector.getByTestId('canvas-config-field').nth(1) |
| 54 | + |
| 55 | + // Not a closed Select -- a plain text input. |
| 56 | + await expect(methodField).toHaveJSProperty('tagName', 'INPUT') |
| 57 | + |
| 58 | + // QUERY is offered as a suggestion via the field's datalist, not |
| 59 | + // required to type blind. |
| 60 | + const listId = await methodField.getAttribute('list') |
| 61 | + expect(listId).toBeTruthy() |
| 62 | + const datalist = inspector.locator(`datalist#${listId}`) |
| 63 | + await expect(datalist.locator('option[value="QUERY"]')).toHaveCount(1) |
| 64 | + |
| 65 | + await methodField.fill('QUERY') |
| 66 | + await methodField.blur() |
| 67 | + |
| 68 | + // Save and reopen via Edit -- the real "did it persist in Node.Config, |
| 69 | + // not just left in the input's own local DOM state" proof, same |
| 70 | + // pattern composition.spec.ts's own save-then-reopen tests already |
| 71 | + // use, rather than a same-tab reselect (which the canvas toolbar's |
| 72 | + // top-left docking makes fiddly to click around). |
| 73 | + await activePanel(page).getByLabel('Label').fill('E2E QUERY method workflow') |
| 74 | + await activePanel(page).getByTestId('save-workflow').click() |
| 75 | + |
| 76 | + const row = workflowRow(page, 'E2E QUERY method workflow') |
| 77 | + await expect(row).toBeVisible() |
| 78 | + await row.getByRole('button', { name: /Edit/ }).click() |
| 79 | + await activePanel(page).locator('.react-flow__node').click() |
| 80 | + await expect(activePanel(page).getByTestId('canvas-config-field').nth(1)).toHaveValue('QUERY') |
| 81 | + |
| 82 | + await page.getByRole('tab', { name: 'Workflows' }).click() |
| 83 | + await row.getByRole('button', { name: /Delete/ }).click() |
| 84 | + await expect(row).toHaveCount(0) |
| 85 | +}) |
0 commit comments