tinyspy
Advanced tools
Comparing version 0.3.3 to 1.0.0
@@ -1,177 +0,92 @@ | ||
var __getOwnPropSymbols = Object.getOwnPropertySymbols; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __propIsEnum = Object.prototype.propertyIsEnumerable; | ||
var __objRest = (source, exclude) => { | ||
var target = {}; | ||
for (var prop in source) | ||
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) | ||
target[prop] = source[prop]; | ||
if (source != null && __getOwnPropSymbols) | ||
for (var prop of __getOwnPropSymbols(source)) { | ||
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) | ||
target[prop] = source[prop]; | ||
} | ||
return target; | ||
}; | ||
// src/utils.ts | ||
function assert(condition, message) { | ||
if (!condition) { | ||
throw new Error(message); | ||
} | ||
function d(t, e) { | ||
if (!t) | ||
throw new Error(e); | ||
} | ||
function isType(type, value) { | ||
return typeof value === type; | ||
function u(t, e) { | ||
return typeof e === t; | ||
} | ||
function f(t, e, i) { | ||
Object.defineProperty(t, e, i); | ||
} | ||
// src/spy.ts | ||
var spies = /* @__PURE__ */ new Set(); | ||
function spy(cb) { | ||
assert(isType("function", cb) || isType("undefined", cb), "cannot spy on a non-function value"); | ||
let fn = function(...args) { | ||
fn.called = true; | ||
fn.callCount++; | ||
fn.calls.push(args); | ||
if (fn.next) { | ||
let [type2, result2] = fn.next; | ||
fn.results.push(fn.next); | ||
fn.next = null; | ||
if (type2 === "ok") { | ||
return result2; | ||
} | ||
throw result2; | ||
var g = /* @__PURE__ */ new Set(); | ||
function S(t) { | ||
d(u("function", t) || u("undefined", t), "cannot spy on a non-function value"); | ||
let e = function(...o) { | ||
if (e.called = !0, e.callCount++, e.calls.push(o), e.next) { | ||
let [s, l] = e.next; | ||
if (e.results.push(e.next), e.next = null, s === "ok") | ||
return l; | ||
throw l; | ||
} | ||
let result; | ||
let type = "ok"; | ||
if (fn.impl) { | ||
let r, n = "ok"; | ||
if (e.impl) | ||
try { | ||
result = fn.impl.apply(this, args); | ||
type = "ok"; | ||
} catch (err) { | ||
result = err; | ||
type = "error"; | ||
fn.results.push([type, err]); | ||
throw err; | ||
r = e.impl.apply(this, o), n = "ok"; | ||
} catch (s) { | ||
throw r = s, n = "error", e.results.push([n, s]), s; | ||
} | ||
} | ||
let resultTuple = [type, result]; | ||
if (result && isType("object", result) && isType("function", result.then)) { | ||
const newPromise = result.then((r) => resultTuple[1] = r).catch((e) => { | ||
resultTuple[0] = "error"; | ||
resultTuple[1] = e; | ||
throw e; | ||
let c = [n, r]; | ||
if (r && u("object", r) && u("function", r.then)) { | ||
let s = r.then((l) => c[1] = l).catch((l) => { | ||
throw c[0] = "error", c[1] = l, l; | ||
}); | ||
Object.assign(newPromise, result); | ||
result = newPromise; | ||
Object.assign(s, r), r = s; | ||
} | ||
fn.results.push(resultTuple); | ||
return result; | ||
return e.results.push(c), r; | ||
}; | ||
Object.defineProperty(fn, "_isMockFunction", { get: () => true }); | ||
Object.defineProperty(fn, "length", { value: cb ? cb.length : 0 }); | ||
Object.defineProperty(fn, "returns", { | ||
f(e, "_isMockFunction", { get: () => !0 }), f(e, "length", { value: t ? t.length : 0 }), f(e, "returns", { | ||
get() { | ||
return this.results.map(([, r]) => r); | ||
return this.results.map(([, o]) => o); | ||
} | ||
}); | ||
Object.defineProperty(fn, "name", { value: cb ? cb.name || "spy" : "spy" }); | ||
const reset = () => { | ||
fn.called = false; | ||
fn.callCount = 0; | ||
fn.results = []; | ||
fn.calls = []; | ||
}), f(e, "name", { value: t && t.name || "spy" }); | ||
let i = () => { | ||
e.called = !1, e.callCount = 0, e.results = [], e.calls = []; | ||
}; | ||
reset(); | ||
fn.impl = cb; | ||
fn.reset = reset; | ||
fn.nextError = (error) => { | ||
fn.next = ["error", error]; | ||
return fn; | ||
}; | ||
fn.nextResult = (result) => { | ||
fn.next = ["ok", result]; | ||
return fn; | ||
}; | ||
return fn; | ||
return i(), e.impl = t, e.reset = i, e.nextError = (o) => (e.next = ["error", o], e), e.nextResult = (o) => (e.next = ["ok", o], e), e; | ||
} | ||
// src/spyOn.ts | ||
var getDescriptor = (obj, method) => Object.getOwnPropertyDescriptor(obj, method); | ||
function spyOn(obj, methodName, mock) { | ||
assert(!isType("undefined", obj), "spyOn could not find an object to spy upon"); | ||
assert(isType("object", obj) || isType("function", obj), "cannot spyOn on a primitive value"); | ||
let getMeta = () => { | ||
if (typeof methodName !== "object") { | ||
return [methodName, "value"]; | ||
} | ||
if ("getter" in methodName && "setter" in methodName) { | ||
var v = (t, e) => Object.getOwnPropertyDescriptor(t, e); | ||
function I(t, e, i) { | ||
d(!u("undefined", t), "spyOn could not find an object to spy upon"), d(u("object", t) || u("function", t), "cannot spyOn on a primitive value"); | ||
let o = () => { | ||
if (typeof e != "object") | ||
return [e, "value"]; | ||
if ("getter" in e && "setter" in e) | ||
throw new Error("cannot spy on both getter and setter"); | ||
} | ||
if ("getter" in methodName) { | ||
return [methodName.getter, "get"]; | ||
} | ||
if ("setter" in methodName) { | ||
return [methodName.setter, "set"]; | ||
} | ||
if ("getter" in e) | ||
return [e.getter, "get"]; | ||
if ("setter" in e) | ||
return [e.setter, "set"]; | ||
throw new Error("specify getter or setter to spy on"); | ||
}; | ||
let [accessName, accessType] = getMeta(); | ||
let objDescriptor = getDescriptor(obj, accessName); | ||
let proto = Object.getPrototypeOf(obj); | ||
let protoDescriptor = proto && getDescriptor(proto, accessName); | ||
let descriptor = objDescriptor || protoDescriptor; | ||
assert(descriptor || accessName in obj, `${String(accessName)} does not exist`); | ||
let ssr = false; | ||
if (accessType === "value" && descriptor && !descriptor.value && descriptor.get) { | ||
accessType = "get"; | ||
ssr = true; | ||
mock = descriptor.get(); | ||
} | ||
let origin; | ||
if (descriptor) { | ||
origin = descriptor[accessType]; | ||
} else if (accessType !== "value") { | ||
origin = () => obj[accessName]; | ||
} else { | ||
origin = obj[accessName]; | ||
} | ||
if (!mock) | ||
mock = origin; | ||
let fn = spy(mock); | ||
let define = (cb) => { | ||
let _a = descriptor || { | ||
configurable: true, | ||
writable: true | ||
}, { value } = _a, desc = __objRest(_a, ["value"]); | ||
if (accessType !== "value") { | ||
delete desc.writable; | ||
} | ||
; | ||
desc[accessType] = cb; | ||
Object.defineProperty(obj, accessName, desc); | ||
}; | ||
let restore = () => define(origin); | ||
fn.restore = restore; | ||
fn.getOriginal = () => ssr ? origin() : origin; | ||
fn.willCall = (newCb) => { | ||
fn.impl = newCb; | ||
return fn; | ||
}; | ||
define(ssr ? () => fn : fn); | ||
spies.add(fn); | ||
return fn; | ||
}, [r, n] = o(), c = v(t, r), s = Object.getPrototypeOf(t), l = s && v(s, r), a = c || l; | ||
d(a || r in t, `${String(r)} does not exist`); | ||
let T = !1; | ||
n === "value" && a && !a.value && a.get && (n = "get", T = !0, i = a.get()); | ||
let y; | ||
a ? y = a[n] : n !== "value" ? y = () => t[r] : y = t[r], i || (i = y); | ||
let p = S(i), A = (m) => { | ||
let { value: w, ...h } = a || { | ||
configurable: !0, | ||
writable: !0 | ||
}; | ||
n !== "value" && delete h.writable, h[n] = m, f(t, r, h); | ||
}, k = () => A(y); | ||
return p.restore = k, p.getOriginal = () => T ? y() : y, p.willCall = (m) => (p.impl = m, p), A(T ? () => p : p), g.add(p), p; | ||
} | ||
// src/restoreAll.ts | ||
function restoreAll() { | ||
for (let fn of spies) { | ||
fn.restore(); | ||
} | ||
spies.clear(); | ||
function G() { | ||
for (let t of g) | ||
t.restore(); | ||
g.clear(); | ||
} | ||
export { | ||
restoreAll, | ||
spies, | ||
spy, | ||
spyOn | ||
G as restoreAll, | ||
g as spies, | ||
S as spy, | ||
I as spyOn | ||
}; |
{ | ||
"name": "tinyspy", | ||
"version": "0.3.3", | ||
"version": "1.0.0", | ||
"type": "module", | ||
"main": "./dist/index.js", | ||
"main": "./dist/index.cjs", | ||
"module": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"exports": { | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.js", | ||
"require": "./dist/index.cjs", | ||
"default": "./dist/index.cjs" | ||
}, | ||
"files": [ | ||
@@ -13,9 +19,9 @@ "dist/**" | ||
"type": "git", | ||
"url": "git+https://github.com/aslemammad/tinyspy.git" | ||
"url": "git+https://github.com/tinylibs/tinyspy.git" | ||
}, | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/aslemammad/tinyspy/issues" | ||
"url": "https://github.com/tinylibs/tinyspy/issues" | ||
}, | ||
"homepage": "https://github.com/aslemammad/tinyspy#readme", | ||
"homepage": "https://github.com/tinylibs/tinyspy#readme", | ||
"keywords": [ | ||
@@ -29,3 +35,6 @@ "spy", | ||
"node": ">=14.0.0" | ||
}, | ||
"scripts": { | ||
"publish": "npm run build && clean-publish" | ||
} | ||
} |
@@ -5,6 +5,6 @@ # tinyspy | ||
A `7KB` package for minimal and easy testing with no dependencies. | ||
A `8KB` package for minimal and easy testing with no dependencies. | ||
This package was created for having a tiny spy library to use in `vitest`, but it can also be used in `jest` and other test environments. | ||
## Docs | ||
Read **[full docs](https://github.com/aslemammad/tinyspy#readme)** on GitHub. | ||
Read **[full docs](https://github.com/tinylibs/tinyspy#readme)** on GitHub. |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
9106
5
239
0
1