ElyMark: a failed editor is told, leaves nothing, and can rebuild (M-13)
A failed build removes its holder. When both editors fail, the page tells the app and keeps the text; the next mode request rebuilds it. mark-broken.mjs breaks the editors through setAttribute and checks the fallback, the told failures, no leftover holders and the rebuild. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0d4dd64640
commit
ca5ac5bb45
6 files changed
+112
-5
No files matched your search
@@ -0,0 +1,80 @@
|
||||
// ElyMark's page: a failed editor says so (M-13).
|
||||
import { createRequire } from 'node:module'
|
||||
import { existsSync } from 'node:fs'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url'
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), '../..')
|
||||
const page = join(root, 'engines/content/ely-mark/index.html')
|
||||
if (!existsSync(page)) {
|
||||
console.log('SKIP: no page; run scripts/build-mark-content.sh')
|
||||
process.exit(0)
|
||||
}
|
||||
let chromium
|
||||
try {
|
||||
;({ chromium } = createRequire(join(root, 'site/package.json'))('@playwright/test'))
|
||||
} catch {
|
||||
console.log('SKIP: no Playwright; run pnpm install in site')
|
||||
process.exit(0)
|
||||
}
|
||||
const fail = (why) => {
|
||||
console.error(`FAIL: ${why}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const browser = await chromium.launch()
|
||||
const tab = await browser.newPage()
|
||||
await tab.addInitScript(() => {
|
||||
window.asked = []
|
||||
window.elyQuery = ({ request, onSuccess }) => {
|
||||
window.asked.push(JSON.parse(request))
|
||||
onSuccess('')
|
||||
}
|
||||
// Setting a role throws; `spare` keeps CodeMirror's.
|
||||
const set = Element.prototype.setAttribute
|
||||
window.breaks = (spare) => {
|
||||
Element.prototype.setAttribute = function (name, value) {
|
||||
const kept = spare && this.classList.contains('cm-content')
|
||||
if (name === 'role' && !kept) throw new Error('broken')
|
||||
return set.call(this, name, value)
|
||||
}
|
||||
}
|
||||
window.mends = () => {
|
||||
Element.prototype.setAttribute = set
|
||||
}
|
||||
})
|
||||
await tab.goto(pathToFileURL(page).href)
|
||||
// What the app heard since the last look.
|
||||
let seen = 0
|
||||
const heard = async () => {
|
||||
await tab.waitForTimeout(800)
|
||||
const all = await tab.evaluate(() => window.asked.filter((a) => a.kind === 'shown' || a.kind === 'failed'))
|
||||
const fresh = all.slice(seen)
|
||||
seen = all.length
|
||||
return JSON.stringify(fresh)
|
||||
}
|
||||
const holders = () => tab.evaluate(() => document.querySelectorAll('#document > div').length)
|
||||
const shown = () => tab.evaluate(() => document.querySelector('#document .cm-content')?.textContent ?? '')
|
||||
const open = (mode) => tab.evaluate((mode) => window.ely.open('# Kept\n', mode, {}, 1, '', null), mode)
|
||||
|
||||
await tab.evaluate(() => window.breaks(true))
|
||||
await open('visual')
|
||||
const fell = JSON.stringify([{ kind: 'shown', mode: 'source', fallback: true, broke: 'Error' }])
|
||||
if ((await heard()) !== fell) fail('a broken visual editor did not fall back to source')
|
||||
if ((await shown()) !== '# Kept') fail(`the fallback shows ${JSON.stringify(await shown())}`)
|
||||
|
||||
await tab.evaluate(() => window.breaks(false))
|
||||
const failed = JSON.stringify([{ kind: 'failed', generation: 1, what: 'Error' }])
|
||||
for (let n = 0; n < 3; n++) {
|
||||
await open('visual')
|
||||
if ((await heard()) !== failed) fail(`two broken editors, try ${n}: the app was not told`)
|
||||
}
|
||||
if ((await holders()) !== 0) fail(`failed builds left ${await holders()} holders`)
|
||||
|
||||
await tab.evaluate(() => window.mends())
|
||||
await tab.evaluate(() => window.ely.mode('source'))
|
||||
const back = JSON.stringify([{ kind: 'shown', mode: 'source', fallback: false, broke: null }])
|
||||
if ((await heard()) !== back) fail('a mode after the failure did not rebuild')
|
||||
if ((await shown()) !== '# Kept' || (await holders()) !== 1) fail('the rebuilt editor lost the text')
|
||||
await browser.close()
|
||||
console.log('mark-broken: fallback, told failures, no leftover holders, a mode rebuilds')
|
||||
Reference in new issue
Block a user