Files
sm-journal-plugin/tests/blogeditor/element.test.ts
Jakub Zych d5a5413525 test(16.2-06): pin the imported-post resave contract
- element.test.ts: an untouched value survives Source tab, tab buttons,
  preview and reattach byte for byte with no summer-change
- TestBlogEditorLoad: HTML verbatim, markdown as content_html, FormatHTML
  fallback, nil and empty values
- TestPostsAdminResaveKeepsHTML (Docker host): GET then PUT the served
  values for an HTML and a markdown post, exact bytes, no notices, then a
  clean edited save in both locales
2026-10-10 15:42:31 +02:00

111 lines
4.0 KiB
TypeScript

// The imported-post resave contract at the element layer (Phase 16.2 D-03,
// D-07; todo journal-imported-html-admin-resave): a value the administrator
// does not touch comes back as the exact served string, even after the
// Source tab and the preview were opened and closed, and the element
// announces nothing.
import { afterEach, describe, expect, it, vi } from 'vitest'
import fixture from './fixtures/imported-post.html?raw'
import { button, click, mount } from './helpers'
afterEach(() => {
vi.useRealTimers()
document.body.replaceChildren()
})
// What the server serves for a markdown post (D-07): its content_html, as
// goldmark rendered it at import, with the raw author footer and a trailing
// newline.
const markdownContentHTML =
'<h2>Nagłówek</h2>\n' +
'<p>Tekst z <em>kursywą</em> i <strong>pogrubieniem</strong>.</p>\n' +
'<ul>\n<li>jeden</li>\n<li>dwa</li>\n</ul>\n' +
'<blockquote>\n<p>Cytat</p>\n</blockquote>\n' +
'<p><a href="https://example.test/zrodlo">źródło</a></p>\n' +
'<footer class="author-footer" itemscope="" itemtype="https://schema.org/Person"><p>Autor</p></footer>\n'
const samples: [string, string][] = [
['the imported HTML post', fixture],
['a markdown post served as content_html', markdownContentHTML],
['HTML with leading white space and a comment', '\n <!-- imported -->\n<p>a&nbsp;b</p>\n'],
['an empty value', ''],
]
function tab(el: HTMLElement, name: 'wysiwyg' | 'source'): HTMLButtonElement {
const found = el.querySelector<HTMLButtonElement>(`button[data-tab="${name}"]`)
if (!found) throw new Error(`no ${name} tab`)
return found
}
describe('untouched value (D-03)', () => {
it.each(samples)('returns %s unchanged after a Source tab round trip', (_name, served) => {
const { el, changes } = mount(served)
expect(el.value).toBe(served)
el.showSource(true)
expect(el.querySelector('textarea')!.value).toBe(served)
expect(el.value).toBe(served)
el.showSource(false)
expect(el.value).toBe(served)
expect(changes).toEqual([])
})
it.each(samples)('returns %s unchanged after the tab buttons are clicked', (_name, served) => {
const { el, changes } = mount(served)
click(tab(el, 'source'))
expect(tab(el, 'source').getAttribute('aria-selected')).toBe('true')
click(tab(el, 'wysiwyg'))
click(tab(el, 'source'))
click(tab(el, 'wysiwyg'))
expect(tab(el, 'wysiwyg').getAttribute('aria-selected')).toBe('true')
expect(el.value).toBe(served)
expect(changes).toEqual([])
})
it.each(samples)('returns %s unchanged when the value is set after connect and echoed', (_name, served) => {
const { el, changes } = mount()
el.value = served
el.showSource(true)
el.showSource(false)
// The SPA writes the form value back only when it differs; an echo of
// the same string must change nothing.
el.value = el.value
expect(el.value).toBe(served)
expect(changes).toEqual([])
})
it('returns the imported post unchanged after the preview is opened and closed', () => {
vi.useFakeTimers()
const { el, changes } = mount(fixture)
click(button(el, 'preview'))
vi.advanceTimersByTime(1000)
click(button(el, 'preview'))
el.showSource(true)
el.showSource(false)
expect(el.value).toBe(fixture)
expect(changes).toEqual([])
})
it('returns the imported post unchanged after a detach and a new attach', () => {
const { el, changes } = mount(fixture)
el.remove()
expect(el.value).toBe(fixture)
document.body.append(el)
expect(el.value).toBe(fixture)
expect(changes).toEqual([])
})
it('reports an edit in the Source tab once and keeps the edited text exactly', () => {
const { el, changes } = mount(fixture)
el.showSource(true)
const textarea = el.querySelector('textarea')!
const edited = fixture.replace('</h2>', ' (edytowane)</h2>')
expect(edited).not.toBe(fixture)
textarea.value = edited
textarea.dispatchEvent(new Event('input'))
el.showSource(false)
expect(el.value).toBe(edited)
expect(changes).toEqual([edited])
})
})