aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/undici/lib/mock/snapshot-utils.js
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
commit76cb9c2a39d477a64824a985ade40507e3bbade1 (patch)
tree41e997aa9c6f538d3a136af61dae9424db2005a9 /vanilla/node_modules/undici/lib/mock/snapshot-utils.js
parent819a39a21ac992b1393244a4c283bbb125208c69 (diff)
downloadneko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.gz
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.bz2
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.zip
feat(vanilla): add testing infrastructure and tests (NK-wjnczv)
Diffstat (limited to 'vanilla/node_modules/undici/lib/mock/snapshot-utils.js')
-rw-r--r--vanilla/node_modules/undici/lib/mock/snapshot-utils.js158
1 files changed, 158 insertions, 0 deletions
diff --git a/vanilla/node_modules/undici/lib/mock/snapshot-utils.js b/vanilla/node_modules/undici/lib/mock/snapshot-utils.js
new file mode 100644
index 0000000..a14b69c
--- /dev/null
+++ b/vanilla/node_modules/undici/lib/mock/snapshot-utils.js
@@ -0,0 +1,158 @@
+'use strict'
+
+const { InvalidArgumentError } = require('../core/errors')
+const { runtimeFeatures } = require('../util/runtime-features.js')
+
+/**
+ * @typedef {Object} HeaderFilters
+ * @property {Set<string>} ignore - Set of headers to ignore for matching
+ * @property {Set<string>} exclude - Set of headers to exclude from matching
+ * @property {Set<string>} match - Set of headers to match (empty means match
+ */
+
+/**
+ * Creates cached header sets for performance
+ *
+ * @param {import('./snapshot-recorder').SnapshotRecorderMatchOptions} matchOptions - Matching options for headers
+ * @returns {HeaderFilters} - Cached sets for ignore, exclude, and match headers
+ */
+function createHeaderFilters (matchOptions = {}) {
+ const { ignoreHeaders = [], excludeHeaders = [], matchHeaders = [], caseSensitive = false } = matchOptions
+
+ return {
+ ignore: new Set(ignoreHeaders.map(header => caseSensitive ? header : header.toLowerCase())),
+ exclude: new Set(excludeHeaders.map(header => caseSensitive ? header : header.toLowerCase())),
+ match: new Set(matchHeaders.map(header => caseSensitive ? header : header.toLowerCase()))
+ }
+}
+
+const crypto = runtimeFeatures.has('crypto')
+ ? require('node:crypto')
+ : null
+
+/**
+ * @callback HashIdFunction
+ * @param {string} value - The value to hash
+ * @returns {string} - The base64url encoded hash of the value
+ */
+
+/**
+ * Generates a hash for a given value
+ * @type {HashIdFunction}
+ */
+const hashId = crypto?.hash
+ ? (value) => crypto.hash('sha256', value, 'base64url')
+ : (value) => Buffer.from(value).toString('base64url')
+
+/**
+ * @typedef {(url: string) => boolean} IsUrlExcluded Checks if a URL matches any of the exclude patterns
+ */
+
+/** @typedef {{[key: Lowercase<string>]: string}} NormalizedHeaders */
+/** @typedef {Array<string>} UndiciHeaders */
+/** @typedef {Record<string, string|string[]>} Headers */
+
+/**
+ * @param {*} headers
+ * @returns {headers is UndiciHeaders}
+ */
+function isUndiciHeaders (headers) {
+ return Array.isArray(headers) && (headers.length & 1) === 0
+}
+
+/**
+ * Factory function to create a URL exclusion checker
+ * @param {Array<string| RegExp>} [excludePatterns=[]] - Array of patterns to exclude
+ * @returns {IsUrlExcluded} - A function that checks if a URL matches any of the exclude patterns
+ */
+function isUrlExcludedFactory (excludePatterns = []) {
+ if (excludePatterns.length === 0) {
+ return () => false
+ }
+
+ return function isUrlExcluded (url) {
+ let urlLowerCased
+
+ for (const pattern of excludePatterns) {
+ if (typeof pattern === 'string') {
+ if (!urlLowerCased) {
+ // Convert URL to lowercase only once
+ urlLowerCased = url.toLowerCase()
+ }
+ // Simple string match (case-insensitive)
+ if (urlLowerCased.includes(pattern.toLowerCase())) {
+ return true
+ }
+ } else if (pattern instanceof RegExp) {
+ // Regex pattern match
+ if (pattern.test(url)) {
+ return true
+ }
+ }
+ }
+
+ return false
+ }
+}
+
+/**
+ * Normalizes headers for consistent comparison
+ *
+ * @param {Object|UndiciHeaders} headers - Headers to normalize
+ * @returns {NormalizedHeaders} - Normalized headers as a lowercase object
+ */
+function normalizeHeaders (headers) {
+ /** @type {NormalizedHeaders} */
+ const normalizedHeaders = {}
+
+ if (!headers) return normalizedHeaders
+
+ // Handle array format (undici internal format: [name, value, name, value, ...])
+ if (isUndiciHeaders(headers)) {
+ for (let i = 0; i < headers.length; i += 2) {
+ const key = headers[i]
+ const value = headers[i + 1]
+ if (key && value !== undefined) {
+ // Convert Buffers to strings if needed
+ const keyStr = Buffer.isBuffer(key) ? key.toString() : key
+ const valueStr = Buffer.isBuffer(value) ? value.toString() : value
+ normalizedHeaders[keyStr.toLowerCase()] = valueStr
+ }
+ }
+ return normalizedHeaders
+ }
+
+ // Handle object format
+ if (headers && typeof headers === 'object') {
+ for (const [key, value] of Object.entries(headers)) {
+ if (key && typeof key === 'string') {
+ normalizedHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(', ') : String(value)
+ }
+ }
+ }
+
+ return normalizedHeaders
+}
+
+const validSnapshotModes = /** @type {const} */ (['record', 'playback', 'update'])
+
+/** @typedef {typeof validSnapshotModes[number]} SnapshotMode */
+
+/**
+ * @param {*} mode - The snapshot mode to validate
+ * @returns {asserts mode is SnapshotMode}
+ */
+function validateSnapshotMode (mode) {
+ if (!validSnapshotModes.includes(mode)) {
+ throw new InvalidArgumentError(`Invalid snapshot mode: ${mode}. Must be one of: ${validSnapshotModes.join(', ')}`)
+ }
+}
+
+module.exports = {
+ createHeaderFilters,
+ hashId,
+ isUndiciHeaders,
+ normalizeHeaders,
+ isUrlExcludedFactory,
+ validateSnapshotMode
+}