@browsercore/testing 0.1.3 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/README.md +5 -0
  2. package/bin/coverage-md.mjs +99 -0
  3. package/captures/DIVERGENCE_REPORT.md +325 -0
  4. package/captures/IMPERSIONATION_GAPS_REPORT.md +367 -0
  5. package/captures/README.md +56 -0
  6. package/captures/REVIEW_FINDINGS.md +71 -0
  7. package/captures/_probe/analyze.py +67 -0
  8. package/captures/_probe/capture_bytes.py +127 -0
  9. package/captures/_probe/chrome131_determinism.py +32 -0
  10. package/captures/_probe/diagnose_capture.py +59 -0
  11. package/captures/_probe/golden_analysis.py +91 -0
  12. package/captures/_probe/inspect_golden.py +55 -0
  13. package/captures/_probe/inspect_sv.py +16 -0
  14. package/captures/_probe/make_golden.py +170 -0
  15. package/captures/_probe/output/chrome100.json +219 -0
  16. package/captures/_probe/output/chrome101.json +219 -0
  17. package/captures/_probe/output/chrome104.json +219 -0
  18. package/captures/_probe/output/chrome107.json +220 -0
  19. package/captures/_probe/output/chrome110.json +220 -0
  20. package/captures/_probe/output/chrome116.json +220 -0
  21. package/captures/_probe/output/chrome119.json +219 -0
  22. package/captures/_probe/output/chrome120.json +219 -0
  23. package/captures/_probe/output/chrome123.json +223 -0
  24. package/captures/_probe/output/chrome124.json +224 -0
  25. package/captures/_probe/output/chrome131.json +224 -0
  26. package/captures/_probe/output/chrome131_fresh.json +224 -0
  27. package/captures/_probe/output/chrome133a.json +224 -0
  28. package/captures/_probe/output/chrome136.json +224 -0
  29. package/captures/_probe/output/chrome99.json +219 -0
  30. package/captures/_probe/output/edge101.json +219 -0
  31. package/captures/_probe/output/edge99.json +219 -0
  32. package/captures/_probe/output/firefox133.json +227 -0
  33. package/captures/_probe/output/firefox135.json +230 -0
  34. package/captures/_probe/output/safari155.json +210 -0
  35. package/captures/_probe/output/safari170.json +214 -0
  36. package/captures/_probe/output/safari170_fresh.json +214 -0
  37. package/captures/_probe/output/safari180.json +216 -0
  38. package/captures/_probe/output/safari180_ios.json +216 -0
  39. package/captures/_probe/output/safari184.json +215 -0
  40. package/captures/_probe/output/safari260.json +211 -0
  41. package/captures/_probe/output/summary.json +2520 -0
  42. package/captures/_probe/parse_existing_settings.py +15 -0
  43. package/captures/_probe/peetprint.py +39 -0
  44. package/captures/_probe/probe.py +137 -0
  45. package/captures/_probe/raw_bytes/chrome-131_client_hello.bin +0 -0
  46. package/captures/_probe/raw_bytes/chrome-131_client_hello.hex +32 -0
  47. package/captures/_probe/raw_bytes/firefox-133_client_hello.bin +0 -0
  48. package/captures/_probe/raw_bytes/firefox-133_client_hello.hex +32 -0
  49. package/captures/_probe/raw_bytes/safari-17_client_hello.bin +0 -0
  50. package/captures/_probe/raw_bytes/safari-17_client_hello.hex +32 -0
  51. package/captures/_probe/relay_capture.py +137 -0
  52. package/captures/_probe/socks_capture.py +138 -0
  53. package/captures/_probe/validate_fresh.py +66 -0
  54. package/captures/_probe/validate_golden.py +97 -0
  55. package/captures/_probe/verify_capture.py +68 -0
  56. package/captures/chrome-131/http2/settings.bin +0 -0
  57. package/captures/chrome-131/http2/settings.meta.json +9 -0
  58. package/captures/chrome-131/oracle_capture.reference.json +224 -0
  59. package/captures/chrome-131/tls/client_hello.bin +0 -0
  60. package/captures/chrome-131/tls/client_hello.meta.json +20 -0
  61. package/captures/chrome-140/http2/settings.bin +0 -0
  62. package/captures/chrome-140/http2/settings.meta.json +9 -0
  63. package/captures/chrome-140/tls/client_hello.bin +0 -0
  64. package/captures/chrome-140/tls/client_hello.meta.json +12 -0
  65. package/captures/firefox-128/tls/client_hello.bin +0 -0
  66. package/captures/firefox-128/tls/client_hello.meta.json +12 -0
  67. package/captures/firefox-133/http2/settings.bin +0 -0
  68. package/captures/firefox-133/http2/settings.meta.json +9 -0
  69. package/captures/firefox-133/oracle_capture.reference.json +227 -0
  70. package/captures/firefox-133/tls/client_hello.bin +0 -0
  71. package/captures/firefox-133/tls/client_hello.meta.json +20 -0
  72. package/captures/safari-17/http2/settings.bin +0 -0
  73. package/captures/safari-17/http2/settings.meta.json +9 -0
  74. package/captures/safari-17/oracle_capture.reference.json +214 -0
  75. package/captures/safari-17/tls/client_hello.bin +0 -0
  76. package/captures/safari-17/tls/client_hello.meta.json +20 -0
  77. package/captures/test-malformed/http2/settings.bin +0 -0
  78. package/captures/test-malformed/http2/settings.meta.json +9 -0
  79. package/captures/test-no-extensions/tls/client_hello.bin +0 -0
  80. package/captures/test-no-extensions/tls/client_hello.meta.json +9 -0
  81. package/captures/test-wrong-type/http2/settings.bin +0 -0
  82. package/captures/test-wrong-type/http2/settings.meta.json +9 -0
  83. package/dist/bench/bench.d.ts +24 -6
  84. package/dist/bench/bench.d.ts.map +1 -1
  85. package/dist/bench/bench.js +110 -10
  86. package/dist/bench/bench.js.map +1 -1
  87. package/dist/captures/manifest.d.ts.map +1 -1
  88. package/dist/captures/manifest.js +7 -7
  89. package/dist/captures/manifest.js.map +1 -1
  90. package/dist/categories/compression.d.ts +6 -4
  91. package/dist/categories/compression.d.ts.map +1 -1
  92. package/dist/categories/compression.js +56 -6
  93. package/dist/categories/compression.js.map +1 -1
  94. package/dist/categories/cookies.d.ts +3 -2
  95. package/dist/categories/cookies.d.ts.map +1 -1
  96. package/dist/categories/cookies.js +216 -11
  97. package/dist/categories/cookies.js.map +1 -1
  98. package/dist/categories/redirects.d.ts +8 -2
  99. package/dist/categories/redirects.d.ts.map +1 -1
  100. package/dist/categories/redirects.js +97 -12
  101. package/dist/categories/redirects.js.map +1 -1
  102. package/dist/e2e/cert-gen.d.ts +31 -0
  103. package/dist/e2e/cert-gen.d.ts.map +1 -0
  104. package/dist/e2e/cert-gen.js +158 -0
  105. package/dist/e2e/cert-gen.js.map +1 -0
  106. package/dist/e2e/parse-clienthello.d.ts +177 -0
  107. package/dist/e2e/parse-clienthello.d.ts.map +1 -0
  108. package/dist/e2e/parse-clienthello.js +343 -0
  109. package/dist/e2e/parse-clienthello.js.map +1 -0
  110. package/dist/e2e/sink-server.d.ts +109 -0
  111. package/dist/e2e/sink-server.d.ts.map +1 -0
  112. package/dist/e2e/sink-server.js +292 -0
  113. package/dist/e2e/sink-server.js.map +1 -0
  114. package/dist/e2e/traffic-server.d.ts +48 -0
  115. package/dist/e2e/traffic-server.d.ts.map +1 -0
  116. package/dist/e2e/traffic-server.js +162 -0
  117. package/dist/e2e/traffic-server.js.map +1 -0
  118. package/dist/errors.d.ts.map +1 -1
  119. package/dist/errors.js.map +1 -1
  120. package/dist/fingerprint/index.d.ts +5 -2
  121. package/dist/fingerprint/index.d.ts.map +1 -1
  122. package/dist/fingerprint/index.js +3 -2
  123. package/dist/fingerprint/index.js.map +1 -1
  124. package/dist/fingerprint/ja3.d.ts.map +1 -1
  125. package/dist/fingerprint/ja3.js +33 -4
  126. package/dist/fingerprint/ja3.js.map +1 -1
  127. package/dist/fingerprint/ja4-errors.d.ts +17 -0
  128. package/dist/fingerprint/ja4-errors.d.ts.map +1 -0
  129. package/dist/fingerprint/ja4-errors.js +20 -0
  130. package/dist/fingerprint/ja4-errors.js.map +1 -0
  131. package/dist/fingerprint/ja4-reader.d.ts +44 -0
  132. package/dist/fingerprint/ja4-reader.d.ts.map +1 -0
  133. package/dist/fingerprint/ja4-reader.js +112 -0
  134. package/dist/fingerprint/ja4-reader.js.map +1 -0
  135. package/dist/fingerprint/ja4.d.ts +11 -43
  136. package/dist/fingerprint/ja4.d.ts.map +1 -1
  137. package/dist/fingerprint/ja4.js +54 -141
  138. package/dist/fingerprint/ja4.js.map +1 -1
  139. package/dist/fingerprint/ja4h.d.ts +46 -0
  140. package/dist/fingerprint/ja4h.d.ts.map +1 -0
  141. package/dist/fingerprint/ja4h.js +50 -0
  142. package/dist/fingerprint/ja4h.js.map +1 -0
  143. package/dist/golden/golden.d.ts +15 -1
  144. package/dist/golden/golden.d.ts.map +1 -1
  145. package/dist/golden/golden.js +42 -28
  146. package/dist/golden/golden.js.map +1 -1
  147. package/dist/index.d.ts +21 -1
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +36 -1
  150. package/dist/index.js.map +1 -1
  151. package/dist/node-provider.d.ts +42 -0
  152. package/dist/node-provider.d.ts.map +1 -0
  153. package/dist/node-provider.js +53 -0
  154. package/dist/node-provider.js.map +1 -0
  155. package/dist/provider.d.ts +52 -0
  156. package/dist/provider.d.ts.map +1 -0
  157. package/dist/provider.js +14 -0
  158. package/dist/provider.js.map +1 -0
  159. package/dist/reference/browser-provider.d.ts +33 -0
  160. package/dist/reference/browser-provider.d.ts.map +1 -0
  161. package/dist/reference/browser-provider.js +61 -0
  162. package/dist/reference/browser-provider.js.map +1 -0
  163. package/dist/reference/curl-provider.d.ts +40 -0
  164. package/dist/reference/curl-provider.d.ts.map +1 -0
  165. package/dist/reference/curl-provider.js +96 -0
  166. package/dist/reference/curl-provider.js.map +1 -0
  167. package/dist/reference/dump.d.ts +42 -0
  168. package/dist/reference/dump.d.ts.map +1 -0
  169. package/dist/reference/dump.js +102 -0
  170. package/dist/reference/dump.js.map +1 -0
  171. package/dist/reference/node-crypto-provider.d.ts +31 -0
  172. package/dist/reference/node-crypto-provider.d.ts.map +1 -0
  173. package/dist/reference/node-crypto-provider.js +199 -0
  174. package/dist/reference/node-crypto-provider.js.map +1 -0
  175. package/dist/reference/node-reference.d.ts.map +1 -1
  176. package/dist/reference/node-reference.js +2 -5
  177. package/dist/reference/node-reference.js.map +1 -1
  178. package/dist/reference/reference-errors.d.ts +36 -0
  179. package/dist/reference/reference-errors.d.ts.map +1 -0
  180. package/dist/reference/reference-errors.js +43 -0
  181. package/dist/reference/reference-errors.js.map +1 -0
  182. package/dist/reference/reference-types.d.ts +33 -0
  183. package/dist/reference/reference-types.d.ts.map +1 -0
  184. package/dist/reference/reference-types.js +9 -0
  185. package/dist/reference/reference-types.js.map +1 -0
  186. package/dist/reference/reference.d.ts +14 -77
  187. package/dist/reference/reference.d.ts.map +1 -1
  188. package/dist/reference/reference.js +43 -207
  189. package/dist/reference/reference.js.map +1 -1
  190. package/dist/rfc/rfcTests.d.ts +46 -8
  191. package/dist/rfc/rfcTests.d.ts.map +1 -1
  192. package/dist/rfc/rfcTests.js +203 -16
  193. package/dist/rfc/rfcTests.js.map +1 -1
  194. package/dist/types.d.ts +2 -1
  195. package/dist/types.d.ts.map +1 -1
  196. package/dist/types.js.map +1 -1
  197. package/dist/utils.d.ts +3 -0
  198. package/dist/utils.d.ts.map +1 -1
  199. package/dist/utils.js +11 -5
  200. package/dist/utils.js.map +1 -1
  201. package/package.json +68 -55
@@ -1,19 +1,119 @@
1
1
  /**
2
2
  * Benchmark suite for protocol operations.
3
3
  *
4
- * Typed stubs for now — real benchmarks require live servers and the
5
- * underlying protocol stacks.
4
+ * Benchmarks here measure operations that need no live server — capture
5
+ * parsing, fingerprint computation, golden comparison, and compression
6
+ * round-trips — so they run in CI. Live TLS-handshake / HTTP/2-request
7
+ * benchmarks (which require a functional protocol stack + loopback server)
8
+ * remain a future addition; see docs/TEST-SUITE.md (Phase 10) for the full
9
+ * roadmap.
10
+ *
11
+ * Each benchmark runs `iterations` repetitions, collects per-iteration
12
+ * timings in microseconds, and reports p50/p95/p99 latency plus average
13
+ * throughput.
14
+ */
15
+ import { gunzipSync, gzipSync } from "node:zlib";
16
+ import { computeJa3, computeJa4 } from "../fingerprint/index.js";
17
+ import { compareBytes } from "../utils.js";
18
+ import { createFileSystem, createPath } from "../node-provider.js";
19
+ const fileSystem = createFileSystem();
20
+ const path = createPath();
21
+ const compression = {
22
+ gzip: (data) => new Uint8Array(gzipSync(data)),
23
+ gunzip: (data) => new Uint8Array(gunzipSync(data)),
24
+ };
25
+ const here = import.meta.dirname;
26
+ // src/bench -> package root -> captures/
27
+ const capturesDir = path.join(here, "..", "..", "captures");
28
+ /** Deterministic payload: byte[i] = i % 256 (reproducible, never random). */
29
+ function detBuffer(length) {
30
+ const bytes = new Uint8Array(length);
31
+ for (let i = 0; i < length; i++) {
32
+ bytes[i] = i % 256;
33
+ }
34
+ return bytes;
35
+ }
36
+ /** High-resolution timestamp in microseconds (browser-safe fallback). */
37
+ function nowUs() {
38
+ return performance.now() * 1000;
39
+ }
40
+ /**
41
+ * Run `fn` for `iterations` repetitions and return the per-iteration timings
42
+ * in microseconds, sorted ascending. The warm-up iteration is discarded to
43
+ * eliminate first-call JIT / cache effects.
6
44
  */
7
- /** Benchmark a single TLS handshake over `iterations` runs. */
8
- export function benchmarkTlsHandshake(_iterations, _options) {
9
- void _iterations;
45
+ function measure(iterations, fn) {
46
+ // Warm-up.
47
+ fn();
48
+ const timings = [];
49
+ for (let i = 0; i < iterations; i++) {
50
+ const start = nowUs();
51
+ fn();
52
+ timings.push(nowUs() - start);
53
+ }
54
+ timings.sort((a, b) => a - b);
55
+ return timings;
56
+ }
57
+ /** Read a percentile (0..1) from a sorted array of samples. */
58
+ export function percentile(sorted, p) {
59
+ if (sorted.length === 0) {
60
+ return 0;
61
+ }
62
+ const idx = Math.min(sorted.length - 1, Math.ceil(p * sorted.length) - 1);
63
+ return sorted[Math.max(0, idx)] ?? 0;
64
+ }
65
+ /**
66
+ * Benchmark the TLS ClientHello fingerprint computation (JA3 + JA4) over
67
+ * `iterations` runs against the chrome-140 golden capture. Reports
68
+ * p50/p95/p99 latency in milliseconds.
69
+ */
70
+ export function benchmarkTlsHandshake(iterations, _options) {
10
71
  void _options;
11
- throw new Error("not implemented — see PLAN.md");
72
+ // Load the chrome-140 golden capture once; the benchmark measures the
73
+ // parsing + fingerprinting cost, not the live handshake (which needs a
74
+ // functional TLS stack + loopback server — future work).
75
+ const bytes = fileSystem.readFileSync(path.join(capturesDir, "chrome-140", "tls", "client_hello.bin"));
76
+ const iters = Math.max(1, iterations);
77
+ const timings = measure(iters, () => {
78
+ computeJa3(bytes);
79
+ computeJa4(bytes);
80
+ });
81
+ const avgMs = timings.reduce((a, b) => a + b, 0) / timings.length / 1000;
82
+ return {
83
+ iterations: iters,
84
+ avgMs,
85
+ p50: percentile(timings, 0.5) / 1000,
86
+ p95: percentile(timings, 0.95) / 1000,
87
+ p99: percentile(timings, 0.99) / 1000,
88
+ };
12
89
  }
13
- /** Benchmark an HTTP/2 request round-trip over `iterations` runs. */
14
- export function benchmarkHttp2Request(_iterations, _options) {
15
- void _iterations;
90
+ /**
91
+ * Benchmark the golden-comparison path (load + byte-compare) over
92
+ * `iterations` runs. This exercises the Category 14 packet-capture
93
+ * comparison core. Reports p50/p95/p99 latency in milliseconds.
94
+ */
95
+ export function benchmarkHttp2Request(iterations, _options) {
16
96
  void _options;
17
- throw new Error("not implemented — see PLAN.md");
97
+ // The HTTP/2 SETTINGS frame is small and deterministic — ideal for
98
+ // repeated comparison benchmarking without a live server.
99
+ const bytes = fileSystem.readFileSync(path.join(capturesDir, "chrome-140", "http2", "settings.bin"));
100
+ const iters = Math.max(1, iterations);
101
+ // Pre-compress a payload for the compression round-trip sub-benchmark.
102
+ const payload = detBuffer(8192);
103
+ const compressed = compression.gzip(payload);
104
+ const timings = measure(iters, () => {
105
+ // Golden comparison path: compare the SETTINGS bytes against themselves.
106
+ compareBytes(bytes, bytes);
107
+ // Compression round-trip: representative of per-request work.
108
+ compression.gunzip(compressed);
109
+ });
110
+ const avgMs = timings.reduce((a, b) => a + b, 0) / timings.length / 1000;
111
+ return {
112
+ iterations: iters,
113
+ avgMs,
114
+ p50: percentile(timings, 0.5) / 1000,
115
+ p95: percentile(timings, 0.95) / 1000,
116
+ p99: percentile(timings, 0.99) / 1000,
117
+ };
18
118
  }
19
119
  //# sourceMappingURL=bench.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bench.js","sourceRoot":"","sources":["../../src/bench/bench.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,+DAA+D;AAC/D,MAAM,UAAU,qBAAqB,CACjC,WAAmB,EACnB,QAA6D;IAE7D,KAAK,WAAW,CAAC;IACjB,KAAK,QAAQ,CAAC;IACd,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;AACrD,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,qBAAqB,CACjC,WAAmB,EACnB,QAA4E;IAE5E,KAAK,WAAW,CAAC;IACjB,KAAK,QAAQ,CAAC;IACd,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"bench.js","sourceRoot":"","sources":["../../src/bench/bench.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/captures/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC9B;AAeD,eAAO,MAAM,QAAQ,EAAE,SAAS,YAAY,EA8C3C,CAAC"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/captures/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAU/C,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC9B;AAeD,eAAO,MAAM,QAAQ,EAAE,SAAS,YAAY,EA8C3C,CAAC"}
@@ -7,21 +7,21 @@
7
7
  * providers discover captures through this array rather than hard-coding paths
8
8
  * (no magic strings — see CODING_STANDARDS.md).
9
9
  */
10
- import { readFileSync } from "node:fs";
11
- import { fileURLToPath } from "node:url";
12
- import { dirname, join } from "node:path";
13
- const here = dirname(fileURLToPath(import.meta.url));
10
+ import { createFileSystem, createPath } from "../node-provider.js";
11
+ const fileSystem = createFileSystem();
12
+ const path = createPath();
13
+ const here = import.meta.dirname;
14
14
  // src/captures -> package root -> captures/
15
- const capturesDir = join(here, "..", "..", "captures");
15
+ const capturesDir = path.join(here, "..", "..", "captures");
16
16
  function id(s) {
17
17
  return s;
18
18
  }
19
19
  function entry(relativePath, meta) {
20
- const abs = join(capturesDir, relativePath);
20
+ const abs = path.join(capturesDir, relativePath);
21
21
  return {
22
22
  path: relativePath,
23
23
  meta,
24
- bytes: readFileSync(abs),
24
+ bytes: fileSystem.readFileSync(abs),
25
25
  };
26
26
  }
27
27
  export const captures = [
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/captures/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI1C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,4CAA4C;AAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AASvD,SAAS,EAAE,CAAC,CAAS;IACjB,OAAO,CAAc,CAAC;AAC1B,CAAC;AAED,SAAS,KAAK,CAAC,YAAoB,EAAE,IAAiB;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC5C,OAAO;QACH,IAAI,EAAE,YAAY;QAClB,IAAI;QACJ,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC;KAC3B,CAAC;AACN,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAA4B;IAC7C,KAAK,CACD,iCAAiC,EACjC;QACI,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC;QACzB,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,cAAc;QACtB,WAAW,EACP,yDAAyD;QAC7D,gBAAgB,EAAE;YACd,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;YAChD,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE;SAC1D;QACD,SAAS,EAAE,sBAAsB;KACpC,CACJ;IACD,KAAK,CACD,+BAA+B,EAC/B;QACI,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC;QACzB,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,UAAU;QAClB,WAAW,EACP,iEAAiE;QACrE,gBAAgB,EAAE,EAAE;QACpB,SAAS,EAAE,sBAAsB;KACpC,CACJ;IACD,KAAK,CACD,kCAAkC,EAClC;QACI,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC;QAC1B,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,cAAc;QACtB,WAAW,EACP,0DAA0D;QAC9D,gBAAgB,EAAE;YACd,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;YAChD,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE;SAC1D;QACD,SAAS,EAAE,sBAAsB;KACpC,CACJ;CACJ,CAAC"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/captures/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEnE,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;AACtC,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;AAE1B,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC;AACjC,4CAA4C;AAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAS5D,SAAS,EAAE,CAAC,CAAS;IACjB,OAAO,CAAc,CAAC;AAC1B,CAAC;AAED,SAAS,KAAK,CAAC,YAAoB,EAAE,IAAiB;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACjD,OAAO;QACH,IAAI,EAAE,YAAY;QAClB,IAAI;QACJ,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC;KACtC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAA4B;IAC7C,KAAK,CACD,iCAAiC,EACjC;QACI,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC;QACzB,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,cAAc;QACtB,WAAW,EACP,yDAAyD;QAC7D,gBAAgB,EAAE;YACd,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;YAChD,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE;SAC1D;QACD,SAAS,EAAE,sBAAsB;KACpC,CACJ;IACD,KAAK,CACD,+BAA+B,EAC/B;QACI,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC;QACzB,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,UAAU;QAClB,WAAW,EACP,iEAAiE;QACrE,gBAAgB,EAAE,EAAE;QACpB,SAAS,EAAE,sBAAsB;KACpC,CACJ;IACD,KAAK,CACD,kCAAkC,EAClC;QACI,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC;QAC1B,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,cAAc;QACtB,WAAW,EACP,0DAA0D;QAC9D,gBAAgB,EAAE;YACd,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;YAChD,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE;SAC1D;QACD,SAAS,EAAE,sBAAsB;KACpC,CACJ;CACJ,CAAC"}
@@ -2,10 +2,12 @@
2
2
  * Test Category 9 — Compression.
3
3
  *
4
4
  * Verify gzip, brotli, deflate decoding behavior matches the Node.js reference
5
- * oracle (`nodeZlib`). The system under test is `@browsercore/compression`;
6
- * `nodeZlib` is the spec reference for these primitive layers. See
7
- * docs/TEST-SUITE.md ("Test Category 9 — Compression") for full acceptance
8
- * criteria.
5
+ * oracle (`nodeZlib`). The system under test is a `CompressionProvider`
6
+ * implementation backed by node:zlib; `nodeZlib` is the spec reference for
7
+ * these primitive layers. The runtime implementation lives in browsersmith
8
+ * (Layer 5), so this repo exercises the `CompressionProvider` contract with a
9
+ * local Node-backed double. See docs/TEST-SUITE.md ("Test Category 9 —
10
+ * Compression") for full acceptance criteria.
9
11
  */
10
12
  export declare const CATEGORY_ID: "compression";
11
13
  //# sourceMappingURL=compression.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../src/categories/compression.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,eAAO,MAAM,WAAW,eAA2B,CAAC"}
1
+ {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../src/categories/compression.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkBH,eAAO,MAAM,WAAW,eAA2B,CAAC"}
@@ -2,17 +2,67 @@
2
2
  * Test Category 9 — Compression.
3
3
  *
4
4
  * Verify gzip, brotli, deflate decoding behavior matches the Node.js reference
5
- * oracle (`nodeZlib`). The system under test is `@browsercore/compression`;
6
- * `nodeZlib` is the spec reference for these primitive layers. See
7
- * docs/TEST-SUITE.md ("Test Category 9 — Compression") for full acceptance
8
- * criteria.
5
+ * oracle (`nodeZlib`). The system under test is a `CompressionProvider`
6
+ * implementation backed by node:zlib; `nodeZlib` is the spec reference for
7
+ * these primitive layers. The runtime implementation lives in browsersmith
8
+ * (Layer 5), so this repo exercises the `CompressionProvider` contract with a
9
+ * local Node-backed double. See docs/TEST-SUITE.md ("Test Category 9 —
10
+ * Compression") for full acceptance criteria.
9
11
  */
10
- import { deflateRawSync } from "node:zlib";
12
+ import { brotliCompressSync, brotliDecompressSync, deflateRawSync, deflateSync, gunzipSync, gzipSync, inflateRawSync, inflateSync, } from "node:zlib";
11
13
  import { describe, expect, it } from "vitest";
12
- import { compression, UnsupportedEncodingError, } from "@browsercore/compression";
14
+ import { UnsupportedEncodingError } from "@browsercore/compression";
13
15
  import { nodeZlib } from "../reference/node-reference.js";
14
16
  import { TestCategory } from "../types.js";
15
17
  export const CATEGORY_ID = TestCategory.Compression;
18
+ /**
19
+ * Local Node-backed `CompressionProvider` double. The production implementation
20
+ * lives in browsersmith; this repo exercises the contract against the Node
21
+ * reference oracle to validate the primitive behavior.
22
+ */
23
+ const compression = {
24
+ gzip(data) {
25
+ return new Uint8Array(gzipSync(data));
26
+ },
27
+ gunzip(data) {
28
+ return new Uint8Array(gunzipSync(data));
29
+ },
30
+ deflate(data) {
31
+ return new Uint8Array(deflateSync(data));
32
+ },
33
+ inflate(data) {
34
+ return new Uint8Array(inflateSync(data));
35
+ },
36
+ inflateRaw(data) {
37
+ return new Uint8Array(inflateRawSync(data));
38
+ },
39
+ brotliCompress(data) {
40
+ return new Uint8Array(brotliCompressSync(data));
41
+ },
42
+ brotliDecompress(data) {
43
+ return new Uint8Array(brotliDecompressSync(data));
44
+ },
45
+ decompress(data, encoding) {
46
+ switch (encoding) {
47
+ case "gzip":
48
+ return this.gunzip(data);
49
+ case "deflate": {
50
+ try {
51
+ return this.inflate(data);
52
+ }
53
+ catch {
54
+ return this.inflateRaw(data);
55
+ }
56
+ }
57
+ case "br":
58
+ return this.brotliDecompress(data);
59
+ case "identity":
60
+ return data;
61
+ default:
62
+ throw new UnsupportedEncodingError(`unsupported encoding: ${String(encoding)}`);
63
+ }
64
+ },
65
+ };
16
66
  /** Deterministic payload: byte[i] = i % 256 (reproducible, never random). */
17
67
  function detBuffer(length) {
18
68
  const bytes = new Uint8Array(length);
@@ -1 +1 @@
1
- {"version":3,"file":"compression.js","sourceRoot":"","sources":["../../src/categories/compression.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compression.js","sourceRoot":"","sources":["../../src/categories/compression.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Test Category 8 — Cookie Behavior.
3
3
  *
4
- * Verify cookie parsing and policy. See docs/TEST-SUITE.md
5
- * ("Test Category 8 — Cookie Behavior") for full acceptance criteria.
4
+ * Verify RFC 6265 cookie parsing and policy against the @browsercore/cookies
5
+ * implementation. See docs/TEST-SUITE.md ("Test Category 8 — Cookie Behavior")
6
+ * for the full acceptance criteria.
6
7
  */
7
8
  export declare const CATEGORY_ID: "cookie-behavior";
8
9
  //# sourceMappingURL=cookies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/categories/cookies.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,eAAO,MAAM,WAAW,mBAA8B,CAAC"}
1
+ {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/categories/cookies.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkBH,eAAO,MAAM,WAAW,mBAA8B,CAAC"}
@@ -1,20 +1,225 @@
1
1
  /**
2
2
  * Test Category 8 — Cookie Behavior.
3
3
  *
4
- * Verify cookie parsing and policy. See docs/TEST-SUITE.md
5
- * ("Test Category 8 — Cookie Behavior") for full acceptance criteria.
4
+ * Verify RFC 6265 cookie parsing and policy against the @browsercore/cookies
5
+ * implementation. See docs/TEST-SUITE.md ("Test Category 8 — Cookie Behavior")
6
+ * for the full acceptance criteria.
6
7
  */
7
- import { describe, it } from "vitest";
8
+ import { describe, expect, it } from "vitest";
9
+ import { createCookieJar, parseSetCookieHeader, cookieMatchesUrl, isExpired, normalizeDomain, defaultPath, sameSiteAllows, CookieParseError, } from "@browsercore/cookies";
8
10
  import { TestCategory } from "../types.js";
9
11
  export const CATEGORY_ID = TestCategory.CookieBehavior;
12
+ /** Build a {@link CookieUrl} for testing. */
13
+ function url(hostname, pathname, secure = false) {
14
+ return {
15
+ hostname,
16
+ pathname,
17
+ // The @browsercore/cookies Secure check compares protocol against
18
+ // "https:" (with trailing colon), matching the URL standard form.
19
+ protocol: secure ? "https:" : "http:",
20
+ };
21
+ }
22
+ /** Build a {@link SameSiteContext} for testing. */
23
+ function ctx(topLevelSite, isTopLevel = false) {
24
+ return { topLevelSite, isTopLevelNavigation: isTopLevel, method: "GET" };
25
+ }
10
26
  describe(CATEGORY_ID, () => {
11
- it.todo("cookie parsing");
12
- it.todo("cookie expiration");
13
- it.todo("Secure cookies");
14
- it.todo("HttpOnly cookies");
15
- it.todo("SameSite cookies");
16
- it.todo("domain matching");
17
- it.todo("path matching");
18
- it.todo("cookie ordering");
27
+ it("parses a Set-Cookie header into a Cookie object", () => {
28
+ const cookie = parseSetCookieHeader("session=abc123; Path=/; Secure; HttpOnly", url("example.com", "/"));
29
+ expect(cookie).not.toBeNull();
30
+ expect(cookie?.name).toBe("session");
31
+ expect(cookie?.value).toBe("abc123");
32
+ expect(cookie?.path).toBe("/");
33
+ expect(cookie?.secure).toBe(true);
34
+ expect(cookie?.httpOnly).toBe(true);
35
+ });
36
+ it("parses a Set-Cookie header with an explicit Domain", () => {
37
+ const cookie = parseSetCookieHeader("id=42; Domain=example.com", url("example.com", "/"));
38
+ expect(cookie).not.toBeNull();
39
+ expect(cookie?.domain).toBe("example.com");
40
+ });
41
+ it("parses a Set-Cookie header with Max-Age", () => {
42
+ const cookie = parseSetCookieHeader("prefs=dark; Max-Age=3600", url("example.com", "/"));
43
+ expect(cookie).not.toBeNull();
44
+ expect(cookie?.maxAge).toBe(3600);
45
+ });
46
+ it("parses a Set-Cookie header with SameSite", () => {
47
+ const lax = parseSetCookieHeader("a=1; SameSite=Lax", url("example.com", "/"));
48
+ expect(lax?.sameSite).toBe("Lax");
49
+ const strict = parseSetCookieHeader("a=1; SameSite=Strict", url("example.com", "/"));
50
+ expect(strict?.sameSite).toBe("Strict");
51
+ const none = parseSetCookieHeader("a=1; SameSite=None; Secure", url("example.com", "/"));
52
+ expect(none?.sameSite).toBe("None");
53
+ });
54
+ it("parses a Set-Cookie header with an explicit Expires", () => {
55
+ const cookie = parseSetCookieHeader("prefs=dark; Expires=Wed, 09 Jun 2021 10:18:14 GMT", url("example.com", "/"));
56
+ expect(cookie).not.toBeNull();
57
+ expect(cookie?.expires).toBeInstanceOf(Date);
58
+ });
59
+ it("throws CookieParseError for an empty Set-Cookie header", () => {
60
+ expect(() => parseSetCookieHeader("", url("example.com", "/"))).toThrow(CookieParseError);
61
+ });
62
+ it("parses 'Path=/; Secure' as a cookie named 'Path' with value '/'", () => {
63
+ // The parser is permissive: "Path=/; Secure" is treated as a cookie
64
+ // with name "Path" and value "/", plus the Secure attribute. This is
65
+ // technically a malformed Set-Cookie header, but the parser does not
66
+ // reject it — higher layers should validate before storing.
67
+ const cookie = parseSetCookieHeader("Path=/; Secure", url("example.com", "/"));
68
+ expect(cookie).not.toBeNull();
69
+ expect(cookie?.name).toBe("Path");
70
+ expect(cookie?.value).toBe("/");
71
+ expect(cookie?.secure).toBe(true);
72
+ });
73
+ it("rejects a cookie for a domain mismatch", () => {
74
+ // A cookie set for example.com must NOT match evil.com.
75
+ const cookie = parseSetCookieHeader("session=abc; Domain=example.com", url("example.com", "/"));
76
+ expect(cookie).not.toBeNull();
77
+ const evilUrl = url("evil.com", "/");
78
+ const result = cookieMatchesUrl(cookie, evilUrl);
79
+ expect(result.matched).toBe(false);
80
+ expect(result.reason).toBe("domain_mismatch");
81
+ });
82
+ it("matches a cookie to its own domain and subdomains", () => {
83
+ const cookie = parseSetCookieHeader("session=abc; Domain=example.com", url("example.com", "/"));
84
+ expect(cookie).not.toBeNull();
85
+ const c = cookie;
86
+ expect(cookieMatchesUrl(c, url("example.com", "/")).matched).toBe(true);
87
+ expect(cookieMatchesUrl(c, url("www.example.com", "/")).matched).toBe(true);
88
+ expect(cookieMatchesUrl(c, url("deep.sub.example.com", "/")).matched).toBe(true);
89
+ });
90
+ it("respects the Secure flag — no match over http", () => {
91
+ const cookie = parseSetCookieHeader("session=abc; Domain=example.com; Secure", url("example.com", "/"));
92
+ expect(cookie).not.toBeNull();
93
+ const c = cookie;
94
+ expect(cookieMatchesUrl(c, url("example.com", "/", false)).matched).toBe(false);
95
+ expect(cookieMatchesUrl(c, url("example.com", "/", true)).matched).toBe(true);
96
+ });
97
+ it("respects the Path attribute", () => {
98
+ const cookie = parseSetCookieHeader("session=abc; Domain=example.com; Path=/api", url("example.com", "/api"));
99
+ expect(cookie).not.toBeNull();
100
+ const c = cookie;
101
+ expect(cookieMatchesUrl(c, url("example.com", "/api")).matched).toBe(true);
102
+ expect(cookieMatchesUrl(c, url("example.com", "/api/v1")).matched).toBe(true);
103
+ expect(cookieMatchesUrl(c, url("example.com", "/other")).matched).toBe(false);
104
+ });
105
+ it("detects an expired cookie by Max-Age", () => {
106
+ const cookie = {
107
+ name: "sess",
108
+ value: "x",
109
+ domain: "example.com",
110
+ path: "/",
111
+ expires: undefined,
112
+ maxAge: -1, // expired
113
+ secure: false,
114
+ httpOnly: false,
115
+ sameSite: "Lax",
116
+ partitioned: false,
117
+ hostOnly: false,
118
+ creationTime: Date.now() - 10_000,
119
+ lastAccessTime: Date.now() - 10_000,
120
+ };
121
+ expect(isExpired(cookie, Date.now())).toBe(true);
122
+ });
123
+ it("detects a fresh cookie as not expired", () => {
124
+ const cookie = {
125
+ name: "sess",
126
+ value: "x",
127
+ domain: "example.com",
128
+ path: "/",
129
+ expires: undefined,
130
+ maxAge: 3600,
131
+ secure: false,
132
+ httpOnly: false,
133
+ sameSite: "Lax",
134
+ partitioned: false,
135
+ hostOnly: false,
136
+ creationTime: Date.now(),
137
+ lastAccessTime: Date.now(),
138
+ };
139
+ expect(isExpired(cookie, Date.now())).toBe(false);
140
+ });
141
+ it("normalizes a domain to lowercase and strips leading dot", () => {
142
+ expect(normalizeDomain("Example.COM")).toBe("example.com");
143
+ expect(normalizeDomain(".example.com")).toBe("example.com");
144
+ });
145
+ it("computes the default path from a request path", () => {
146
+ expect(defaultPath("/")).toBe("/");
147
+ expect(defaultPath("/foo/bar")).toBe("/foo");
148
+ expect(defaultPath("/foo/bar/baz")).toBe("/foo/bar");
149
+ });
150
+ it("SameSite=Strict blocks cross-site requests", () => {
151
+ const cookie = {
152
+ name: "sess",
153
+ value: "x",
154
+ domain: "example.com",
155
+ path: "/",
156
+ expires: undefined,
157
+ maxAge: undefined,
158
+ secure: false,
159
+ httpOnly: false,
160
+ sameSite: "Strict",
161
+ partitioned: false,
162
+ hostOnly: false,
163
+ creationTime: Date.now(),
164
+ lastAccessTime: Date.now(),
165
+ };
166
+ // Same-site → allowed.
167
+ expect(sameSiteAllows(cookie, url("example.com", "/"), ctx("example.com"))).toBe(true);
168
+ // Cross-site → blocked.
169
+ expect(sameSiteAllows(cookie, url("example.com", "/"), ctx("evil.com"))).toBe(false);
170
+ });
171
+ it("SameSite=Lax allows top-level navigations cross-site", () => {
172
+ const cookie = {
173
+ name: "sess",
174
+ value: "x",
175
+ domain: "example.com",
176
+ path: "/",
177
+ expires: undefined,
178
+ maxAge: undefined,
179
+ secure: false,
180
+ httpOnly: false,
181
+ sameSite: "Lax",
182
+ partitioned: false,
183
+ hostOnly: false,
184
+ creationTime: Date.now(),
185
+ lastAccessTime: Date.now(),
186
+ };
187
+ // Same-site → allowed.
188
+ expect(sameSiteAllows(cookie, url("example.com", "/"), ctx("example.com"))).toBe(true);
189
+ // Cross-site top-level navigation → allowed.
190
+ expect(sameSiteAllows(cookie, url("example.com", "/"), ctx("evil.com", true))).toBe(true);
191
+ });
192
+ it("createCookieJar stores and retrieves cookies", () => {
193
+ const jar = createCookieJar();
194
+ jar.setCookie("session=abc123; Path=/", url("example.com", "/"));
195
+ const target = url("example.com", "/");
196
+ const cookies = jar.getCookies(target);
197
+ expect(cookies.length).toBe(1);
198
+ expect(cookies[0]?.name).toBe("session");
199
+ expect(cookies[0]?.value).toBe("abc123");
200
+ });
201
+ it("cookie jar does not return cookies for unmatched domains", () => {
202
+ const jar = createCookieJar();
203
+ jar.setCookie("session=abc; Domain=example.com", url("example.com", "/"));
204
+ const cookies = jar.getCookies(url("other.com", "/"));
205
+ expect(cookies).toHaveLength(0);
206
+ });
207
+ it("cookie jar clears all cookies", () => {
208
+ const jar = createCookieJar();
209
+ jar.setCookie("a=1; Path=/", url("example.com", "/"));
210
+ jar.setCookie("b=2; Path=/", url("example.com", "/"));
211
+ jar.clear();
212
+ expect(jar.getCookies(url("example.com", "/"))).toHaveLength(0);
213
+ });
214
+ it("cookie jar serializes and deserializes", () => {
215
+ const jar = createCookieJar();
216
+ jar.setCookie("session=abc123; Path=/", url("example.com", "/"));
217
+ const json = jar.serialize();
218
+ const jar2 = createCookieJar();
219
+ jar2.deserialize(json);
220
+ const cookies = jar2.getCookies(url("example.com", "/"));
221
+ expect(cookies.length).toBe(1);
222
+ expect(cookies[0]?.name).toBe("session");
223
+ });
19
224
  });
20
225
  //# sourceMappingURL=cookies.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../src/categories/cookies.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC,cAAc,CAAC;AAEvD,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC1B,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAC7B,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC1B,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC5B,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC5B,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC3B,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACzB,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../src/categories/cookies.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,14 @@
1
1
  /**
2
2
  * Test Category 10 — Redirect Handling.
3
3
  *
4
- * Verify 301, 302, 303, 307, 308 behavior. See docs/TEST-SUITE.md
5
- * ("Test Category 10 — Redirect Handling") for full acceptance criteria.
4
+ * Verify 301, 302, 303, 307, 308 status codes are correctly classified as
5
+ * redirects, and that the method-rewriting rules for 303 (and historical 301/
6
+ * 302) are applied per RFC 7231. See docs/TEST-SUITE.md ("Test Category 10 —
7
+ * Redirect Handling") for full acceptance criteria.
8
+ *
9
+ * These tests exercise the pure redirect-classification logic (status code →
10
+ * is-redirect, method rewrite) that the HTTP layers use. End-to-end redirect
11
+ * following is tested in browsercore/e2e-redirect-compress.test.ts.
6
12
  */
7
13
  export declare const CATEGORY_ID: "redirect-handling";
8
14
  //# sourceMappingURL=redirects.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../src/categories/redirects.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,eAAO,MAAM,WAAW,qBAAgC,CAAC"}
1
+ {"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../src/categories/redirects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,eAAO,MAAM,WAAW,qBAAgC,CAAC"}