mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
test(client): close the merged-architecture coverage and jsdom gaps
- user-text.tsx enters ui-primitives' per-file 100% gate: replace three regex-guaranteed impossible ?? fallbacks with asserted captures, make the precedence sort a branch-free rank comparator, and pin the nested recall-label ordering and the no-basename quoted-path fallback with tests (100% statements/branches/functions locally). - assembled-boot stubs Range.prototype.getBoundingClientRect: jsdom has no Range geometry, and Lexical's selection reveal now reaches it in the built-graph lane after the architecture merge (the unhandled TypeError behind command-image-envelope and preview-boot).
This commit is contained in:
@@ -159,6 +159,13 @@ export function installAssembledBootEnv(): void {
|
||||
if (typeof Element.prototype.scrollIntoView !== 'function') {
|
||||
Element.prototype.scrollIntoView = () => {}
|
||||
}
|
||||
// jsdom implements no Range geometry either: Lexical's selection reveal
|
||||
// measures the caret with one after a programmatic edit settles focus.
|
||||
if (typeof Range.prototype.getBoundingClientRect !== 'function') {
|
||||
Range.prototype.getBoundingClientRect = () => ({
|
||||
top: 0, bottom: 0, left: 0, right: 0, width: 0, height: 0, x: 0, y: 0, toJSON: () => ({}),
|
||||
}) as DOMRect
|
||||
}
|
||||
beforeEach(() => {
|
||||
localStorage.clear()
|
||||
// The locale service derives its provisional locale from the browser and
|
||||
|
||||
@@ -41,7 +41,7 @@ export function projectUserText(text: string, sessionLabels: readonly string[]):
|
||||
end: wire.index + wire[0].length,
|
||||
label: wire[0],
|
||||
kind: 'session',
|
||||
display: wire[1] ?? '',
|
||||
display: wire[1] as string, // non-optional capture in SESSION_WIRE_RE
|
||||
})
|
||||
}
|
||||
for (const rawLabel of [...new Set(sessionLabels)].sort((a, b) => b.length - a.length)) {
|
||||
@@ -55,16 +55,16 @@ export function projectUserText(text: string, sessionLabels: readonly string[]):
|
||||
const re = /(^|\s)(\/[\w-]+|@"[^"\n]+"|@[^\s]+)/gu
|
||||
let m: RegExpExecArray | null
|
||||
while ((m = re.exec(text)) !== null) {
|
||||
const tokenStart = m.index + (m[1]?.length ?? 0)
|
||||
const rawLabel = m[2] ?? ''
|
||||
const tokenStart = m.index + (m[1] as string).length // (^|\s) captures '' at line start
|
||||
const rawLabel = m[2] as string // non-optional alternation capture
|
||||
const label = rawLabel.startsWith('@"')
|
||||
? rawLabel
|
||||
: rawLabel.replace(/[.,;:!?,。;:!?]+$/gu, '')
|
||||
if (label.length <= 1) continue
|
||||
ranges.push({ start: tokenStart, end: tokenStart + label.length, label, kind: 'plain' })
|
||||
}
|
||||
ranges.sort((a, b) => a.start - b.start
|
||||
|| (a.kind === b.kind ? b.end - a.end : a.kind === 'session' ? -1 : 1))
|
||||
const rankOf = (range: DecorationRange): number => range.kind === 'session' ? 0 : 1
|
||||
ranges.sort((a, b) => a.start - b.start || rankOf(a) - rankOf(b) || b.end - a.end)
|
||||
const parts: ReactNode[] = []
|
||||
let cursor = 0
|
||||
const pushPlain = (from: number, to: number): void => {
|
||||
|
||||
@@ -62,6 +62,19 @@ describe('projectUserText', () => {
|
||||
expect(host.textContent).toBe('用 /plan。 试试 @。')
|
||||
})
|
||||
|
||||
it('prefers the longer recall label when one nests inside another', () => {
|
||||
const host = project('@会话一 收尾', ['会话', '会话一'])
|
||||
const chips = [...host.querySelectorAll('[data-ref-chip="session"]')]
|
||||
expect(chips.map(c => c.textContent)).toEqual(['会话一'])
|
||||
expect(host.textContent).toBe('会话一 收尾')
|
||||
})
|
||||
|
||||
it('falls back to the raw quoted label when the path has no basename', () => {
|
||||
const host = project('看 @"/" 下面')
|
||||
const chip = host.querySelector('[data-ref-chip="file"]')!
|
||||
expect(chip.textContent).toBe('"/"')
|
||||
})
|
||||
|
||||
it('renders undecorated text as one inline run', () => {
|
||||
const host = project('纯文本,无引用')
|
||||
expect(host.querySelectorAll('div').length).toBe(0)
|
||||
|
||||
Reference in New Issue
Block a user