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.
@@ -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":"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"}
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":"AAiFA,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"}
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"}
@@ -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,
@@ -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":"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"}
@@ -1,13 +1,20 @@
1
1
  "use strict";
2
2
  // pm.expect / PmAssertion — Postman/Chai-flavored fluent assertion vocabulary.
3
3
  //
4
- // Lifted as-is from the legacy callman_core/src/script/pmApi.ts (which is
5
- // also identical to the backend's PostmanAssertion class). This is the one
6
- // part of the sandbox that all three implementations agreed on, so we keep
7
- // the behavior bit-identical to avoid breaking user scripts.
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
- // Chain getters (.to / .be / .have / ...) return `this` and exist purely
10
- // for English-grammar fluency (`pm.expect(x).to.have.status(200)`).
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
- constructor(actual) {
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 — return `this` for fluent grammar
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
- if (this.actual !== true) {
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
- if (this.actual !== false) {
108
- throw new Error(`Expected ${formatValue(this.actual)} to be false`);
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
- if (this.actual === null || this.actual === undefined) {
114
- throw new Error(`Expected ${formatValue(this.actual)} to exist`);
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 (!Object.is(this.actual, expected)) {
120
- throw new Error(`Expected ${formatValue(this.actual)} to equal ${formatValue(expected)}`);
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
- if (this.actual === undefined) {
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
- if (!isDeepEqual(this.actual, expected)) {
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
- if (actualType !== normalizedExpectedType) {
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
- if (!property.exists) {
159
- throw new Error(`Expected ${formatValue(this.actual)} to have property "${key}"`);
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 = new PmAssertion(property.value);
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
- if (!this.actual.includes(String(expected))) {
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
- if (!this.actual.some((entry) => isDeepEqual(entry, expected))) {
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
- throw new Error("toContain supports only strings and arrays");
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
- if (!matcher.test(this.actual)) {
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
- if (!entry) {
209
- throw new Error(`Expected response headers to contain "${name}"`);
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 = new PmAssertion(entry[1]);
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
- if (actualNumber <= expectedNumber) {
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
- if (actualNumber >= expectedNumber) {
241
- throw new Error(`Expected ${formatValue(this.actual)} to be less than ${formatValue(expected)}`);
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
- toBeTruthy() {
246
- if (!this.actual) {
247
- throw new Error(`Expected ${formatValue(this.actual)} to be truthy`);
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
- if (this.actual) {
253
- throw new Error(`Expected ${formatValue(this.actual)} to be falsy`);
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
  }