54 lines
2.9 KiB
JavaScript
54 lines
2.9 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import {readFile} from 'node:fs/promises'
|
|
import {JSDOM} from '../../learner/node_modules/jsdom/lib/api.js'
|
|
|
|
let serial=0
|
|
async function page(run){
|
|
const html=await readFile(new URL('./index.html',import.meta.url),'utf8')
|
|
const dom=new JSDOM(html,{url:'http://127.0.0.1:5184/'})
|
|
globalThis.window=dom.window;globalThis.document=dom.window.document
|
|
dom.window.scrollTo=()=>{}
|
|
dom.window.HTMLElement.prototype.scrollIntoView=()=>{}
|
|
await import(`./app.mjs?test=${++serial}`)
|
|
const $=id=>document.getElementById(id)
|
|
try{await run($,dom.window)}finally{await new Promise(resolve=>setTimeout(resolve,120));dom.window.close()}
|
|
}
|
|
|
|
test('close preserves keyboard cursor: next arrow continues at the adjacent word',()=>page(($,w)=>{
|
|
const span=[...$('reader').children].find(n=>n.textContent==='workshop')
|
|
span.click();assert.equal($('term').textContent,'workshop')
|
|
$('close').click();assert.equal($('panel').hidden,true)
|
|
$('reader').dispatchEvent(new w.KeyboardEvent('keydown',{key:'ArrowRight',bubbles:true}))
|
|
assert.equal($('term').textContent,'before')
|
|
}))
|
|
test('native punctuation-only selection clears stale word and cannot save it',()=>page(async($,w)=>{
|
|
[...$('reader').children].find(n=>n.textContent==='curiosity').click()
|
|
const dot=[...$('reader').children].find(n=>n.textContent==='.')
|
|
const range=document.createRange();range.selectNodeContents(dot)
|
|
w.getSelection().removeAllRanges();w.getSelection().addRange(range)
|
|
document.dispatchEvent(new w.Event('selectionchange'))
|
|
await new Promise(resolve=>setTimeout(resolve,130))
|
|
assert.equal($('panel').hidden,true)
|
|
assert.equal($('reader').querySelectorAll('.selected').length,0)
|
|
}))
|
|
test('native selection maps DOM text through spans and expands to full token endpoints',()=>page(async($,w)=>{
|
|
const spans=[...$('reader').children]
|
|
const start=spans.find(n=>n.textContent==='Mira'),end=spans.find(n=>n.textContent==='workshop')
|
|
const range=document.createRange();range.setStart(start.firstChild,2);range.setEnd(end.firstChild,3)
|
|
w.getSelection().removeAllRanges();w.getSelection().addRange(range)
|
|
document.dispatchEvent(new w.Event('selectionchange'))
|
|
await new Promise(resolve=>setTimeout(resolve,130))
|
|
assert.equal($('term').textContent,'Mira opened the workshop')
|
|
const result=JSON.parse($('range-output').textContent)
|
|
assert.equal($('reader').textContent.slice(...result.utf16),result.text)
|
|
}))
|
|
test('explicit save updates repeated words; unsaved edits are discarded on close',()=>page(($)=>{
|
|
const words=[...$('reader').children].filter(n=>n.textContent==='curiosity')
|
|
words[0].click();$('meaning').value='虚构释义';$('save').click()
|
|
assert.ok(words.every(n=>n.classList.contains('learning')))
|
|
$('meaning').value='未保存修改';$('close').click();words[1].click()
|
|
assert.equal($('meaning').value,'虚构释义')
|
|
$('next').click();assert.equal($('panel').hidden,true)
|
|
}))
|