callman-core 1.6.0 → 1.7.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.
- package/dist/script/features/assertions.d.ts +26 -2
- package/dist/script/features/assertions.d.ts.map +1 -1
- package/dist/script/features/assertions.js +255 -57
- package/dist/script/features/assertions.js.map +1 -1
- package/dist/script/features/cryptojs.d.ts +1 -0
- package/dist/script/features/cryptojs.d.ts.map +1 -1
- package/dist/script/features/cryptojs.js +39 -0
- package/dist/script/features/cryptojs.js.map +1 -1
- package/dist/script/scope.d.ts.map +1 -1
- package/dist/script/scope.js +33 -0
- package/dist/script/scope.js.map +1 -1
- package/dist-cjs/script/features/assertions.js +255 -57
- package/dist-cjs/script/features/assertions.js.map +1 -1
- package/dist-cjs/script/features/cryptojs.js +39 -0
- package/dist-cjs/script/features/cryptojs.js.map +1 -1
- package/dist-cjs/script/scope.js +33 -0
- package/dist-cjs/script/scope.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// CryptoJS.enc.Utf8.parse(string) → Uint8Array
|
|
10
10
|
// CryptoJS.enc.Utf8.stringify(Uint8Array | ArrayBufferLike) → string
|
|
11
11
|
// CryptoJS.enc.Base64.stringify(Uint8Array | ArrayBufferLike) → string
|
|
12
|
+
// CryptoJS.enc.Base64.parse(base64String) → Uint8Array (decoder)
|
|
12
13
|
//
|
|
13
14
|
// HMAC / SHA / AES are intentionally out of scope.
|
|
14
15
|
const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
@@ -46,6 +47,38 @@ const encodeBase64 = (bytes) => {
|
|
|
46
47
|
}
|
|
47
48
|
return output;
|
|
48
49
|
};
|
|
50
|
+
// Inverse of encodeBase64. Accepts both standard base64 (`+`/`/`, padded)
|
|
51
|
+
// and base64url (`-`/`_`, unpadded) input — useful because callers
|
|
52
|
+
// frequently pass JWT payload segments which use the url-safe alphabet
|
|
53
|
+
// without padding. Throws on characters outside both alphabets so the
|
|
54
|
+
// caller fails fast on garbage input rather than silently producing junk
|
|
55
|
+
// bytes.
|
|
56
|
+
const decodeBase64 = (input) => {
|
|
57
|
+
// Normalize url-safe → standard and re-pad to a multiple of 4.
|
|
58
|
+
const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
59
|
+
const padding = (4 - (normalized.length % 4)) % 4;
|
|
60
|
+
const padded = normalized + "=".repeat(padding);
|
|
61
|
+
// Reject anything outside the standard alphabet (post-normalization).
|
|
62
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(padded)) {
|
|
63
|
+
throw new Error("CryptoJS.enc.Base64.parse: invalid base64 input");
|
|
64
|
+
}
|
|
65
|
+
const cleanLength = padded.replace(/=+$/g, "").length;
|
|
66
|
+
const byteLength = Math.floor((cleanLength * 3) / 4);
|
|
67
|
+
const out = new Uint8Array(byteLength);
|
|
68
|
+
let outIndex = 0;
|
|
69
|
+
for (let i = 0; i < padded.length; i += 4) {
|
|
70
|
+
const c1 = BASE64_CHARS.indexOf(padded[i]);
|
|
71
|
+
const c2 = BASE64_CHARS.indexOf(padded[i + 1]);
|
|
72
|
+
const c3 = padded[i + 2] === "=" ? -1 : BASE64_CHARS.indexOf(padded[i + 2]);
|
|
73
|
+
const c4 = padded[i + 3] === "=" ? -1 : BASE64_CHARS.indexOf(padded[i + 3]);
|
|
74
|
+
out[outIndex++] = (c1 << 2) | (c2 >> 4);
|
|
75
|
+
if (c3 >= 0)
|
|
76
|
+
out[outIndex++] = ((c2 & 0x0f) << 4) | (c3 >> 2);
|
|
77
|
+
if (c4 >= 0)
|
|
78
|
+
out[outIndex++] = ((c3 & 0x03) << 6) | c4;
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
};
|
|
49
82
|
export const createCryptoJsApi = () => {
|
|
50
83
|
const decoder = new TextDecoder();
|
|
51
84
|
return {
|
|
@@ -56,6 +89,12 @@ export const createCryptoJsApi = () => {
|
|
|
56
89
|
},
|
|
57
90
|
Base64: {
|
|
58
91
|
stringify: (input) => encodeBase64(toUint8Array(input)),
|
|
92
|
+
parse: (input) => {
|
|
93
|
+
if (typeof input !== "string") {
|
|
94
|
+
throw new Error("CryptoJS.enc.Base64.parse: expected a string");
|
|
95
|
+
}
|
|
96
|
+
return decodeBase64(input);
|
|
97
|
+
},
|
|
59
98
|
},
|
|
60
99
|
},
|
|
61
100
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cryptojs.js","sourceRoot":"","sources":["../../../src/script/features/cryptojs.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,sEAAsE;AACtE,yEAAyE;AACzE,qEAAqE;AACrE,qEAAqE;AACrE,EAAE;AACF,sEAAsE;AACtE,iDAAiD;AACjD,uEAAuE;AACvE,yEAAyE;AACzE,EAAE;AACF,mDAAmD;AAEnD,MAAM,YAAY,GAChB,kEAAkE,CAAC;AAErE,MAAM,YAAY,GAAG,CAAC,KAAc,EAAc,EAAE;IAClD,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAwB,CAAC;QACtC,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC,CAAC;AAEF,2EAA2E;AAC3E,yEAAyE;AACzE,uDAAuD;AACvD,MAAM,YAAY,GAAG,CAAC,KAAiB,EAAU,EAAE;IACjD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QACxB,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;QAC5C,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/C,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/C,MAAM,IAAI,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACzE,MAAM,IAAI,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cryptojs.js","sourceRoot":"","sources":["../../../src/script/features/cryptojs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/script/scope.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/script/scope.ts"],"names":[],"mappings":"AAmHA,eAAO,MAAM,oBAAoB,aAgB/B,CAAC;AAEH,eAAO,MAAM,8BAA8B,QAAuB,CAAC;AAEnE,MAAM,WAAW,aAAa;IAE5B,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAM5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC;IAIvD,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAED,eAAO,MAAM,gBAAgB,GAAI,UAAU,aAAa,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CA4DhF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAiBrF,CAAC"}
|
package/dist/script/scope.js
CHANGED
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
//
|
|
9
9
|
// The "blocked" set is the safety floor: these names are always undefined
|
|
10
10
|
// in user scripts, regardless of what the caller passes in `bindings`.
|
|
11
|
+
// Resolve a host-global lazily and only if it's actually a function. This
|
|
12
|
+
// lets us bind Node 18+ web-compat APIs (`atob`, `btoa`, `structuredClone`)
|
|
13
|
+
// without crashing on older runtimes that don't ship them. A missing API
|
|
14
|
+
// simply doesn't get added to ALLOWED_GLOBALS, mirroring the legacy
|
|
15
|
+
// "not exposed" behavior for that host.
|
|
16
|
+
const hostFn = (name) => {
|
|
17
|
+
const value = globalThis[name];
|
|
18
|
+
return typeof value === "function" ? value : undefined;
|
|
19
|
+
};
|
|
11
20
|
const ALLOWED_GLOBALS = {
|
|
12
21
|
JSON,
|
|
13
22
|
Math,
|
|
@@ -37,6 +46,30 @@ const ALLOWED_GLOBALS = {
|
|
|
37
46
|
URLSearchParams,
|
|
38
47
|
TextEncoder,
|
|
39
48
|
TextDecoder,
|
|
49
|
+
// Binary / typed-array surface — pure JS built-ins, no FS access. Lets
|
|
50
|
+
// scripts decode `new Uint8Array([...])` style payloads (JWT bodies,
|
|
51
|
+
// protobuf blobs, raw bytes from kafka) without falling back to Node-
|
|
52
|
+
// specific Buffer.
|
|
53
|
+
ArrayBuffer,
|
|
54
|
+
DataView,
|
|
55
|
+
Uint8Array,
|
|
56
|
+
Uint8ClampedArray,
|
|
57
|
+
Uint16Array,
|
|
58
|
+
Uint32Array,
|
|
59
|
+
Int8Array,
|
|
60
|
+
Int16Array,
|
|
61
|
+
Int32Array,
|
|
62
|
+
Float32Array,
|
|
63
|
+
Float64Array,
|
|
64
|
+
BigInt64Array,
|
|
65
|
+
BigUint64Array,
|
|
66
|
+
// Web-compat encoders. `atob`/`btoa` are standard in Node 18+; we bind
|
|
67
|
+
// the host implementation when available so scripts can decode base64url
|
|
68
|
+
// JWT payloads with no third-party shim. `structuredClone` mirrors the
|
|
69
|
+
// Node 17+ helper for deep-cloning Date/Map/Set/RegExp etc.
|
|
70
|
+
atob: hostFn("atob"),
|
|
71
|
+
btoa: hostFn("btoa"),
|
|
72
|
+
structuredClone: hostFn("structuredClone"),
|
|
40
73
|
parseInt,
|
|
41
74
|
parseFloat,
|
|
42
75
|
encodeURIComponent,
|
package/dist/script/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/script/scope.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/script/scope.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,wEAAwE;AACxE,4EAA4E;AAC5E,yEAAyE;AACzE,wEAAwE;AACxE,yBAAyB;AACzB,EAAE;AACF,0EAA0E;AAC1E,uEAAuE;AAEvE,0EAA0E;AAC1E,4EAA4E;AAC5E,yEAAyE;AACzE,oEAAoE;AACpE,wCAAwC;AACxC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAW,EAAE;IACvC,MAAM,KAAK,GAAI,UAAsC,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC,CAAC;AAEF,MAAM,eAAe,GAA4B;IAC/C,IAAI;IACJ,IAAI;IACJ,MAAM;IACN,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,IAAI;IACJ,MAAM;IACN,OAAO;IACP,KAAK;IACL,SAAS;IACT,cAAc;IACd,WAAW;IACX,UAAU;IACV,SAAS;IACT,QAAQ;IACR,cAAc;IACd,GAAG;IACH,GAAG;IACH,OAAO;IACP,OAAO;IACP,MAAM;IACN,MAAM;IACN,GAAG;IACH,eAAe;IACf,WAAW;IACX,WAAW;IACX,uEAAuE;IACvE,qEAAqE;IACrE,sEAAsE;IACtE,mBAAmB;IACnB,WAAW;IACX,QAAQ;IACR,UAAU;IACV,iBAAiB;IACjB,WAAW;IACX,WAAW;IACX,SAAS;IACT,UAAU;IACV,UAAU;IACV,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,cAAc;IACd,uEAAuE;IACvE,yEAAyE;IACzE,uEAAuE;IACvE,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC,iBAAiB,CAAC;IAC1C,QAAQ;IACR,UAAU;IACV,kBAAkB;IAClB,kBAAkB;IAClB,QAAQ;IACR,KAAK;IACL,sEAAsE;IACtE,SAAS;IACT,GAAG;IACH,QAAQ;CACT,CAAC;AAEF,MAAM,eAAe,GAAG;IACtB,MAAM;IACN,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,cAAc;IACd,aAAa;IACb,eAAe;IACf,OAAO;IACP,gBAAgB;IAChB,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,MAAM;IACN,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,SAAS;IACT,QAAQ;IACR,SAAS;IACT,WAAW;IACX,eAAe;CACP,CAAC;AAEX,wEAAwE;AACxE,0EAA0E;AAC1E,uEAAuE;AACvE,+BAA+B;AAC/B,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAS;IAClD,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;IAC/B,GAAG,eAAe;IAClB,IAAI;IACJ,KAAK;IACL,SAAS;IACT,SAAS;IACT,UAAU;IACV,MAAM;IACN,QAAQ;IACR,UAAU;IACV,0EAA0E;IAC1E,iEAAiE;IACjE,IAAI;IACJ,OAAO;IACP,OAAO;CACR,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,8BAA8B,GAAG,oBAAoB,CAAC;AAgCnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAuB,EAA2B,EAAE;IACnF,MAAM,MAAM,GAA4B;QACtC,GAAG,eAAe;QAClB,EAAE,EAAE,QAAQ,CAAC,EAAE;KAChB,CAAC;IAEF,IAAI,QAAQ,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;IAC5B,CAAC;IACD,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;IAC5C,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACpC,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;IACtC,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC9B,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAClC,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACpC,CAAC;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,CAAC,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAChC,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAChC,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAClC,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACpC,CAAC;IACD,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;IACxC,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;IACtC,CAAC;IACD,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAClE,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAA+B,EAA2B,EAAE,CAC3F,IAAI,KAAK,CAAC,MAAM,EAAE;IAChB,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI;IACf,GAAG,CAAC,WAAW,EAAE,QAAQ;QACvB,IAAI,QAAQ,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;YACpC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,WAAW,CAAC,QAAoC,CAAC,CAAC;IAC3D,CAAC;IACD,GAAG,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK;QAC9B,WAAW,CAAC,QAAoC,CAAC,GAAG,KAAK,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,cAAc,CAAC,WAAW,EAAE,QAAQ;QAClC,OAAO,WAAW,CAAC,QAAoC,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// pm.expect / PmAssertion — Postman/Chai-flavored fluent assertion vocabulary.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
4
|
+
// Public surface stays bit-identical with the legacy implementation: every
|
|
5
|
+
// previously-shipped method/getter behaves the same when called without
|
|
6
|
+
// `.not`/`.deep`/`.nested` modifiers. Three flags layered on top give us
|
|
7
|
+
// chai-style affordances:
|
|
8
8
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
9
|
+
// .not — flips pass/fail of the next assertion
|
|
10
|
+
// .deep — promotes `.equal`/`.toBe` to deep-equality (alias for .eql)
|
|
11
|
+
// .nested — `.property("a.b.c")` walks dot-paths (already the default;
|
|
12
|
+
// kept as a chain word so chai-style code reads naturally)
|
|
13
|
+
//
|
|
14
|
+
// All chain getters return a NEW PmAssertion instance carrying the updated
|
|
15
|
+
// flags. This keeps each `pm.expect(x)` call independent — flag state can't
|
|
16
|
+
// leak across assertions on the same value, and `.not.not.equal(x)` cleanly
|
|
17
|
+
// double-toggles back to the positive form.
|
|
11
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
19
|
exports.createExpectApi = exports.PmAssertion = void 0;
|
|
13
20
|
const get_js_1 = require("../../utils/get.js");
|
|
@@ -52,12 +59,36 @@ const isDeepEqual = (left, right) => {
|
|
|
52
59
|
}
|
|
53
60
|
return false;
|
|
54
61
|
};
|
|
62
|
+
// Type-of helpers used by `.empty` so we treat Map/Set/object correctly.
|
|
63
|
+
const hasLengthProperty = (value) => value !== null &&
|
|
64
|
+
typeof value.length === "number";
|
|
65
|
+
const hasSizeProperty = (value) => value !== null &&
|
|
66
|
+
typeof value.size === "number";
|
|
55
67
|
class PmAssertion {
|
|
56
68
|
actual;
|
|
57
|
-
|
|
69
|
+
flags;
|
|
70
|
+
constructor(actual, flags = {}) {
|
|
58
71
|
this.actual = actual;
|
|
72
|
+
this.flags = flags;
|
|
73
|
+
}
|
|
74
|
+
// Internal: wrap an outcome with negation, throwing the right message.
|
|
75
|
+
check(pass, positiveMessage, negativeMessage) {
|
|
76
|
+
const finalPass = this.flags.negated ? !pass : pass;
|
|
77
|
+
if (!finalPass) {
|
|
78
|
+
throw new Error(this.flags.negated
|
|
79
|
+
? negativeMessage ?? `Expected NOT: ${positiveMessage}`
|
|
80
|
+
: positiveMessage);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Internal: build a child assertion preserving negation but stripping the
|
|
84
|
+
// `.deep`/`.nested` flags that were consumed by the current call. Used by
|
|
85
|
+
// `.property()` so chained calls like
|
|
86
|
+
// pm.expect(obj).to.have.property("a", 1).and.to.equal({a:1})
|
|
87
|
+
// start a fresh chain on the property value.
|
|
88
|
+
child(value) {
|
|
89
|
+
return new PmAssertion(value, { negated: this.flags.negated });
|
|
59
90
|
}
|
|
60
|
-
// English chain getters —
|
|
91
|
+
// ── English chain getters — pure grammar, no behavior ────────────────
|
|
61
92
|
get to() {
|
|
62
93
|
return this;
|
|
63
94
|
}
|
|
@@ -91,43 +122,77 @@ class PmAssertion {
|
|
|
91
122
|
get same() {
|
|
92
123
|
return this;
|
|
93
124
|
}
|
|
125
|
+
// ── Modifier chain words — return a NEW instance with the flag set ──
|
|
126
|
+
get not() {
|
|
127
|
+
return new PmAssertion(this.actual, {
|
|
128
|
+
...this.flags,
|
|
129
|
+
negated: !this.flags.negated,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
94
132
|
get deep() {
|
|
95
|
-
return this;
|
|
133
|
+
return new PmAssertion(this.actual, { ...this.flags, deep: true });
|
|
96
134
|
}
|
|
135
|
+
get nested() {
|
|
136
|
+
return new PmAssertion(this.actual, { ...this.flags, nested: true });
|
|
137
|
+
}
|
|
138
|
+
// ── Assertion getters ────────────────────────────────────────────────
|
|
97
139
|
get ok() {
|
|
98
140
|
return this.toBeTruthy();
|
|
99
141
|
}
|
|
100
142
|
get true() {
|
|
101
|
-
|
|
102
|
-
throw new Error(`Expected ${formatValue(this.actual)} to be true`);
|
|
103
|
-
}
|
|
143
|
+
this.check(this.actual === true, `Expected ${formatValue(this.actual)} to be true`, `Expected ${formatValue(this.actual)} NOT to be true`);
|
|
104
144
|
return this;
|
|
105
145
|
}
|
|
106
146
|
get false() {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
147
|
+
this.check(this.actual === false, `Expected ${formatValue(this.actual)} to be false`, `Expected ${formatValue(this.actual)} NOT to be false`);
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
get null() {
|
|
151
|
+
this.check(this.actual === null, `Expected ${formatValue(this.actual)} to be null`, `Expected ${formatValue(this.actual)} NOT to be null`);
|
|
152
|
+
return this;
|
|
153
|
+
}
|
|
154
|
+
get undefined() {
|
|
155
|
+
this.check(this.actual === undefined, `Expected ${formatValue(this.actual)} to be undefined`, `Expected ${formatValue(this.actual)} NOT to be undefined`);
|
|
110
156
|
return this;
|
|
111
157
|
}
|
|
112
158
|
get exist() {
|
|
113
|
-
|
|
114
|
-
|
|
159
|
+
this.check(this.actual !== null && this.actual !== undefined, `Expected ${formatValue(this.actual)} to exist`, `Expected ${formatValue(this.actual)} NOT to exist`);
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
// `.empty` — works for strings, arrays, Maps, Sets, and plain objects.
|
|
163
|
+
get empty() {
|
|
164
|
+
let isEmpty;
|
|
165
|
+
if (typeof this.actual === "string" || Array.isArray(this.actual)) {
|
|
166
|
+
isEmpty = this.actual.length === 0;
|
|
115
167
|
}
|
|
168
|
+
else if (this.actual instanceof Map ||
|
|
169
|
+
this.actual instanceof Set ||
|
|
170
|
+
hasSizeProperty(this.actual)) {
|
|
171
|
+
isEmpty = this.actual.size === 0;
|
|
172
|
+
}
|
|
173
|
+
else if (isRecord(this.actual)) {
|
|
174
|
+
isEmpty = Object.keys(this.actual).length === 0;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
throw new Error(`Expected ${formatValue(this.actual)} to be a string, array, Map, Set, or object`);
|
|
178
|
+
}
|
|
179
|
+
this.check(isEmpty, `Expected ${formatValue(this.actual)} to be empty`, `Expected ${formatValue(this.actual)} NOT to be empty`);
|
|
116
180
|
return this;
|
|
117
181
|
}
|
|
182
|
+
// ── Equality ─────────────────────────────────────────────────────────
|
|
183
|
+
// `.deep.equal(x)` upgrades to deep equality; `.equal(x)` is identity.
|
|
118
184
|
equal(expected) {
|
|
119
|
-
if (
|
|
120
|
-
|
|
185
|
+
if (this.flags.deep) {
|
|
186
|
+
return this.toEqual(expected);
|
|
121
187
|
}
|
|
188
|
+
this.check(Object.is(this.actual, expected), `Expected ${formatValue(this.actual)} to equal ${formatValue(expected)}`, `Expected ${formatValue(this.actual)} NOT to equal ${formatValue(expected)}`);
|
|
122
189
|
return this;
|
|
123
190
|
}
|
|
124
191
|
toBe(expected) {
|
|
125
192
|
return this.equal(expected);
|
|
126
193
|
}
|
|
127
194
|
toBeDefined() {
|
|
128
|
-
|
|
129
|
-
throw new Error(`Expected ${formatValue(this.actual)} to be defined`);
|
|
130
|
-
}
|
|
195
|
+
this.check(this.actual !== undefined, `Expected ${formatValue(this.actual)} to be defined`, `Expected ${formatValue(this.actual)} NOT to be defined`);
|
|
131
196
|
return this;
|
|
132
197
|
}
|
|
133
198
|
equals(expected) {
|
|
@@ -137,33 +202,69 @@ class PmAssertion {
|
|
|
137
202
|
return this.toEqual(expected);
|
|
138
203
|
}
|
|
139
204
|
toEqual(expected) {
|
|
140
|
-
|
|
141
|
-
throw new Error(`Expected ${formatValue(this.actual)} to deeply equal ${formatValue(expected)}`);
|
|
142
|
-
}
|
|
205
|
+
this.check(isDeepEqual(this.actual, expected), `Expected ${formatValue(this.actual)} to deeply equal ${formatValue(expected)}`, `Expected ${formatValue(this.actual)} NOT to deeply equal ${formatValue(expected)}`);
|
|
143
206
|
return this;
|
|
144
207
|
}
|
|
208
|
+
// ── Type checks ──────────────────────────────────────────────────────
|
|
145
209
|
a(expectedType) {
|
|
146
210
|
const actualType = getValueType(this.actual);
|
|
147
211
|
const normalizedExpectedType = expectedType.trim().toLowerCase();
|
|
148
|
-
|
|
149
|
-
throw new Error(`Expected type ${normalizedExpectedType} but got ${actualType}`);
|
|
150
|
-
}
|
|
212
|
+
this.check(actualType === normalizedExpectedType, `Expected type ${normalizedExpectedType} but got ${actualType}`, `Expected type NOT to be ${normalizedExpectedType}`);
|
|
151
213
|
return this;
|
|
152
214
|
}
|
|
153
215
|
an(expectedType) {
|
|
154
216
|
return this.a(expectedType);
|
|
155
217
|
}
|
|
218
|
+
instanceOf(constructor) {
|
|
219
|
+
if (typeof constructor !== "function") {
|
|
220
|
+
throw new Error("instanceOf expects a constructor function as its argument");
|
|
221
|
+
}
|
|
222
|
+
const ctorName = constructor.name || "<anonymous>";
|
|
223
|
+
let isInstance = false;
|
|
224
|
+
try {
|
|
225
|
+
isInstance = this.actual instanceof constructor;
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// RHS isn't actually callable as a constructor — treat as failure.
|
|
229
|
+
isInstance = false;
|
|
230
|
+
}
|
|
231
|
+
this.check(isInstance, `Expected ${formatValue(this.actual)} to be an instance of ${ctorName}`, `Expected ${formatValue(this.actual)} NOT to be an instance of ${ctorName}`);
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
234
|
+
// ── Property access ──────────────────────────────────────────────────
|
|
235
|
+
// `safeGet` already supports dot-path notation (e.g. "a.b.c"). The
|
|
236
|
+
// `.nested` flag is therefore informational only — kept so chai-style
|
|
237
|
+
// code (`.nested.property("a.b")`) reads naturally. Existing call sites
|
|
238
|
+
// that pass plain keys continue to work because safeGet treats a key
|
|
239
|
+
// without "." as a single token.
|
|
156
240
|
property(key, expectedValue) {
|
|
157
241
|
const property = (0, get_js_1.safeGet)(this.actual, key);
|
|
158
|
-
|
|
159
|
-
|
|
242
|
+
this.check(property.exists, `Expected ${formatValue(this.actual)} to have property "${key}"`, `Expected ${formatValue(this.actual)} NOT to have property "${key}"`);
|
|
243
|
+
// Stop here if negated — the inner-value chain below would be a no-op
|
|
244
|
+
// in the negated case (we already asserted the property is absent).
|
|
245
|
+
if (this.flags.negated) {
|
|
246
|
+
return this;
|
|
160
247
|
}
|
|
161
|
-
const nextAssertion =
|
|
248
|
+
const nextAssertion = this.child(property.value);
|
|
162
249
|
if (arguments.length > 1) {
|
|
163
250
|
nextAssertion.toEqual(expectedValue);
|
|
164
251
|
}
|
|
165
252
|
return nextAssertion;
|
|
166
253
|
}
|
|
254
|
+
// chai-style: pm.expect(obj).to.have.keys("a", "b") — strict, all of them
|
|
255
|
+
// must be the object's own enumerable keys and nothing else.
|
|
256
|
+
keys(...names) {
|
|
257
|
+
if (!isRecord(this.actual)) {
|
|
258
|
+
throw new Error(`Expected ${formatValue(this.actual)} to be an object`);
|
|
259
|
+
}
|
|
260
|
+
const expected = new Set(names);
|
|
261
|
+
const actualKeys = new Set(Object.keys(this.actual));
|
|
262
|
+
const matches = expected.size === actualKeys.size &&
|
|
263
|
+
[...expected].every((key) => actualKeys.has(key));
|
|
264
|
+
this.check(matches, `Expected object to have exactly keys [${names.join(", ")}], got [${[...actualKeys].join(", ")}]`, `Expected object NOT to have exactly keys [${names.join(", ")}]`);
|
|
265
|
+
return this;
|
|
266
|
+
}
|
|
267
|
+
// ── Containment ──────────────────────────────────────────────────────
|
|
167
268
|
contain(expected) {
|
|
168
269
|
return this.toContain(expected);
|
|
169
270
|
}
|
|
@@ -171,30 +272,36 @@ class PmAssertion {
|
|
|
171
272
|
return this.toContain(expected);
|
|
172
273
|
}
|
|
173
274
|
toContain(expected) {
|
|
275
|
+
let isIncluded;
|
|
174
276
|
if (typeof this.actual === "string") {
|
|
175
|
-
|
|
176
|
-
throw new Error(`Expected ${formatValue(this.actual)} to contain ${formatValue(expected)}`);
|
|
177
|
-
}
|
|
178
|
-
return this;
|
|
277
|
+
isIncluded = this.actual.includes(String(expected));
|
|
179
278
|
}
|
|
180
|
-
if (Array.isArray(this.actual)) {
|
|
181
|
-
|
|
182
|
-
throw new Error(`Expected ${formatValue(this.actual)} to contain ${formatValue(expected)}`);
|
|
183
|
-
}
|
|
184
|
-
return this;
|
|
279
|
+
else if (Array.isArray(this.actual)) {
|
|
280
|
+
isIncluded = this.actual.some((entry) => isDeepEqual(entry, expected));
|
|
185
281
|
}
|
|
186
|
-
|
|
282
|
+
else {
|
|
283
|
+
throw new Error("toContain supports only strings and arrays");
|
|
284
|
+
}
|
|
285
|
+
this.check(isIncluded, `Expected ${formatValue(this.actual)} to contain ${formatValue(expected)}`, `Expected ${formatValue(this.actual)} NOT to contain ${formatValue(expected)}`);
|
|
286
|
+
return this;
|
|
287
|
+
}
|
|
288
|
+
oneOf(values) {
|
|
289
|
+
if (!Array.isArray(values)) {
|
|
290
|
+
throw new Error("oneOf expects an array");
|
|
291
|
+
}
|
|
292
|
+
const isMember = values.some((entry) => isDeepEqual(entry, this.actual));
|
|
293
|
+
this.check(isMember, `Expected ${formatValue(this.actual)} to be one of ${formatValue(values)}`, `Expected ${formatValue(this.actual)} NOT to be one of ${formatValue(values)}`);
|
|
294
|
+
return this;
|
|
187
295
|
}
|
|
188
296
|
match(pattern) {
|
|
189
297
|
if (typeof this.actual !== "string") {
|
|
190
298
|
throw new Error(`Expected ${formatValue(this.actual)} to be a string`);
|
|
191
299
|
}
|
|
192
300
|
const matcher = typeof pattern === "string" ? new RegExp(pattern) : pattern;
|
|
193
|
-
|
|
194
|
-
throw new Error(`Expected ${formatValue(this.actual)} to match ${String(matcher)}`);
|
|
195
|
-
}
|
|
301
|
+
this.check(matcher.test(this.actual), `Expected ${formatValue(this.actual)} to match ${String(matcher)}`, `Expected ${formatValue(this.actual)} NOT to match ${String(matcher)}`);
|
|
196
302
|
return this;
|
|
197
303
|
}
|
|
304
|
+
// ── Response-shape shortcuts ─────────────────────────────────────────
|
|
198
305
|
status(expected) {
|
|
199
306
|
return this.property("status", expected);
|
|
200
307
|
}
|
|
@@ -205,30 +312,38 @@ class PmAssertion {
|
|
|
205
312
|
}
|
|
206
313
|
const normalizedName = name.toLowerCase();
|
|
207
314
|
const entry = Object.entries(headers.value).find(([key]) => key.toLowerCase() === normalizedName);
|
|
208
|
-
|
|
209
|
-
|
|
315
|
+
this.check(Boolean(entry), `Expected response headers to contain "${name}"`, `Expected response headers NOT to contain "${name}"`);
|
|
316
|
+
if (this.flags.negated || !entry) {
|
|
317
|
+
return this;
|
|
210
318
|
}
|
|
211
|
-
const nextAssertion =
|
|
319
|
+
const nextAssertion = this.child(entry[1]);
|
|
212
320
|
if (arguments.length > 1) {
|
|
213
321
|
nextAssertion.toEqual(expectedValue);
|
|
214
322
|
}
|
|
215
323
|
return nextAssertion;
|
|
216
324
|
}
|
|
325
|
+
// ── Numeric comparison ──────────────────────────────────────────────
|
|
217
326
|
greaterThan(expected) {
|
|
218
327
|
return this.toBeGreaterThan(expected);
|
|
219
328
|
}
|
|
220
329
|
lessThan(expected) {
|
|
221
330
|
return this.toBeLessThan(expected);
|
|
222
331
|
}
|
|
332
|
+
// chai-style alias for the same predicate (no `.be.above` chain — call
|
|
333
|
+
// directly: `pm.expect(x).to.be.above(5)`).
|
|
334
|
+
above(expected) {
|
|
335
|
+
return this.toBeGreaterThan(expected);
|
|
336
|
+
}
|
|
337
|
+
below(expected) {
|
|
338
|
+
return this.toBeLessThan(expected);
|
|
339
|
+
}
|
|
223
340
|
toBeGreaterThan(expected) {
|
|
224
341
|
const actualNumber = Number(this.actual);
|
|
225
342
|
const expectedNumber = Number(expected);
|
|
226
343
|
if (!Number.isFinite(actualNumber) || !Number.isFinite(expectedNumber)) {
|
|
227
344
|
throw new Error("toBeGreaterThan supports only finite numbers");
|
|
228
345
|
}
|
|
229
|
-
|
|
230
|
-
throw new Error(`Expected ${formatValue(this.actual)} to be greater than ${formatValue(expected)}`);
|
|
231
|
-
}
|
|
346
|
+
this.check(actualNumber > expectedNumber, `Expected ${formatValue(this.actual)} to be greater than ${formatValue(expected)}`, `Expected ${formatValue(this.actual)} NOT to be greater than ${formatValue(expected)}`);
|
|
232
347
|
return this;
|
|
233
348
|
}
|
|
234
349
|
toBeLessThan(expected) {
|
|
@@ -237,21 +352,104 @@ class PmAssertion {
|
|
|
237
352
|
if (!Number.isFinite(actualNumber) || !Number.isFinite(expectedNumber)) {
|
|
238
353
|
throw new Error("toBeLessThan supports only finite numbers");
|
|
239
354
|
}
|
|
240
|
-
|
|
241
|
-
|
|
355
|
+
this.check(actualNumber < expectedNumber, `Expected ${formatValue(this.actual)} to be less than ${formatValue(expected)}`, `Expected ${formatValue(this.actual)} NOT to be less than ${formatValue(expected)}`);
|
|
356
|
+
return this;
|
|
357
|
+
}
|
|
358
|
+
within(min, max) {
|
|
359
|
+
const actualNumber = Number(this.actual);
|
|
360
|
+
const minNumber = Number(min);
|
|
361
|
+
const maxNumber = Number(max);
|
|
362
|
+
if (!Number.isFinite(actualNumber) ||
|
|
363
|
+
!Number.isFinite(minNumber) ||
|
|
364
|
+
!Number.isFinite(maxNumber)) {
|
|
365
|
+
throw new Error("within supports only finite numbers");
|
|
242
366
|
}
|
|
367
|
+
this.check(actualNumber >= minNumber && actualNumber <= maxNumber, `Expected ${formatValue(this.actual)} to be within ${formatValue(min)}..${formatValue(max)}`, `Expected ${formatValue(this.actual)} NOT to be within ${formatValue(min)}..${formatValue(max)}`);
|
|
243
368
|
return this;
|
|
244
369
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
370
|
+
closeTo(expected, delta) {
|
|
371
|
+
const actualNumber = Number(this.actual);
|
|
372
|
+
const expectedNumber = Number(expected);
|
|
373
|
+
const deltaNumber = Number(delta);
|
|
374
|
+
if (!Number.isFinite(actualNumber) ||
|
|
375
|
+
!Number.isFinite(expectedNumber) ||
|
|
376
|
+
!Number.isFinite(deltaNumber)) {
|
|
377
|
+
throw new Error("closeTo supports only finite numbers");
|
|
378
|
+
}
|
|
379
|
+
this.check(Math.abs(actualNumber - expectedNumber) <= deltaNumber, `Expected ${formatValue(this.actual)} to be within ${deltaNumber} of ${formatValue(expected)}`, `Expected ${formatValue(this.actual)} NOT to be within ${deltaNumber} of ${formatValue(expected)}`);
|
|
380
|
+
return this;
|
|
381
|
+
}
|
|
382
|
+
// ── Length / size ────────────────────────────────────────────────────
|
|
383
|
+
lengthOf(expected) {
|
|
384
|
+
if (!hasLengthProperty(this.actual) &&
|
|
385
|
+
!hasSizeProperty(this.actual)) {
|
|
386
|
+
throw new Error(`Expected ${formatValue(this.actual)} to have a length or size`);
|
|
248
387
|
}
|
|
388
|
+
const actualLength = hasLengthProperty(this.actual)
|
|
389
|
+
? this.actual.length
|
|
390
|
+
: this.actual.size;
|
|
391
|
+
this.check(actualLength === expected, `Expected ${formatValue(this.actual)} to have length ${expected}, got ${actualLength}`, `Expected ${formatValue(this.actual)} NOT to have length ${expected}`);
|
|
392
|
+
return this;
|
|
393
|
+
}
|
|
394
|
+
length(expected) {
|
|
395
|
+
return this.lengthOf(expected);
|
|
396
|
+
}
|
|
397
|
+
// ── Truthiness ──────────────────────────────────────────────────────
|
|
398
|
+
toBeTruthy() {
|
|
399
|
+
this.check(Boolean(this.actual), `Expected ${formatValue(this.actual)} to be truthy`, `Expected ${formatValue(this.actual)} NOT to be truthy`);
|
|
249
400
|
return this;
|
|
250
401
|
}
|
|
251
402
|
toBeFalsy() {
|
|
252
|
-
|
|
253
|
-
|
|
403
|
+
this.check(!this.actual, `Expected ${formatValue(this.actual)} to be falsy`, `Expected ${formatValue(this.actual)} NOT to be falsy`);
|
|
404
|
+
return this;
|
|
405
|
+
}
|
|
406
|
+
// ── Function-shape predicates ────────────────────────────────────────
|
|
407
|
+
// `pm.expect(fn).to.throw()` — runs the function and asserts it throws.
|
|
408
|
+
// Optional matcher narrows by message substring (string), regex test,
|
|
409
|
+
// or `instanceof <Constructor>` (function).
|
|
410
|
+
throw(matcher) {
|
|
411
|
+
if (typeof this.actual !== "function") {
|
|
412
|
+
throw new Error(`Expected ${formatValue(this.actual)} to be a function`);
|
|
413
|
+
}
|
|
414
|
+
let thrown = null;
|
|
415
|
+
let didThrow = false;
|
|
416
|
+
try {
|
|
417
|
+
this.actual();
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
didThrow = true;
|
|
421
|
+
thrown = error;
|
|
422
|
+
}
|
|
423
|
+
let pass = didThrow;
|
|
424
|
+
let detail = "";
|
|
425
|
+
if (didThrow && matcher !== undefined) {
|
|
426
|
+
const errorMessage = thrown instanceof Error ? thrown.message : String(thrown);
|
|
427
|
+
if (typeof matcher === "string") {
|
|
428
|
+
pass = errorMessage.includes(matcher);
|
|
429
|
+
detail = ` matching ${formatValue(matcher)}`;
|
|
430
|
+
}
|
|
431
|
+
else if (matcher instanceof RegExp) {
|
|
432
|
+
pass = matcher.test(errorMessage);
|
|
433
|
+
detail = ` matching ${String(matcher)}`;
|
|
434
|
+
}
|
|
435
|
+
else if (typeof matcher === "function") {
|
|
436
|
+
pass = thrown instanceof matcher;
|
|
437
|
+
detail = ` of type ${matcher.name ?? "<anonymous>"}`;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
this.check(pass, `Expected function to throw${detail}`, `Expected function NOT to throw${detail}`);
|
|
441
|
+
return this;
|
|
442
|
+
}
|
|
443
|
+
// chai-style: `pm.expect(obj).to.respondTo("methodName")` — actual has
|
|
444
|
+
// a callable property by that name. Accepts any non-null object
|
|
445
|
+
// (plain objects, arrays, Maps, Sets, class instances) — method lookup
|
|
446
|
+
// falls through the prototype chain like a normal `obj.method` access.
|
|
447
|
+
respondTo(methodName) {
|
|
448
|
+
let fn = undefined;
|
|
449
|
+
if (this.actual !== null && this.actual !== undefined) {
|
|
450
|
+
fn = this.actual[methodName];
|
|
254
451
|
}
|
|
452
|
+
this.check(typeof fn === "function", `Expected ${formatValue(this.actual)} to respond to method "${methodName}"`, `Expected ${formatValue(this.actual)} NOT to respond to method "${methodName}"`);
|
|
255
453
|
return this;
|
|
256
454
|
}
|
|
257
455
|
}
|