fix: element tests drive the widget host protocol; the image element gets tests (WR-25)

The transfer element's busy and state=error handling is now tested
through the fake widget host, and golem15-seo-image gets tests for the
upload id matching, the error display, Remove and the disabled state.
The README's test gate runs npm test.
This commit is contained in:
2026-10-27 15:44:22 +01:00
parent 923d0f9c3a
commit 5c2ad6aee1
3 changed files with 135 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
import { afterEach, beforeAll, describe, expect, it } from 'vitest'
import { applyState, ROW_CAP, shownRows, type PreviewData, type PreviewRow } from '../../assets/src/elements/transfer'
import { labelsFor } from '../../assets/src/elements/labels'
import { HostFailure, mountWidget, settle } from './host'
// E6 golem15-seo-transfer (UI-SPEC C13): Apply is enabled only after a
// preview with no refused row and at least one change.
@@ -82,3 +83,50 @@ describe('E6 apply gating', () => {
expect(node.querySelector('.seo-transfer__actions')).toBeNull()
})
})
describe('E6 host protocol (WR-25)', () => {
function downloadButton(node: HTMLElement): HTMLButtonElement {
return node.querySelector<HTMLButtonElement>('.seo-transfer__section button')!
}
it('an export goes through the host and the buttons are busy until it settles', async () => {
const host = mountWidget('golem15-seo-transfer', {
attrs: { 'ui-locale': 'en', 'busy-label': 'Working…' },
answer: () => ({ op: 'export', filename: 'seo-redirects.csv', csv: 'source\n' }),
})
URL.createObjectURL = () => 'blob:x'
URL.revokeObjectURL = () => undefined
downloadButton(host.node).click()
expect(host.posted).toEqual([{ op: 'export', dataset: 'redirects' }])
expect(downloadButton(host.node).disabled).toBe(true)
expect(downloadButton(host.node).textContent).toBe('Working…')
downloadButton(host.node).click()
expect(host.emitted).toHaveLength(1)
await settle()
expect(downloadButton(host.node).disabled).toBe(false)
})
it('state=error unblocks the next request', async () => {
let fail = true
const host = mountWidget('golem15-seo-transfer', {
attrs: { 'ui-locale': 'en' },
answer: () => {
if (fail) {
fail = false
throw new HostFailure('export')
}
return { op: 'export', filename: 'seo-redirects.csv', csv: 'source\n' }
},
})
URL.createObjectURL = () => 'blob:x'
URL.revokeObjectURL = () => undefined
downloadButton(host.node).click()
await settle()
expect(host.node.getAttribute('state')).toBe('error')
expect(downloadButton(host.node).disabled).toBe(false)
downloadButton(host.node).click()
await settle()
expect(host.posted).toHaveLength(2)
})
})