Reputation: 1877
Context
I am writing a "testing" utility for a specific use case.
We need the tests to be in separate files, and to be really simple to write, inspired by cypress and mocha.
For now I load the tests using require
and it works well, but for the tests to be even more simple, I'd like to remove the first and last lines which are redundant.
What I have
// test.file.js :
const test = new (require("../index.js").Test)()
// to be removed
test.this(true) // test is initialized
.should("equal", true) // (syntax inspired by cypress)
test.log(__dirname)
// all node functionalities (require...)
// are available
module.exports = test // to be removed
// importing logic :
function run (filePath) {
const test = require(filePath)
test.run()
} // much simplified
Here everything works fine but you need to require the library and do some logic and export the test in each test file.
What I would like
// test.file.js
test.log("hello world")
test.this(true) // test is initialized
.should("equal", true)
test.log(__dirname) // node functions are available
Here test
is already declared, initialized and available at scope level.
Exports are also automatic.
The problem
I'd like all node core functionalities to be available in the test BUT not the scope variables where I import the file.
What I tried
I achieved to make it work using some complicated eval
, but the problem is that every local variables of the parent scopes are available for modification in the tests...
let hello = "world"
// this variable should not be available in the test
function run (testPath) {
const test = new Test()
// initialize the test
const script = readFileSync(
resolve(__dirname, testPath),
{encoding: "utf-8"}
)
const scope = {
test
} // local variables i want the function to have access to
eval(
"(function ("
+ Object.keys(scope).join(", ")
+ ") {"
+ script
+ "})"
)(...Object.values(scope))
console.log(hello)
// here hello can be modified inside the test
// this I don't want
test.run() // works
}
I also tried with new Function(script)
and some derivative but I could not find a solution
Question
How could I evaluate the test file in a clean node scope, scope with ALL the node functionalities AND only one shared variable which is test
?
Minimum reproducible example:
// test.file.js
test.log("hello from test")
test.variableProperty = "MODIFIED"
test.log(__dirname) // global node available
// test.log(hello) // should crash or hello be undefined
// index.js
class Test {
constructor () {
this.variableProperty = "INITIAL"
}
log (str) {
console.log(str)
}
run () {
console.log(this.variableProperty)
}
}
// file import logic :
function importTest (path) {
const test = new Test()
// ...
return test
}
// testing :
let hello = "should not appear"
const t = importTest("./test.file.js")
t.run()
// should output:
// "hello from test"
// (the __dirname)
// "MODIFIED"
// (and crash if last line of test.file.js uncommented)
Upvotes: 0
Views: 62