mattrguerra/meridian-ops-boardmainPrivate on GitHub, published here in full

notes.test.ts

Language TypeScript1.8 KB40 lines

apps/worker/test/notes.test.ts

  1. /**
  2. * User notes ride into pre-rendered pages as serve-time JSON.
  3. *
  4. * The text is typed by a person and shared with everyone who opens the board,
  5. * which makes it the one string on this page an insider could aim at a
  6. * colleague's browser. The defence is layered: the page script renders notes
  7. * via textContent only, and this file pins the injection layer: a note
  8. * containing `</script>` must not be able to end the JSON tag and spill the
  9. * rest of itself into the document as markup.
  10. */
  11. import { describe, expect, it } from 'vitest'
  12. import { injectNotes, type BoardNote } from '../src/index.js'
  13. const PAGE = '<html><body><p>board</p></body></html>'
  14. const note = (text: string): Record<string, BoardNote> => ({
  15. 'order:MD2639640': { text, by: 'Rafael Montero', at: '2026-09-01T20:00:00.000Z' },
  16. })
  17. describe('injectNotes', () => {
  18. it('injects the notes as a JSON script tag before </body>', () => {
  19. const out = injectNotes(PAGE, note('waiting on the client to confirm colors'))
  20. expect(out).toContain('<script id="board-notes" type="application/json">')
  21. expect(out).toContain('waiting on the client to confirm colors')
  22. expect(out.indexOf('</body>')).toBeGreaterThan(out.indexOf('board-notes'))
  23. })
  24. it('a note containing </script> cannot break out of the tag', () => {
  25. const out = injectNotes(PAGE, note('</script><img src=x onerror=alert(1)>'))
  26. // Every `<` in the payload is \u003c-escaped, so the literal sequences the
  27. // parser would act on never appear.
  28. expect(out).not.toContain('</script><img')
  29. expect(out).toContain('\\u003c/script>')
  30. })
  31. it('no notes still injects an empty object, so the page script can tell "no notes" from "old worker"', () => {
  32. const out = injectNotes(PAGE, {})
  33. expect(out).toContain('type="application/json">{}</script>')
  34. })
  35. })