Files
apes-sidebar/tests/html-preview.spec.ts
T
figmar e5bbef1907 feat(sync): re-base the fork onto upstream dsh-better-sidebar v0.24.1 (fork 1.3.0)
Branch for hardware verification on a host that meets v0.24.1's peer range.

Base: upstream `dsh-better-sidebar` v0.24.1 (tag v0.24.1 = a2751cf), MIT.
Measured delta carried over from the v0.19.1 line: 78 rename-only files, 11 real
edits, 10 additions. Ported with the same measurement method as the v0.19.1
re-base: build a normalized base (upstream tree + the fork rename, excluding
README.md / package.json / docs/plans/* which deliberately keep the upstream
name), extract the delta against it, then three-way apply onto the renamed
v0.24.1 tree (`git apply -3`). 13 conflicts resolved by hand.

Identity:
- version 1.3.0, SIDEBAR_SERVICE_VERSION 1.3.0 (package.json ↔ service.ts pair
  is asserted by tests/service.spec.ts), forkedFrom -> v0.24.1/a2751cf.
- package.json keeps the union of both sides' metadata: upstream's new
  `zustand` + `icon`/`locale` files entries, plus the fork's `scripts/switch.sh`
  entry and its `forkedFrom` block.
- README.md takes upstream v0.24.1 wholesale (its own v0.24.1 changelog and all
  16 sections) and keeps the fork's two deltas: the fork-notice block at the top
  (now documenting the 0.2.0-rc.1+ requirement) and the fork package name.
- peerDependencies stay upstream's `^0.2.0-rc.1` — this line does NOT load on
  DSH 0.1.x: the host's semver pre-check rejects a caret range across a minor
  and silently disables the row (no error, no load).

Carried features, all re-verified against the new base:
- apes:* information-layer tabs (src/client/apes/) — the subtree's session feed
  changed shape in 0.1.7 and the port follows the host's own migration notes in
  context-types.ts: the per-session catalog is now
  `projectionsBySession[id].values.subagentCatalog` (a flat entry list) instead
  of 0.1.6's `subagentsByParent` catalog with `entries`/`kind`/`activity`, and
  the removed `list.current` is answered by `props.scope.sessionId`. Rows are
  normalized to { id, label, mode } with activity read from the durable
  summaries, so catalog and byId sources render alike.
- HTML preview delivery through srcdoc (sandbox kept intact).
- Panel host mounted inside the shell's framed content viewport.

Gate: typecheck clean; build clean; 1515 passed / 9 skipped (141 files).

NOT applied to ~/.dsh/profiles/desktop — that profile runs DSH 2.0.10 with
@deepseek-ai/dsh 0.1.5-rc.2, where this line is silently disabled by design.
2026-10-04 00:58:28 +08:00

52 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* HTML preview vocabulary tests: the srcdoc delivery path needs the previewed
* document's relative references to resolve back into its own
* `/sidebar/html/…` route (a srcdoc document has no URL of its own — the
* browser would otherwise resolve `./style.css` against the GUI page).
*
* Pure module, plain node environment.
*/
import { describe, expect, it } from 'vitest'
import { previewBaseOf, withPreviewBase } from '../src/client/html-preview.ts'
const URL_ = '/sidebar/html/s1/p/a/index.html'
describe('previewBaseOf', () => {
it('keeps everything up to the last slash', () => {
expect(previewBaseOf(URL_)).toBe('/sidebar/html/s1/p/a/')
})
it('keeps the UNC double slash intact (the route encodes it that way)', () => {
expect(previewBaseOf('/sidebar/html/s1//server/share/a.html')).toBe('/sidebar/html/s1//server/share/')
})
it('returns the input unchanged when it has no slash', () => {
expect(previewBaseOf('s1')).toBe('s1')
})
})
describe('withPreviewBase', () => {
it('injects the base as the first child of <head>, ahead of the document’s own elements', () => {
const out = withPreviewBase('<html><head><title>t</title></head><body></body></html>', URL_)
expect(out).toBe('<html><head><base href="/sidebar/html/s1/p/a/"><title>t</title></head><body></body></html>')
})
it('falls back to <html> when the document declares no head', () => {
const out = withPreviewBase('<html><body>x</body></html>', URL_)
expect(out).toBe('<html><base href="/sidebar/html/s1/p/a/"><body>x</body></html>')
})
it('prepends for a headless fragment', () => {
expect(withPreviewBase('<h1>x</h1>', URL_)).toBe('<base href="/sidebar/html/s1/p/a/"><h1>x</h1>')
})
it('leaves a document that declares its own base alone (the author owns it)', () => {
const doc = '<head><base href="https://example.com/"></head>'
expect(withPreviewBase(doc, URL_)).toBe(doc)
})
it('quotes the injected href', () => {
expect(withPreviewBase('<head></head>', '/x/"y/')).toBe('<head><base href="/x/&quot;y/"></head>')
})
})