- 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
111 lines
4.0 KiB
TypeScript
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 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])
|
|
})
|
|
})
|