- E8: the page and profile type options, an invalid currency - E9: the checking line with aria-busy, noRules per type, one queued request, the danger line and its recovery - E10: both lists capped at 10 - the parent select's value parsing, empty default and disabled state
92 lines
3.7 KiB
TypeScript
92 lines
3.7 KiB
TypeScript
import { afterEach, beforeAll, describe, expect, it } from 'vitest'
|
|
import { labelsFor } from '../../assets/src/elements/labels'
|
|
import { HostFailure, mountWidget, settle } from './host'
|
|
|
|
// E9 golem15-seo-graph (UI-SPEC C18): the checking line with aria-busy
|
|
// while the request runs, the noRules line per type without Google rules,
|
|
// at most one queued request, and the danger line that keeps the last
|
|
// graph. The first render and the 800 ms re-check are in schema.test.ts.
|
|
|
|
beforeAll(async () => {
|
|
await import('../../assets/src/elements/index')
|
|
})
|
|
|
|
afterEach(() => {
|
|
document.body.replaceChildren()
|
|
})
|
|
|
|
const en = labelsFor('en')
|
|
|
|
const answer = {
|
|
locale: 'en',
|
|
url: 'https://example.test/x',
|
|
graph: { '@context': 'https://schema.org', '@graph': [] },
|
|
nodes: [
|
|
{ id: 'https://example.test/x#webpage', type: 'WebPage', rules: false, findings: [] },
|
|
{ id: 'https://example.test/x#service', type: 'Service', rules: false, findings: [] },
|
|
{ id: 'https://example.test/x#website', type: 'WebSite', rules: true, findings: [{ level: 'required', property: 'name' }] },
|
|
],
|
|
}
|
|
|
|
describe('E9 golem15-seo-graph states', () => {
|
|
it('shows the checking line and aria-busy while the request runs, neither after it', async () => {
|
|
const host = mountWidget('golem15-seo-graph', { attrs: { 'ui-locale': 'en' }, answer: () => answer })
|
|
await Promise.resolve()
|
|
expect(host.node.getAttribute('aria-busy')).toBe('true')
|
|
expect(host.node.querySelector('.seo-graph__checking')!.textContent).toBe(en.graphChecking)
|
|
await settle()
|
|
expect(host.node.getAttribute('aria-busy')).toBe('false')
|
|
expect(host.node.querySelector('.seo-graph__checking')).toBeNull()
|
|
})
|
|
|
|
it('writes one noRules line per node type without Google rules and the finding of the others', async () => {
|
|
const host = mountWidget('golem15-seo-graph', { attrs: { 'ui-locale': 'en' }, answer: () => answer })
|
|
await settle()
|
|
const text = host.node.textContent ?? ''
|
|
expect(text).toContain(en.noRules.replace(':type', 'WebPage'))
|
|
expect(text).toContain(en.noRules.replace(':type', 'Service'))
|
|
expect(text).not.toContain(en.noRules.replace(':type', 'WebSite'))
|
|
expect(text).toContain('Missing required property “name” (WebSite)')
|
|
expect(text).not.toContain(en.allGood)
|
|
})
|
|
|
|
it('queues at most one request while one runs', async () => {
|
|
const host = mountWidget('golem15-seo-graph', { attrs: { 'ui-locale': 'en' }, answer: () => answer })
|
|
await Promise.resolve()
|
|
const node = host.node as HTMLElement & { check(): void }
|
|
node.check()
|
|
node.check()
|
|
node.check()
|
|
await settle()
|
|
expect(host.posted).toHaveLength(2)
|
|
expect(host.node.getAttribute('aria-busy')).toBe('false')
|
|
})
|
|
|
|
it('shows the danger line on the first failure and clears it on the next success', async () => {
|
|
let fail = true
|
|
const host = mountWidget('golem15-seo-graph', {
|
|
attrs: { 'ui-locale': 'en' },
|
|
answer: () => {
|
|
if (fail) {
|
|
throw new HostFailure('down')
|
|
}
|
|
return answer
|
|
},
|
|
})
|
|
await settle()
|
|
expect(host.node.querySelector('.seo-graph__error')!.textContent).toBe(en.graphFailed)
|
|
expect(host.node.getAttribute('aria-busy')).toBe('false')
|
|
fail = false
|
|
host.node.querySelector<HTMLButtonElement>('.seo-graph__button')!.click()
|
|
await settle()
|
|
expect(host.node.querySelector('.seo-graph__error')).toBeNull()
|
|
expect(host.node.textContent).toContain('WebSite')
|
|
})
|
|
|
|
it('renders the Polish labels with ui-locale pl', async () => {
|
|
const host = mountWidget('golem15-seo-graph', { attrs: { 'ui-locale': 'pl' }, answer: () => ({ ...answer, nodes: [answer.nodes[0]] }) })
|
|
await settle()
|
|
expect(host.node.textContent).toContain(labelsFor('pl').noRules.replace(':type', 'WebPage'))
|
|
})
|
|
})
|