testdouble
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -81,2 +81,18 @@ # Replacing Real Dependencies with Test Doubles | ||
### How module replacement works | ||
Under the hood, testdouble.js uses a module called | ||
[quibble](https://github.com/testdouble/quibble) that facilitates `td.replace`'s | ||
behavior by monkey-patching Node's `require` function (specifically, | ||
`Module._load`). When `td.replace` is invoked for a module, quibble will begin | ||
intercepting any `require` calls made in that file and—bypassing the Node.js | ||
module cache—return a test double instead of the actual module that resolves to | ||
the same absolute path as whatever path was passed to `td.replace`. | ||
As a result, keep in mind that you must **call `td.replace` for each of your | ||
subject's dependencies before you `require` your subject itself**. If you | ||
`require` your subject before calling `td.replace`, it will load normally | ||
(potentially from the module cache) and any calls to `td.replace` will be too | ||
late to have their intended effect). | ||
### Aside: third-party modules | ||
@@ -83,0 +99,0 @@ |
@@ -12,3 +12,4 @@ // Generated by CoffeeScript 1.10.0 | ||
afterEach(function() { | ||
return td.reset(); | ||
td.reset(); | ||
return td.config.reset(); | ||
}); | ||
@@ -15,0 +16,0 @@ |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
global.td = require('./../src/testdouble'); | ||
var sourceDir; | ||
sourceDir = process.env.COVER != null ? process.env.COVER : 'src'; | ||
global.requireSource = function(path) { | ||
return require((process.cwd()) + "/" + sourceDir + "/" + path); | ||
}; | ||
global.td = requireSource('testdouble'); | ||
global.chai = require('chai'); | ||
@@ -6,0 +14,0 @@ |
@@ -7,3 +7,3 @@ // Generated by CoffeeScript 1.10.0 | ||
if (NODE_JS) { | ||
return require('../../src/args-match')([expected], [actual], {}); | ||
return requireSource('args-match')([expected], [actual], {}); | ||
} else { | ||
@@ -197,3 +197,3 @@ return expected.__matches(actual); | ||
}; | ||
})(this)), "the contains() matcher only supports strings, arrays, and plain objects"); | ||
})(this)), "Error: testdouble.js - td.matchers.contains - this matcher only supports strings, arrays, and plain objects"); | ||
}); | ||
@@ -200,0 +200,0 @@ }); |
@@ -86,2 +86,27 @@ // Generated by CoffeeScript 1.10.0 | ||
}); | ||
describe('Replacing a method on an object instantiated with `new`', function() { | ||
Given(function() { | ||
return this.thing = new this.dependency.thingConstructor(); | ||
}); | ||
When(function() { | ||
return this.doubleFoo = td.replace(this.thing, 'foo'); | ||
}); | ||
Then(function() { | ||
return td.explain(this.thing.foo).isTestDouble === true; | ||
}); | ||
And(function() { | ||
return this.thing.foo() === void 0; | ||
}); | ||
return describe('reset restores it', function() { | ||
When(function() { | ||
return td.reset(); | ||
}); | ||
Then(function() { | ||
return td.explain(this.thing.foo).isTestDouble === false; | ||
}); | ||
return And(function() { | ||
return this.thing.foo() === 'og foo'; | ||
}); | ||
}); | ||
}); | ||
describe('Replacing an object / function bag', function() { | ||
@@ -107,7 +132,10 @@ When(function() { | ||
}); | ||
describe('Replacing a non-existent property', function() { | ||
describe('Replacing a property that is not an object/function', function() { | ||
Given(function() { | ||
return this.message = 'Error: testdouble.js - td.replace - "badType" property was found, but test double only knows how to replace functions, constructors, & objects containing functions (its value was '; | ||
}); | ||
When(function() { | ||
var e, error; | ||
try { | ||
return td.replace(this.dependency, 'notAThing'); | ||
return td.replace(this.dependency, 'badType'); | ||
} catch (error) { | ||
@@ -118,20 +146,137 @@ e = error; | ||
}); | ||
return Then(function() { | ||
return this.error.message === 'td.replace error: No "notAThing" property was found.'; | ||
context('a number', function() { | ||
Given(function() { | ||
return this.dependency.badType = 5; | ||
}); | ||
return Then(function() { | ||
return this.error.message === this.message + '5).'; | ||
}); | ||
}); | ||
context('a string', function() { | ||
Given(function() { | ||
return this.dependency.badType = "hello"; | ||
}); | ||
return Then(function() { | ||
return this.error.message === this.message + '"hello").'; | ||
}); | ||
}); | ||
context('null', function() { | ||
Given(function() { | ||
return this.dependency.badType = null; | ||
}); | ||
return Then(function() { | ||
return this.error.message === this.message + 'null).'; | ||
}); | ||
}); | ||
return context('undefined', function() { | ||
Given(function() { | ||
return this.dependency.badType = void 0; | ||
}); | ||
return Then(function() { | ||
return this.error.message === this.message + 'undefined).'; | ||
}); | ||
}); | ||
}); | ||
describe('Replacing a non-existent property', function() { | ||
context('using automatic replacement', function() { | ||
When(function() { | ||
var e, error; | ||
try { | ||
return td.replace(this.dependency, 'notAThing'); | ||
} catch (error) { | ||
e = error; | ||
return this.error = e; | ||
} | ||
}); | ||
return Then(function() { | ||
return this.error.message === 'Error: testdouble.js - td.replace - No "notAThing" property was found.'; | ||
}); | ||
}); | ||
return context('with manual replacement', function() { | ||
Given(function() { | ||
return this.myFake = td.replace(this.dependency, 'notAThing', 'MY FAKE'); | ||
}); | ||
Then(function() { | ||
return this.myFake === 'MY FAKE'; | ||
}); | ||
And(function() { | ||
return this.myFake === this.dependency.notAThing; | ||
}); | ||
return context('is deleted following a reset', function() { | ||
Given(function() { | ||
return td.reset(); | ||
}); | ||
return Then(function() { | ||
return this.dependency.hasOwnProperty('notAThing') === false; | ||
}); | ||
}); | ||
}); | ||
}); | ||
return describe('Manually specifying the override', function() { | ||
When(function() { | ||
return this.myDouble = td.replace(this.dependency, 'honk', 'FAKE THING'); | ||
Given(function() { | ||
return this.ogWarn = console.warn; | ||
}); | ||
Then(function() { | ||
return this.myDouble === 'FAKE THING'; | ||
Given(function() { | ||
return this.warnings = []; | ||
}); | ||
return And(function() { | ||
return this.myDouble === this.dependency.honk; | ||
Given(function() { | ||
return console.warn = (function(_this) { | ||
return function(msg) { | ||
return _this.warnings.push(msg); | ||
}; | ||
})(this); | ||
}); | ||
afterEach(function() { | ||
return console.warn = this.ogWarn; | ||
}); | ||
context('with a matching type', function() { | ||
Given(function() { | ||
return this.originalHonk = this.dependency.honk; | ||
}); | ||
When(function() { | ||
return this.myDouble = td.replace(this.dependency, 'honk', function() { | ||
return 'FAKE THING'; | ||
}); | ||
}); | ||
Then(function() { | ||
return this.myDouble() === 'FAKE THING'; | ||
}); | ||
And(function() { | ||
return this.myDouble === this.dependency.honk; | ||
}); | ||
And(function() { | ||
return this.warnings.length === 0; | ||
}); | ||
return context('is restored following a reset', function() { | ||
When(function() { | ||
return td.reset(); | ||
}); | ||
return Then(function() { | ||
return this.dependency.honk === this.originalHonk; | ||
}); | ||
}); | ||
}); | ||
context('with mismatched types', function() { | ||
Given(function() { | ||
return this.dependency.lol = 5; | ||
}); | ||
When(function() { | ||
return td.replace(this.dependency, 'lol', 'foo'); | ||
}); | ||
return Then(function() { | ||
return this.warnings[0] === "Warning: testdouble.js - td.replace - property \"lol\" 5 (Number) was replaced with \"foo\", which has a different type (String)."; | ||
}); | ||
}); | ||
return context('where the actual is not defined', function() { | ||
When(function() { | ||
return td.replace(this.dependency, 'naw', 'lol'); | ||
}); | ||
return Then(function() { | ||
return this.warnings.length === 0; | ||
}); | ||
}); | ||
}); | ||
}); | ||
return describe('Node.js-specific module replacement', function() { | ||
if (!require('lodash').isFunction(require('quibble'))) { | ||
if (!NODE_JS) { | ||
return; | ||
@@ -138,0 +283,0 @@ } |
@@ -9,3 +9,3 @@ // Generated by CoffeeScript 1.10.0 | ||
Given(function() { | ||
return this.subject = require('../../../src/stringify/anything'); | ||
return this.subject = requireSource('stringify/anything'); | ||
}); | ||
@@ -12,0 +12,0 @@ Then(function() { |
@@ -10,27 +10,27 @@ // Generated by CoffeeScript 1.10.0 | ||
Then(function() { | ||
return td.when === require('../../src/when'); | ||
return td.when === requireSource('when'); | ||
}); | ||
Then(function() { | ||
return td.verify === require('../../src/verify'); | ||
return td.verify === requireSource('verify'); | ||
}); | ||
Then(function() { | ||
return td["function"] === require('../../src/function'); | ||
return td["function"] === requireSource('function'); | ||
}); | ||
Then(function() { | ||
return td.object === require('../../src/object'); | ||
return td.object === requireSource('object'); | ||
}); | ||
Then(function() { | ||
return td.matchers === require('../../src/matchers'); | ||
return td.matchers === requireSource('matchers'); | ||
}); | ||
Then(function() { | ||
return td.callback === require('../../src/matchers/callback'); | ||
return td.callback === requireSource('matchers/callback'); | ||
}); | ||
Then(function() { | ||
return td.explain === require('../../src/explain'); | ||
return td.explain === requireSource('explain'); | ||
}); | ||
Then(function() { | ||
return td.reset === require('../../src/reset'); | ||
return td.reset === requireSource('reset'); | ||
}); | ||
Then(function() { | ||
return td.replace === require('../../src/replace/index'); | ||
return td.replace === requireSource('replace/index'); | ||
}); | ||
@@ -37,0 +37,0 @@ return Then(function() { |
@@ -136,3 +136,3 @@ // Generated by CoffeeScript 1.10.0 | ||
}; | ||
})(this)), "No test double invocation detected for `verify()`.\n\n Usage:\n verify(myTestDouble('foo'))"); | ||
})(this)), "Error: testdouble.js - td.verify - No test double invocation detected for `verify()`.\n\n Usage:\n verify(myTestDouble('foo'))"); | ||
}); | ||
@@ -139,0 +139,0 @@ }); |
@@ -179,2 +179,19 @@ // Generated by CoffeeScript 1.10.0 | ||
}); | ||
describe('stubbing error, no invocation found', function() { | ||
Given(function() { | ||
return td.reset(); | ||
}); | ||
Given(function() { | ||
var e, error; | ||
try { | ||
return td.when().thenReturn('hi'); | ||
} catch (error) { | ||
e = error; | ||
return this.error = e; | ||
} | ||
}); | ||
return Then(function() { | ||
return this.error.message === "Error: testdouble.js - td.when - No test double invocation call detected for `when()`.\n\n Usage:\n when(myTestDouble('foo')).thenReturn('bar')"; | ||
}); | ||
}); | ||
return describe('config object', function() { | ||
@@ -181,0 +198,0 @@ describe('ignoring extra arguments', function() { |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var _, create, stringifyArguments; | ||
var _, create, log, stringifyArguments; | ||
_ = require('lodash'); | ||
log = require('../log'); | ||
create = require('./create'); | ||
@@ -66,3 +68,3 @@ | ||
} else { | ||
throw new Error("the contains() matcher only supports strings, arrays, and plain objects"); | ||
return log.error("td.matchers.contains", "this matcher only supports strings, arrays, and plain objects"); | ||
} | ||
@@ -69,0 +71,0 @@ }); |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var _, isConstructor, object, tdFunction, wrapWithConstructor; | ||
var _, isConstructor, log, object, stringifyAnything, tdFunction, wrapWithConstructor; | ||
@@ -11,2 +11,4 @@ _ = require('lodash'); | ||
log = require('../log'); | ||
isConstructor = require('./is-constructor'); | ||
@@ -16,7 +18,11 @@ | ||
stringifyAnything = require('../stringify/anything'); | ||
module.exports = function(realThing, optionalName) { | ||
if (isConstructor(realThing) || _.isPlainObject(realThing)) { | ||
return object(realThing); | ||
} else if (_.isFunction(realThing)) { | ||
return tdFunction((realThing != null ? realThing.name : void 0) ? realThing.name : optionalName); | ||
} else { | ||
return tdFunction((realThing != null ? realThing.name : void 0) ? realThing.name : optionalName); | ||
return log.error("td.replace", "\"" + optionalName + "\" property was found, but test double only knows how to replace functions, constructors, & objects containing functions (its value was " + (stringifyAnything(realThing)) + ")."); | ||
} | ||
@@ -23,0 +29,0 @@ }; |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var ensurePropertyExists, imitate, isConstructor, reset, wrapIfNeeded, wrapWithConstructor; | ||
var _, imitate, isConstructor, log, reset, stringifyAnything, warnIfTypeMismatch, wrapIfNeeded, wrapWithConstructor; | ||
@@ -11,22 +11,30 @@ imitate = require('./imitate'); | ||
log = require('../log'); | ||
reset = require('../reset'); | ||
stringifyAnything = require('../stringify/anything'); | ||
_ = require('lodash'); | ||
module.exports = function(object, property, manualReplacement) { | ||
var fakeThing, realThing; | ||
ensurePropertyExists(object, property); | ||
var fakeThing, isManual, realThing, realThingExists; | ||
isManual = arguments.length > 2; | ||
realThingExists = object[property] || object.hasOwnProperty(property); | ||
if (!isManual && !realThingExists) { | ||
log.error("td.replace", "No \"" + property + "\" property was found."); | ||
} | ||
realThing = object[property]; | ||
fakeThing = arguments.length > 2 ? manualReplacement : imitate(realThing, property); | ||
fakeThing = isManual ? (warnIfTypeMismatch(property, manualReplacement, realThing), manualReplacement) : imitate(realThing, property); | ||
object[property] = wrapIfNeeded(fakeThing, realThing); | ||
reset.onNextReset(function() { | ||
return object[property] = realThing; | ||
if (realThingExists) { | ||
return object[property] = realThing; | ||
} else { | ||
return delete object[property]; | ||
} | ||
}); | ||
object[property] = wrapIfNeeded(fakeThing, realThing); | ||
return fakeThing; | ||
}; | ||
ensurePropertyExists = function(object, property) { | ||
if (!object.hasOwnProperty(property)) { | ||
throw new Error("td.replace error: No \"" + property + "\" property was found."); | ||
} | ||
}; | ||
wrapIfNeeded = function(fakeThing, realThing) { | ||
@@ -40,2 +48,14 @@ if (isConstructor(realThing)) { | ||
warnIfTypeMismatch = function(property, fakeThing, realThing) { | ||
var fakeType, realType; | ||
if (realThing === void 0) { | ||
return; | ||
} | ||
fakeType = typeof fakeThing; | ||
realType = typeof realThing; | ||
if (fakeType !== realType) { | ||
return log.warn("td.replace", "property \"" + property + "\" " + (stringifyAnything(realThing)) + " (" + (_.capitalize(realType)) + ") was replaced with " + (stringifyAnything(fakeThing)) + ", which has a different type (" + (_.capitalize(fakeType)) + ")."); | ||
} | ||
}; | ||
}).call(this); |
@@ -13,2 +13,6 @@ // Generated by CoffeeScript 1.10.0 | ||
store.onReset(function() { | ||
return lastCall = null; | ||
}); | ||
module.exports = { | ||
@@ -15,0 +19,0 @@ log: function(testDouble, args, context) { |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var _, globalStore, initialEntryFor; | ||
var EventEmitter, _, globalStore, initialEntryFor, storeEmitter; | ||
_ = require('lodash'); | ||
EventEmitter = require('events'); | ||
storeEmitter = new EventEmitter(); | ||
globalStore = []; | ||
module.exports = { | ||
onReset: function(func) { | ||
return storeEmitter.on('reset', func); | ||
}, | ||
reset: function() { | ||
return globalStore = []; | ||
globalStore = []; | ||
return storeEmitter.emit('reset'); | ||
}, | ||
@@ -13,0 +21,0 @@ "for": function(testDouble, createIfNew) { |
@@ -9,6 +9,7 @@ // Generated by CoffeeScript 1.10.0 | ||
matchers: require('./matchers/index'), | ||
callback: require('./matchers/callback'), | ||
replace: require('./replace/index'), | ||
explain: require('./explain'), | ||
replace: require('./replace/index'), | ||
reset: require('./reset'), | ||
config: require('./config'), | ||
callback: require('./matchers/callback'), | ||
version: require('./version') | ||
@@ -15,0 +16,0 @@ }; |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var _, callsStore, invocationSummary, store, stringifyArgs, stringifyName, timesMessage, unsatisfiedErrorMessage; | ||
var _, callsStore, invocationSummary, log, store, stringifyArgs, stringifyName, timesMessage, unsatisfiedErrorMessage; | ||
@@ -13,2 +13,4 @@ _ = require('lodash'); | ||
log = require('./log'); | ||
module.exports = function(__userDoesPretendInvocationHere__, config) { | ||
@@ -23,6 +25,6 @@ var last; | ||
} else { | ||
throw new Error(unsatisfiedErrorMessage(last.testDouble, last.args, config)); | ||
return log.fail(unsatisfiedErrorMessage(last.testDouble, last.args, config)); | ||
} | ||
} else { | ||
throw new Error("No test double invocation detected for `verify()`.\n\n Usage:\n verify(myTestDouble('foo'))"); | ||
return log.error("td.verify", "No test double invocation detected for `verify()`.\n\n Usage:\n verify(myTestDouble('foo'))"); | ||
} | ||
@@ -29,0 +31,0 @@ }; |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
module.exports = '1.2.0'; | ||
module.exports = '1.3.0'; | ||
}).call(this); |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var _, addStubbing, callback, calls, concatImpliedCallback, stubbings, | ||
var _, addStubbing, callback, calls, concatImpliedCallback, log, stubbings, | ||
slice = [].slice; | ||
@@ -14,2 +14,4 @@ | ||
log = require('./log'); | ||
module.exports = function(__userDoesPretendInvocationHere__, config) { | ||
@@ -52,3 +54,3 @@ if (config == null) { | ||
} else { | ||
throw new Error("No test double invocation call detected for `when()`.\n\n Usage:\n when(myTestDouble('foo')).thenReturn('bar')"); | ||
return log.error("td.when", "No test double invocation call detected for `when()`.\n\n Usage:\n when(myTestDouble('foo')).thenReturn('bar')"); | ||
} | ||
@@ -55,0 +57,0 @@ }; |
{ | ||
"name": "testdouble", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "A minimal test double library for TDD with JavaScript", | ||
@@ -17,3 +17,4 @@ "homepage": "https://github.com/testdouble/testdouble.js", | ||
"scripts": { | ||
"clean": "rm -rf generated dist lib && git checkout -- dist", | ||
"clean:dist": "git checkout -- dist", | ||
"clean": "rm -rf generated dist lib .coverage && npm run clean:dist", | ||
"compile:node": "coffee --output lib --compile src", | ||
@@ -23,3 +24,7 @@ "compile:test": "coffee --output generated/test --compile test", | ||
"compile": "npm run compile:node && npm run compile:test && npm run compile:browser", | ||
"test": "mocha --ui mocha-given --reporter $npm_package_config_mocha_reporter --compilers coffee:coffee-script --recursive test/node-helper.coffee test/src", | ||
"test": "mocha --ui mocha-given --reporter $npm_package_config_mocha_reporter --compilers coffee:coffee-script $EXTRA_MOCHA_ARGS --recursive test/node-helper.coffee test/src", | ||
"test:cover:instrument": "istanbul instrument lib -o .coverage/lib", | ||
"test:cover:run": "EXTRA_MOCHA_ARGS=\"--reporter mocha-istanbul\" COVER=.coverage/lib ISTANBUL_REPORT_DIR=.coverage ISTANBUL_REPORTERS=lcov,html npm run test", | ||
"test:cover:report": "codeclimate-test-reporter < .coverage/lcov.info", | ||
"test:cover": "npm run compile:node && npm run test:cover:instrument && npm run test:cover:run", | ||
"test:browser": "npm run compile && testem ci", | ||
@@ -31,3 +36,3 @@ "test:example:webpack": "cd examples/webpack && npm i && npm test & cd ../..", | ||
"test:all": "npm run test --testdouble:mocha_reporter=tap && testem ci && npm run test:example", | ||
"test:ci": "npm run clean && npm run compile && npm run test:all", | ||
"test:ci": "npm run clean && npm run compile && npm run test:all && npm run clean:dist", | ||
"test:debug": "npm test -- --debug-brk", | ||
@@ -52,7 +57,10 @@ "version:write": "echo \"module.exports = '$npm_package_version'\" > src/version.coffee", | ||
"chai": "^3.2.0", | ||
"codeclimate-test-reporter": "^0.3.1", | ||
"coffee-script": "^1.10.0", | ||
"disc": "^1.3.2", | ||
"headerify": "^1.0.1", | ||
"istanbul": "^0.4.2", | ||
"mocha": "^2.3.1", | ||
"mocha-given": "^0.1.3", | ||
"mocha-istanbul": "arikon/mocha-istanbul", | ||
"testem": "^0.9.4" | ||
@@ -59,0 +67,0 @@ }, |
# testdouble.js | ||
[![Build Status](https://secure.travis-ci.org/testdouble/testdouble.js.svg)](http://travis-ci.org/testdouble/testdouble.js) [![npmjs](https://img.shields.io/badge/npm-testdouble-red.svg)](https://www.npmjs.com/package/testdouble) | ||
[![Test Coverage](https://codeclimate.com/github/testdouble/testdouble.js/badges/coverage.svg)](https://codeclimate.com/github/testdouble/testdouble.js/coverage) | ||
@@ -25,13 +26,34 @@ Welcome! Are you writing JavaScript tests and in the market for a mocking library to | ||
Before diving into our in-depth docs, here are a couple demo GIFs of the basic | ||
uses: | ||
Before diving into our in-depth docs, here is a quick intro of the basic uses: | ||
### Stubbing return values for functions | ||
![simple stubbing example animation](docs/img/stub.gif) | ||
```js | ||
var td = require('testdouble'); | ||
var fetch = td.function(); | ||
td.when(fetch(42)).thenReturn('Jane User'); | ||
fetch(42); // -> 'Jane User' | ||
``` | ||
### Verifying a function was invoked | ||
![simple verification of a function invocation](docs/img/verify.gif) | ||
```js | ||
var td = require('testdouble'); | ||
var save = td.function('.save'); | ||
save(41, 'Jane'); | ||
td.verify(save(41, 'Jill')); | ||
// | ||
// Error: Unsatisfied verification on test double `.save`. | ||
// | ||
// Wanted: | ||
// - called with `(41, "Jill")`. | ||
// | ||
// But was actually called: | ||
// - called with `(41, "Jane")`. | ||
``` | ||
## Docs | ||
@@ -38,0 +60,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
154
17258
127
749360
11
8