Skip to content
File

Blob: tests/worker/protocol/xml/parser.test.ts

typescript55 lines
1import { describe, expect, it } from "vitest";
2 
3import { parseICalendarBytes } from "@/worker/caldav/ical/parse";
4import { parseVCardBytes } from "@/worker/carddav/vcard";
5import { utf8ArrayBuffer } from "@tests/worker/helpers/bytes";
6import { extractDeadPropertyFragment } from "@/worker/xml/dead-props";
7import { parseSafeXml } from "@/worker/xml/parser";
8 
9describe("parser compatibility checks", () => {
10 it("preserves namespace URI and local name for dead property fragments", () => {
11 const fragment = extractDeadPropertyFragment('<x:favorite xmlns:x="urn:example:test">blue</x:favorite>');
12 expect(fragment).toEqual({
13 nsUri: "urn:example:test",
14 localName: "favorite",
15 xmlValue: '<x:favorite xmlns:x="urn:example:test">blue</x:favorite>',
16 });
17 });
18 
19 it("rejects unsafe entity declarations", () => {
20 expect(() => parseSafeXml("<!DOCTYPE x [<!ENTITY y 'z'>]><x>&y;</x>")).toThrow(
21 "Unsafe XML entity declarations are not accepted",
22 );
23 });
24 
25 it("rejects structurally hostile XML below the byte limit", () => {
26 const deep = `${"<x>".repeat(129)}${"</x>".repeat(129)}`;
27 expect(() => parseSafeXml(deep)).toThrow();
28 
29 const many = `<root>${"<x/>".repeat(50_001)}</root>`;
30 expect(() => parseSafeXml(many, 1_000_000)).toThrow("element count limit");
31 });
32 
33 it("imports bounded calendar and contact parsers in the Worker runtime", () => {
34 const calendar = [
35 "BEGIN:VCALENDAR",
36 "VERSION:2.0",
37 "PRODID:-//dab//parser-check//EN",
38 "BEGIN:VEVENT",
39 "UID:calendar-parser-check",
40 "DTSTAMP:20260521T000000Z",
41 "DTSTART:20260521T000000Z",
42 "END:VEVENT",
43 "END:VCALENDAR",
44 ].join("\r\n");
45 const contact = ["BEGIN:VCARD", "VERSION:4.0", "UID:contact-parser-check", "FN:Parser Check", "END:VCARD"].join(
46 "\r\n",
47 );
48 
49 expect(parseICalendarBytes(utf8ArrayBuffer(calendar), 4096, { maxYears: 1, maxInstances: 10 }).uid).toBe(
50 "calendar-parser-check",
51 );
52 expect(parseVCardBytes(utf8ArrayBuffer(contact), 4096).uid).toBe("contact-parser-check");
53 });
54});