@browsercore/testing 0.1.0

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 (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/dist/bench/bench.d.ts +21 -0
  4. package/dist/bench/bench.d.ts.map +1 -0
  5. package/dist/bench/bench.js +19 -0
  6. package/dist/bench/bench.js.map +1 -0
  7. package/dist/captures/manifest.d.ts +18 -0
  8. package/dist/captures/manifest.d.ts.map +1 -0
  9. package/dist/captures/manifest.js +62 -0
  10. package/dist/captures/manifest.js.map +1 -0
  11. package/dist/categories/capture.d.ts +8 -0
  12. package/dist/categories/capture.d.ts.map +1 -0
  13. package/dist/categories/capture.js +31 -0
  14. package/dist/categories/capture.js.map +1 -0
  15. package/dist/categories/compression.d.ts +8 -0
  16. package/dist/categories/compression.d.ts.map +1 -0
  17. package/dist/categories/compression.js +15 -0
  18. package/dist/categories/compression.js.map +1 -0
  19. package/dist/categories/cookies.d.ts +8 -0
  20. package/dist/categories/cookies.d.ts.map +1 -0
  21. package/dist/categories/cookies.js +20 -0
  22. package/dist/categories/cookies.js.map +1 -0
  23. package/dist/categories/errors.d.ts +11 -0
  24. package/dist/categories/errors.d.ts.map +1 -0
  25. package/dist/categories/errors.js +41 -0
  26. package/dist/categories/errors.js.map +1 -0
  27. package/dist/categories/http.d.ts +9 -0
  28. package/dist/categories/http.d.ts.map +1 -0
  29. package/dist/categories/http.js +46 -0
  30. package/dist/categories/http.js.map +1 -0
  31. package/dist/categories/index.d.ts +17 -0
  32. package/dist/categories/index.d.ts.map +1 -0
  33. package/dist/categories/index.js +17 -0
  34. package/dist/categories/index.js.map +1 -0
  35. package/dist/categories/redirects.d.ts +8 -0
  36. package/dist/categories/redirects.d.ts.map +1 -0
  37. package/dist/categories/redirects.js +21 -0
  38. package/dist/categories/redirects.js.map +1 -0
  39. package/dist/categories/regression.d.ts +8 -0
  40. package/dist/categories/regression.d.ts.map +1 -0
  41. package/dist/categories/regression.js +28 -0
  42. package/dist/categories/regression.js.map +1 -0
  43. package/dist/categories/session.d.ts +8 -0
  44. package/dist/categories/session.d.ts.map +1 -0
  45. package/dist/categories/session.js +23 -0
  46. package/dist/categories/session.js.map +1 -0
  47. package/dist/categories/tls.d.ts +10 -0
  48. package/dist/categories/tls.d.ts.map +1 -0
  49. package/dist/categories/tls.js +48 -0
  50. package/dist/categories/tls.js.map +1 -0
  51. package/dist/categories/transport.d.ts +8 -0
  52. package/dist/categories/transport.d.ts.map +1 -0
  53. package/dist/categories/transport.js +22 -0
  54. package/dist/categories/transport.js.map +1 -0
  55. package/dist/errors.d.ts +22 -0
  56. package/dist/errors.d.ts.map +1 -0
  57. package/dist/errors.js +28 -0
  58. package/dist/errors.js.map +1 -0
  59. package/dist/fingerprint/index.d.ts +5 -0
  60. package/dist/fingerprint/index.d.ts.map +1 -0
  61. package/dist/fingerprint/index.js +4 -0
  62. package/dist/fingerprint/index.js.map +1 -0
  63. package/dist/fingerprint/ja3.d.ts +36 -0
  64. package/dist/fingerprint/ja3.d.ts.map +1 -0
  65. package/dist/fingerprint/ja3.js +141 -0
  66. package/dist/fingerprint/ja3.js.map +1 -0
  67. package/dist/fingerprint/ja4.d.ts +109 -0
  68. package/dist/fingerprint/ja4.d.ts.map +1 -0
  69. package/dist/fingerprint/ja4.js +325 -0
  70. package/dist/fingerprint/ja4.js.map +1 -0
  71. package/dist/golden/golden.d.ts +45 -0
  72. package/dist/golden/golden.d.ts.map +1 -0
  73. package/dist/golden/golden.js +216 -0
  74. package/dist/golden/golden.js.map +1 -0
  75. package/dist/index.d.ts +25 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +25 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/reference/node-reference.d.ts +83 -0
  80. package/dist/reference/node-reference.d.ts.map +1 -0
  81. package/dist/reference/node-reference.js +161 -0
  82. package/dist/reference/node-reference.js.map +1 -0
  83. package/dist/reference/reference.d.ts +143 -0
  84. package/dist/reference/reference.d.ts.map +1 -0
  85. package/dist/reference/reference.js +323 -0
  86. package/dist/reference/reference.js.map +1 -0
  87. package/dist/rfc/rfcTests.d.ts +14 -0
  88. package/dist/rfc/rfcTests.d.ts.map +1 -0
  89. package/dist/rfc/rfcTests.js +22 -0
  90. package/dist/rfc/rfcTests.js.map +1 -0
  91. package/dist/types.d.ts +140 -0
  92. package/dist/types.d.ts.map +1 -0
  93. package/dist/types.js +34 -0
  94. package/dist/types.js.map +1 -0
  95. package/dist/utils.d.ts +29 -0
  96. package/dist/utils.d.ts.map +1 -0
  97. package/dist/utils.js +102 -0
  98. package/dist/utils.js.map +1 -0
  99. package/package.json +53 -0
package/dist/utils.js ADDED
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Small shared helpers for @browsercore/testing.
3
+ */
4
+ /**
5
+ * Exhaustiveness check for `switch`/`if-else` over discriminated unions.
6
+ * Call in the `default` branch: `default: assertNever(x)`.
7
+ * Adding a new union member forces every handler to compile-error until handled.
8
+ */
9
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
10
+ export function assertNever(x) {
11
+ throw new Error(`Unexpected value: ${JSON.stringify(x)}`);
12
+ }
13
+ /** Generate a unique TestCaseId (not cryptographically random). */
14
+ export function createId(prefix = "tc") {
15
+ return `${prefix}_${Date.now().toString(36)}_${Math.floor(Math.random() * 1e6).toString(36)}`;
16
+ }
17
+ /** Format bytes as a lowercase hex string with no separators. */
18
+ export function bytesToHex(buf) {
19
+ let out = "";
20
+ for (let i = 0; i < buf.length; i++) {
21
+ out += buf[i].toString(16).padStart(2, "0");
22
+ }
23
+ return out;
24
+ }
25
+ /**
26
+ * Compare two byte arrays. Returns a {@link ComparisonResult} reporting whether
27
+ * they match, the first divergence index (if any), and a message.
28
+ */
29
+ export function compareBytes(a, b) {
30
+ if (a.length !== b.length) {
31
+ return {
32
+ matches: false,
33
+ divergenceByteIndex: Math.min(a.length, b.length),
34
+ message: `Length mismatch: ${a.length} vs ${b.length}`,
35
+ };
36
+ }
37
+ for (let i = 0; i < a.length; i++) {
38
+ if (a[i] !== b[i]) {
39
+ return {
40
+ matches: false,
41
+ divergenceByteIndex: i,
42
+ message: `Byte ${i}: 0x${bytesToHex(a.subarray(i, i + 1))} vs 0x${bytesToHex(b.subarray(i, i + 1))}`,
43
+ };
44
+ }
45
+ }
46
+ return {
47
+ matches: true,
48
+ divergenceByteIndex: undefined,
49
+ message: "equal",
50
+ };
51
+ }
52
+ /**
53
+ * Compare two byte arrays while masking byte ranges that are intentionally
54
+ * randomized by the protocol spec (ephemeral keys, nonces, GREASE, random).
55
+ *
56
+ * Ranges in `ignore` are skipped when scanning for divergence. The returned
57
+ * {@link ComparisonResultWithIgnore.maskedReports} lists the ranges that were
58
+ * masked so callers can audit what was excluded.
59
+ */
60
+ export function compareBytesWithIgnore(a, b, ignore) {
61
+ // Defensive copy, sorted ascending so masking checks are O(log n) per byte.
62
+ const ranges = [...ignore].sort((x, y) => x.byteOffset - y.byteOffset);
63
+ const isMasked = (index) => {
64
+ for (const range of ranges) {
65
+ if (index < range.byteOffset)
66
+ return false;
67
+ if (index < range.byteOffset + range.length)
68
+ return true;
69
+ }
70
+ return false;
71
+ };
72
+ const maxLen = Math.max(a.length, b.length);
73
+ for (let i = 0; i < maxLen; i++) {
74
+ const inA = i < a.length;
75
+ const inB = i < b.length;
76
+ if (!inA || !inB) {
77
+ if (isMasked(i))
78
+ continue;
79
+ return {
80
+ matches: false,
81
+ divergenceByteIndex: i,
82
+ message: `Length divergence at byte ${i}: ${a.length} vs ${b.length}`,
83
+ maskedRanges: ranges,
84
+ };
85
+ }
86
+ if (a[i] !== b[i] && !isMasked(i)) {
87
+ return {
88
+ matches: false,
89
+ divergenceByteIndex: i,
90
+ message: `Byte ${i}: 0x${bytesToHex(a.subarray(i, i + 1))} vs 0x${bytesToHex(b.subarray(i, i + 1))}`,
91
+ maskedRanges: ranges,
92
+ };
93
+ }
94
+ }
95
+ return {
96
+ matches: true,
97
+ divergenceByteIndex: undefined,
98
+ message: "equal",
99
+ maskedRanges: ranges,
100
+ };
101
+ }
102
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@browsercore/testing",
3
+ "version": "0.1.0",
4
+ "description": "Protocol verification — RFC compliance tests, browser golden packet captures, integration tests, and benchmarking.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/jverneuer/browsercore-testing.git"
8
+ },
9
+ "homepage": "https://github.com/jverneuer/browsercore-testing#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/jverneuer/browsercore-testing/issues"
12
+ },
13
+ "license": "MIT",
14
+ "type": "module",
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": ["dist", "LICENSE", "README.md"],
24
+ "publishConfig": {
25
+ "access": "public",
26
+ "registry": "https://registry.npmjs.org/"
27
+ },
28
+ "scripts": {
29
+ "clean": "rm -rf dist",
30
+ "build": "tsc -p tsconfig.build.json",
31
+ "prepublishOnly": "npm run clean && npm run build",
32
+ "typecheck": "tsc -p tsconfig.json --noEmit",
33
+ "test": "vitest run"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.14.0",
37
+ "typescript": "^5.6.3",
38
+ "vitest": "^2.1.8"
39
+ },
40
+ "engines": {
41
+ "node": ">=24.0.0"
42
+ },
43
+ "dependencies": {
44
+ "@browsercore/cookies": "^0.1.0",
45
+ "@browsercore/crypto": "^0.1.0",
46
+ "@browsercore/fetch": "^0.1.0",
47
+ "@browsercore/http1": "^0.1.0",
48
+ "@browsercore/http2": "^0.1.0",
49
+ "@browsercore/profiles": "^0.1.0",
50
+ "@browsercore/tls": "^0.1.0",
51
+ "@browsercore/transport": "^0.1.0"
52
+ }
53
+ }