diff --git a/getter.js b/getter.js index c63b32b..190081e 100644 --- a/getter.js +++ b/getter.js @@ -129,14 +129,13 @@ var toConsumableArray = function (arr) { }; var LAZY_VARS_FIELD = symbol.for('__lazyVars'); -var noop = function noop() {}; var VariableMetadata = function () { - function VariableMetadata(name, definition) { + function VariableMetadata(name, definition, metadata) { classCallCheck(this, VariableMetadata); this.value = definition; - this.parent = null; + this.parent = metadata; this.names = defineProperty({}, name, true); } @@ -154,9 +153,7 @@ var VariableMetadata = function () { }, { key: 'evaluate', value: function evaluate() { - var value = this.value; - - return typeof value === 'function' ? value() : value; + return typeof this.value === 'function' ? this.value() : this.value; } }]); return VariableMetadata; @@ -184,7 +181,7 @@ var Metadata = function () { value: function setVirtual(context, metadata) { var virtualMetadata = Object.create(metadata); - virtualMetadata.releaseVars = noop; + virtualMetadata.values = {}; context[LAZY_VARS_FIELD] = virtualMetadata; } }]); @@ -201,17 +198,18 @@ var Metadata = function () { createClass(Metadata, [{ key: 'getVar', value: function getVar(name) { - if (!this.values.hasOwnProperty(name)) { + if (!this.values.hasOwnProperty(name) && this.defs[name]) { this.hasValues = true; - if (this.defs[name] instanceof VariableMetadata) { - this.values[name] = this.defs[name].evaluate(); - } else { - this.values[name] = undefined; - } + this.values[name] = this.evaluate(name); } return this.values[name]; } + }, { + key: 'evaluate', + value: function evaluate(name) { + return this.defs[name].evaluate(); + } }, { key: 'addChild', value: function addChild(child) { @@ -226,7 +224,7 @@ var Metadata = function () { } this.defined = true; - this.defs[name] = new VariableMetadata(name, definition); + this.defs[name] = new VariableMetadata(name, definition, this); return this; } @@ -243,6 +241,18 @@ var Metadata = function () { this.hasValues = false; } } + }, { + key: 'lookupMetadataFor', + value: function lookupMetadataFor(varName) { + var varMeta = this.defs[varName]; + var definedIn = varMeta.parent; + + if (!varMeta || !definedIn.parent.defs[varName]) { + throw new Error('Unknown parent variable "' + varName + '".'); + } + + return definedIn.parent; + } }]); return Metadata; }(); @@ -268,6 +278,10 @@ var Variable = function () { }, { key: 'evaluate', value: function evaluate(varName, options) { + if (!options.in) { + throw new Error('It looke like you are trying to evaluate "' + varName + '" too early'); + } + var variable = Variable.fromStack(options.in); if (variable.isSame(varName)) { @@ -278,7 +292,7 @@ var Variable = function () { variable = Variable.allocate(varName, options); return variable.value(); } finally { - variable.release(); + variable.pullFromStack(); } } }, { @@ -293,7 +307,7 @@ var Variable = function () { this.name = varName; this.context = context; - this.meta = context ? Metadata$1.of(context) : null; + this.evaluationMeta = context ? Metadata$1.of(context) : null; } createClass(Variable, [{ @@ -304,8 +318,7 @@ var Variable = function () { }, { key: 'value', value: function value() { - // console.log('<-------', this.context.result.description) - return Metadata$1.of(this.context).getVar(this.name); + return this.evaluationMeta.getVar(this.name); } }, { key: 'addToStack', @@ -316,33 +329,22 @@ var Variable = function () { return this; } }, { - key: 'release', - value: function release() { + key: 'pullFromStack', + value: function pullFromStack() { this.context[CURRENTLY_RETRIEVED_VAR_FIELD].pop(); } }, { key: 'valueInParentContext', value: function valueInParentContext(varOrAliasName) { - var prevMeta = this.meta; + var meta = this.evaluationMeta; try { - this.meta = this.getParentMetadataFor(varOrAliasName); - return this.meta.getVar(varOrAliasName); + this.evaluationMeta = meta.lookupMetadataFor(varOrAliasName); + return this.evaluationMeta.evaluate(varOrAliasName); } finally { - this.meta = prevMeta; + this.evaluationMeta = meta; } } - }, { - key: 'getParentMetadataFor', - value: function getParentMetadataFor(varName) { - var metadata$$1 = this.meta; - - if (!metadata$$1 || !metadata$$1.defs[varName]) { - throw new Error('Unknown parent variable "' + varName + '".'); - } - - return metadata$$1.parent; - } }]); return Variable; }(); @@ -428,25 +430,13 @@ var SuiteTracker = function () { classCallCheck(this, SuiteTracker); this.state = { currentlyDefinedSuite: config.rootSuite }; - this.suiteTracker = config.suiteTracker || this.createSuiteTracker(); + this.suiteTracker = config.suiteTracker; this.suites = []; + this.cleanUpCurrentContext = this.cleanUpCurrentContext.bind(this); + this.cleanUpCurrentAndRestorePrevContext = this.cleanUpCurrentAndRestorePrevContext.bind(this); } createClass(SuiteTracker, [{ - key: 'createSuiteTracker', - value: function createSuiteTracker() { - return { - before: function before(tracker, suite) { - suite.beforeAll(tracker.registerSuite); - }, - after: function after(tracker, suite) { - suite.beforeAll(tracker.cleanUp); - suite.afterEach(tracker.cleanUp); - suite.afterAll(tracker.cleanUpAndRestorePrev); - } - }; - } - }, { key: 'wrapSuite', value: function wrapSuite(describe) { var tracker = this; @@ -482,24 +472,13 @@ var SuiteTracker = function () { }, { key: 'execute', value: function execute(defineTests, suite, args) { - var tracker = this.buildRuntimeTrackerFor(suite); - - this.suiteTracker.before(tracker, suite); + this.suiteTracker.before(this, suite); defineTests.apply(suite, args); if (Metadata$2.of(suite)) { - this.suiteTracker.after(tracker, suite); + this.suiteTracker.after(this, suite); } } - }, { - key: 'buildRuntimeTrackerFor', - value: function buildRuntimeTrackerFor(suite) { - return { - registerSuite: this.registerSuite.bind(this, suite), - cleanUp: this.cleanUp.bind(this, suite), - cleanUpAndRestorePrev: this.cleanUpAndRestorePrev.bind(this, suite) - }; - } }, { key: 'isRoot', value: function isRoot(suite) { @@ -543,10 +522,15 @@ var SuiteTracker = function () { } } }, { - key: 'cleanUpAndRestorePrev', - value: function cleanUpAndRestorePrev(context) { + key: 'cleanUpCurrentContext', + value: function cleanUpCurrentContext() { + this.cleanUp(this.currentContext); + } + }, { + key: 'cleanUpCurrentAndRestorePrevContext', + value: function cleanUpCurrentAndRestorePrevContext() { + this.cleanUpCurrentContext(); this.state.currentTestContext = this.state.prevTestContext; - return this.cleanUp(context); } }, { key: 'currentContext', @@ -566,13 +550,12 @@ var suite_tracker = SuiteTracker; function createSuiteTracker() { return { - before: function before(tracker) { - commonjsGlobal.beforeAll(tracker.registerSuite); - commonjsGlobal.afterEach(tracker.cleanUp); - commonjsGlobal.afterAll(tracker.cleanUpAndRestorePrev); + before: function before(tracker, suite) { + commonjsGlobal.beforeAll(tracker.registerSuite.bind(tracker, suite)); + commonjsGlobal.afterAll(tracker.cleanUpCurrentAndRestorePrevContext); }, after: function after(tracker) { - commonjsGlobal.beforeAll(tracker.cleanUp); + commonjsGlobal.beforeAll(tracker.cleanUpCurrentContext); } }; } @@ -586,6 +569,7 @@ function addInterface(rootSuite, options) { context.describe = tracker.wrapSuite(context.describe); context.xdescribe = tracker.wrapSuite(context.xdescribe); context.fdescribe = tracker.wrapSuite(context.fdescribe); + commonjsGlobal.afterEach(tracker.cleanUpCurrentContext); return context; } @@ -611,9 +595,22 @@ var jest = jasmine; // eslint-disable-line +function createSuiteTracker$1() { + return { + before: function before(tracker, suite) { + suite.beforeAll(tracker.registerSuite.bind(tracker, suite)); + }, + after: function after(tracker, suite) { + suite.beforeAll(tracker.cleanUpCurrentContext); + suite.afterAll(tracker.cleanUpCurrentAndRestorePrevContext); + } + }; +} + function addInterface$1(rootSuite, options) { - var tracker = new options.Tracker({ rootSuite: rootSuite }); + var tracker = new options.Tracker({ rootSuite: rootSuite, suiteTracker: createSuiteTracker$1() }); + rootSuite.afterEach(tracker.cleanUpCurrentContext); rootSuite.on('pre-require', function (context) { var ui = _interface$2(context, tracker, options); var describe = context.describe; diff --git a/global.js b/global.js index 75d4904..efeb557 100644 --- a/global.js +++ b/global.js @@ -129,14 +129,13 @@ var toConsumableArray = function (arr) { }; var LAZY_VARS_FIELD = symbol.for('__lazyVars'); -var noop = function noop() {}; var VariableMetadata = function () { - function VariableMetadata(name, definition) { + function VariableMetadata(name, definition, metadata) { classCallCheck(this, VariableMetadata); this.value = definition; - this.parent = null; + this.parent = metadata; this.names = defineProperty({}, name, true); } @@ -154,9 +153,7 @@ var VariableMetadata = function () { }, { key: 'evaluate', value: function evaluate() { - var value = this.value; - - return typeof value === 'function' ? value() : value; + return typeof this.value === 'function' ? this.value() : this.value; } }]); return VariableMetadata; @@ -184,7 +181,7 @@ var Metadata = function () { value: function setVirtual(context, metadata) { var virtualMetadata = Object.create(metadata); - virtualMetadata.releaseVars = noop; + virtualMetadata.values = {}; context[LAZY_VARS_FIELD] = virtualMetadata; } }]); @@ -201,17 +198,18 @@ var Metadata = function () { createClass(Metadata, [{ key: 'getVar', value: function getVar(name) { - if (!this.values.hasOwnProperty(name)) { + if (!this.values.hasOwnProperty(name) && this.defs[name]) { this.hasValues = true; - if (this.defs[name] instanceof VariableMetadata) { - this.values[name] = this.defs[name].evaluate(); - } else { - this.values[name] = undefined; - } + this.values[name] = this.evaluate(name); } return this.values[name]; } + }, { + key: 'evaluate', + value: function evaluate(name) { + return this.defs[name].evaluate(); + } }, { key: 'addChild', value: function addChild(child) { @@ -226,7 +224,7 @@ var Metadata = function () { } this.defined = true; - this.defs[name] = new VariableMetadata(name, definition); + this.defs[name] = new VariableMetadata(name, definition, this); return this; } @@ -243,6 +241,18 @@ var Metadata = function () { this.hasValues = false; } } + }, { + key: 'lookupMetadataFor', + value: function lookupMetadataFor(varName) { + var varMeta = this.defs[varName]; + var definedIn = varMeta.parent; + + if (!varMeta || !definedIn.parent.defs[varName]) { + throw new Error('Unknown parent variable "' + varName + '".'); + } + + return definedIn.parent; + } }]); return Metadata; }(); @@ -268,6 +278,10 @@ var Variable = function () { }, { key: 'evaluate', value: function evaluate(varName, options) { + if (!options.in) { + throw new Error('It looke like you are trying to evaluate "' + varName + '" too early'); + } + var variable = Variable.fromStack(options.in); if (variable.isSame(varName)) { @@ -278,7 +292,7 @@ var Variable = function () { variable = Variable.allocate(varName, options); return variable.value(); } finally { - variable.release(); + variable.pullFromStack(); } } }, { @@ -293,7 +307,7 @@ var Variable = function () { this.name = varName; this.context = context; - this.meta = context ? Metadata$1.of(context) : null; + this.evaluationMeta = context ? Metadata$1.of(context) : null; } createClass(Variable, [{ @@ -304,8 +318,7 @@ var Variable = function () { }, { key: 'value', value: function value() { - // console.log('<-------', this.context.result.description) - return Metadata$1.of(this.context).getVar(this.name); + return this.evaluationMeta.getVar(this.name); } }, { key: 'addToStack', @@ -316,33 +329,22 @@ var Variable = function () { return this; } }, { - key: 'release', - value: function release() { + key: 'pullFromStack', + value: function pullFromStack() { this.context[CURRENTLY_RETRIEVED_VAR_FIELD].pop(); } }, { key: 'valueInParentContext', value: function valueInParentContext(varOrAliasName) { - var prevMeta = this.meta; + var meta = this.evaluationMeta; try { - this.meta = this.getParentMetadataFor(varOrAliasName); - return this.meta.getVar(varOrAliasName); + this.evaluationMeta = meta.lookupMetadataFor(varOrAliasName); + return this.evaluationMeta.evaluate(varOrAliasName); } finally { - this.meta = prevMeta; + this.evaluationMeta = meta; } } - }, { - key: 'getParentMetadataFor', - value: function getParentMetadataFor(varName) { - var metadata$$1 = this.meta; - - if (!metadata$$1 || !metadata$$1.defs[varName]) { - throw new Error('Unknown parent variable "' + varName + '".'); - } - - return metadata$$1.parent; - } }]); return Variable; }(); @@ -428,25 +430,13 @@ var SuiteTracker = function () { classCallCheck(this, SuiteTracker); this.state = { currentlyDefinedSuite: config.rootSuite }; - this.suiteTracker = config.suiteTracker || this.createSuiteTracker(); + this.suiteTracker = config.suiteTracker; this.suites = []; + this.cleanUpCurrentContext = this.cleanUpCurrentContext.bind(this); + this.cleanUpCurrentAndRestorePrevContext = this.cleanUpCurrentAndRestorePrevContext.bind(this); } createClass(SuiteTracker, [{ - key: 'createSuiteTracker', - value: function createSuiteTracker() { - return { - before: function before(tracker, suite) { - suite.beforeAll(tracker.registerSuite); - }, - after: function after(tracker, suite) { - suite.beforeAll(tracker.cleanUp); - suite.afterEach(tracker.cleanUp); - suite.afterAll(tracker.cleanUpAndRestorePrev); - } - }; - } - }, { key: 'wrapSuite', value: function wrapSuite(describe) { var tracker = this; @@ -482,24 +472,13 @@ var SuiteTracker = function () { }, { key: 'execute', value: function execute(defineTests, suite, args) { - var tracker = this.buildRuntimeTrackerFor(suite); - - this.suiteTracker.before(tracker, suite); + this.suiteTracker.before(this, suite); defineTests.apply(suite, args); if (Metadata$2.of(suite)) { - this.suiteTracker.after(tracker, suite); + this.suiteTracker.after(this, suite); } } - }, { - key: 'buildRuntimeTrackerFor', - value: function buildRuntimeTrackerFor(suite) { - return { - registerSuite: this.registerSuite.bind(this, suite), - cleanUp: this.cleanUp.bind(this, suite), - cleanUpAndRestorePrev: this.cleanUpAndRestorePrev.bind(this, suite) - }; - } }, { key: 'isRoot', value: function isRoot(suite) { @@ -543,10 +522,15 @@ var SuiteTracker = function () { } } }, { - key: 'cleanUpAndRestorePrev', - value: function cleanUpAndRestorePrev(context) { + key: 'cleanUpCurrentContext', + value: function cleanUpCurrentContext() { + this.cleanUp(this.currentContext); + } + }, { + key: 'cleanUpCurrentAndRestorePrevContext', + value: function cleanUpCurrentAndRestorePrevContext() { + this.cleanUpCurrentContext(); this.state.currentTestContext = this.state.prevTestContext; - return this.cleanUp(context); } }, { key: 'currentContext', @@ -566,13 +550,12 @@ var suite_tracker = SuiteTracker; function createSuiteTracker() { return { - before: function before(tracker) { - commonjsGlobal.beforeAll(tracker.registerSuite); - commonjsGlobal.afterEach(tracker.cleanUp); - commonjsGlobal.afterAll(tracker.cleanUpAndRestorePrev); + before: function before(tracker, suite) { + commonjsGlobal.beforeAll(tracker.registerSuite.bind(tracker, suite)); + commonjsGlobal.afterAll(tracker.cleanUpCurrentAndRestorePrevContext); }, after: function after(tracker) { - commonjsGlobal.beforeAll(tracker.cleanUp); + commonjsGlobal.beforeAll(tracker.cleanUpCurrentContext); } }; } @@ -586,6 +569,7 @@ function addInterface(rootSuite, options) { context.describe = tracker.wrapSuite(context.describe); context.xdescribe = tracker.wrapSuite(context.xdescribe); context.fdescribe = tracker.wrapSuite(context.fdescribe); + commonjsGlobal.afterEach(tracker.cleanUpCurrentContext); return context; } @@ -611,9 +595,22 @@ var jest = jasmine; // eslint-disable-line +function createSuiteTracker$1() { + return { + before: function before(tracker, suite) { + suite.beforeAll(tracker.registerSuite.bind(tracker, suite)); + }, + after: function after(tracker, suite) { + suite.beforeAll(tracker.cleanUpCurrentContext); + suite.afterAll(tracker.cleanUpCurrentAndRestorePrevContext); + } + }; +} + function addInterface$1(rootSuite, options) { - var tracker = new options.Tracker({ rootSuite: rootSuite }); + var tracker = new options.Tracker({ rootSuite: rootSuite, suiteTracker: createSuiteTracker$1() }); + rootSuite.afterEach(tracker.cleanUpCurrentContext); rootSuite.on('pre-require', function (context) { var ui = _interface$2(context, tracker, options); var describe = context.describe; diff --git a/index.js b/index.js index 3946f78..dc8752c 100644 --- a/index.js +++ b/index.js @@ -129,14 +129,13 @@ var toConsumableArray = function (arr) { }; var LAZY_VARS_FIELD = symbol.for('__lazyVars'); -var noop = function noop() {}; var VariableMetadata = function () { - function VariableMetadata(name, definition) { + function VariableMetadata(name, definition, metadata) { classCallCheck(this, VariableMetadata); this.value = definition; - this.parent = null; + this.parent = metadata; this.names = defineProperty({}, name, true); } @@ -154,9 +153,7 @@ var VariableMetadata = function () { }, { key: 'evaluate', value: function evaluate() { - var value = this.value; - - return typeof value === 'function' ? value() : value; + return typeof this.value === 'function' ? this.value() : this.value; } }]); return VariableMetadata; @@ -184,7 +181,7 @@ var Metadata = function () { value: function setVirtual(context, metadata) { var virtualMetadata = Object.create(metadata); - virtualMetadata.releaseVars = noop; + virtualMetadata.values = {}; context[LAZY_VARS_FIELD] = virtualMetadata; } }]); @@ -201,17 +198,18 @@ var Metadata = function () { createClass(Metadata, [{ key: 'getVar', value: function getVar(name) { - if (!this.values.hasOwnProperty(name)) { + if (!this.values.hasOwnProperty(name) && this.defs[name]) { this.hasValues = true; - if (this.defs[name] instanceof VariableMetadata) { - this.values[name] = this.defs[name].evaluate(); - } else { - this.values[name] = undefined; - } + this.values[name] = this.evaluate(name); } return this.values[name]; } + }, { + key: 'evaluate', + value: function evaluate(name) { + return this.defs[name].evaluate(); + } }, { key: 'addChild', value: function addChild(child) { @@ -226,7 +224,7 @@ var Metadata = function () { } this.defined = true; - this.defs[name] = new VariableMetadata(name, definition); + this.defs[name] = new VariableMetadata(name, definition, this); return this; } @@ -243,6 +241,18 @@ var Metadata = function () { this.hasValues = false; } } + }, { + key: 'lookupMetadataFor', + value: function lookupMetadataFor(varName) { + var varMeta = this.defs[varName]; + var definedIn = varMeta.parent; + + if (!varMeta || !definedIn.parent.defs[varName]) { + throw new Error('Unknown parent variable "' + varName + '".'); + } + + return definedIn.parent; + } }]); return Metadata; }(); @@ -268,6 +278,10 @@ var Variable = function () { }, { key: 'evaluate', value: function evaluate(varName, options) { + if (!options.in) { + throw new Error('It looke like you are trying to evaluate "' + varName + '" too early'); + } + var variable = Variable.fromStack(options.in); if (variable.isSame(varName)) { @@ -278,7 +292,7 @@ var Variable = function () { variable = Variable.allocate(varName, options); return variable.value(); } finally { - variable.release(); + variable.pullFromStack(); } } }, { @@ -293,7 +307,7 @@ var Variable = function () { this.name = varName; this.context = context; - this.meta = context ? Metadata$1.of(context) : null; + this.evaluationMeta = context ? Metadata$1.of(context) : null; } createClass(Variable, [{ @@ -304,8 +318,7 @@ var Variable = function () { }, { key: 'value', value: function value() { - // console.log('<-------', this.context.result.description) - return Metadata$1.of(this.context).getVar(this.name); + return this.evaluationMeta.getVar(this.name); } }, { key: 'addToStack', @@ -316,33 +329,22 @@ var Variable = function () { return this; } }, { - key: 'release', - value: function release() { + key: 'pullFromStack', + value: function pullFromStack() { this.context[CURRENTLY_RETRIEVED_VAR_FIELD].pop(); } }, { key: 'valueInParentContext', value: function valueInParentContext(varOrAliasName) { - var prevMeta = this.meta; + var meta = this.evaluationMeta; try { - this.meta = this.getParentMetadataFor(varOrAliasName); - return this.meta.getVar(varOrAliasName); + this.evaluationMeta = meta.lookupMetadataFor(varOrAliasName); + return this.evaluationMeta.evaluate(varOrAliasName); } finally { - this.meta = prevMeta; + this.evaluationMeta = meta; } } - }, { - key: 'getParentMetadataFor', - value: function getParentMetadataFor(varName) { - var metadata$$1 = this.meta; - - if (!metadata$$1 || !metadata$$1.defs[varName]) { - throw new Error('Unknown parent variable "' + varName + '".'); - } - - return metadata$$1.parent; - } }]); return Variable; }(); @@ -428,25 +430,13 @@ var SuiteTracker = function () { classCallCheck(this, SuiteTracker); this.state = { currentlyDefinedSuite: config.rootSuite }; - this.suiteTracker = config.suiteTracker || this.createSuiteTracker(); + this.suiteTracker = config.suiteTracker; this.suites = []; + this.cleanUpCurrentContext = this.cleanUpCurrentContext.bind(this); + this.cleanUpCurrentAndRestorePrevContext = this.cleanUpCurrentAndRestorePrevContext.bind(this); } createClass(SuiteTracker, [{ - key: 'createSuiteTracker', - value: function createSuiteTracker() { - return { - before: function before(tracker, suite) { - suite.beforeAll(tracker.registerSuite); - }, - after: function after(tracker, suite) { - suite.beforeAll(tracker.cleanUp); - suite.afterEach(tracker.cleanUp); - suite.afterAll(tracker.cleanUpAndRestorePrev); - } - }; - } - }, { key: 'wrapSuite', value: function wrapSuite(describe) { var tracker = this; @@ -482,24 +472,13 @@ var SuiteTracker = function () { }, { key: 'execute', value: function execute(defineTests, suite, args) { - var tracker = this.buildRuntimeTrackerFor(suite); - - this.suiteTracker.before(tracker, suite); + this.suiteTracker.before(this, suite); defineTests.apply(suite, args); if (Metadata$2.of(suite)) { - this.suiteTracker.after(tracker, suite); + this.suiteTracker.after(this, suite); } } - }, { - key: 'buildRuntimeTrackerFor', - value: function buildRuntimeTrackerFor(suite) { - return { - registerSuite: this.registerSuite.bind(this, suite), - cleanUp: this.cleanUp.bind(this, suite), - cleanUpAndRestorePrev: this.cleanUpAndRestorePrev.bind(this, suite) - }; - } }, { key: 'isRoot', value: function isRoot(suite) { @@ -543,10 +522,15 @@ var SuiteTracker = function () { } } }, { - key: 'cleanUpAndRestorePrev', - value: function cleanUpAndRestorePrev(context) { + key: 'cleanUpCurrentContext', + value: function cleanUpCurrentContext() { + this.cleanUp(this.currentContext); + } + }, { + key: 'cleanUpCurrentAndRestorePrevContext', + value: function cleanUpCurrentAndRestorePrevContext() { + this.cleanUpCurrentContext(); this.state.currentTestContext = this.state.prevTestContext; - return this.cleanUp(context); } }, { key: 'currentContext', @@ -566,13 +550,12 @@ var suite_tracker = SuiteTracker; function createSuiteTracker() { return { - before: function before(tracker) { - commonjsGlobal.beforeAll(tracker.registerSuite); - commonjsGlobal.afterEach(tracker.cleanUp); - commonjsGlobal.afterAll(tracker.cleanUpAndRestorePrev); + before: function before(tracker, suite) { + commonjsGlobal.beforeAll(tracker.registerSuite.bind(tracker, suite)); + commonjsGlobal.afterAll(tracker.cleanUpCurrentAndRestorePrevContext); }, after: function after(tracker) { - commonjsGlobal.beforeAll(tracker.cleanUp); + commonjsGlobal.beforeAll(tracker.cleanUpCurrentContext); } }; } @@ -586,6 +569,7 @@ function addInterface(rootSuite, options) { context.describe = tracker.wrapSuite(context.describe); context.xdescribe = tracker.wrapSuite(context.xdescribe); context.fdescribe = tracker.wrapSuite(context.fdescribe); + commonjsGlobal.afterEach(tracker.cleanUpCurrentContext); return context; } @@ -611,9 +595,22 @@ var jest = jasmine; // eslint-disable-line +function createSuiteTracker$1() { + return { + before: function before(tracker, suite) { + suite.beforeAll(tracker.registerSuite.bind(tracker, suite)); + }, + after: function after(tracker, suite) { + suite.beforeAll(tracker.cleanUpCurrentContext); + suite.afterAll(tracker.cleanUpCurrentAndRestorePrevContext); + } + }; +} + function addInterface$1(rootSuite, options) { - var tracker = new options.Tracker({ rootSuite: rootSuite }); + var tracker = new options.Tracker({ rootSuite: rootSuite, suiteTracker: createSuiteTracker$1() }); + rootSuite.afterEach(tracker.cleanUpCurrentContext); rootSuite.on('pre-require', function (context) { var ui = _interface$2(context, tracker, options); var describe = context.describe; diff --git a/lib/interface/jasmine.js b/lib/interface/jasmine.js index 56376ce..c20dc1d 100644 --- a/lib/interface/jasmine.js +++ b/lib/interface/jasmine.js @@ -3,14 +3,13 @@ const SuiteTracker = require('../suite_tracker'); function createSuiteTracker() { return { - before(tracker) { - global.beforeAll(tracker.registerSuite); - global.afterEach(tracker.cleanUp); - global.afterAll(tracker.cleanUpAndRestorePrev); + before(tracker, suite) { + global.beforeAll(tracker.registerSuite.bind(tracker, suite)); + global.afterAll(tracker.cleanUpCurrentAndRestorePrevContext); }, after(tracker) { - global.beforeAll(tracker.cleanUp); + global.beforeAll(tracker.cleanUpCurrentContext); } }; } @@ -24,6 +23,7 @@ function addInterface(rootSuite, options) { context.describe = tracker.wrapSuite(context.describe); context.xdescribe = tracker.wrapSuite(context.xdescribe); context.fdescribe = tracker.wrapSuite(context.fdescribe); + global.afterEach(tracker.cleanUpCurrentContext); return context; } diff --git a/lib/interface/mocha.js b/lib/interface/mocha.js index 2ad9a5a..d53f7a1 100644 --- a/lib/interface/mocha.js +++ b/lib/interface/mocha.js @@ -2,9 +2,23 @@ const Mocha = require('mocha'); // eslint-disable-line const createLazyVarInterface = require('../interface'); const SuiteTracker = require('../suite_tracker'); +function createSuiteTracker() { + return { + before(tracker, suite) { + suite.beforeAll(tracker.registerSuite.bind(tracker, suite)); + }, + + after(tracker, suite) { + suite.beforeAll(tracker.cleanUpCurrentContext); + suite.afterAll(tracker.cleanUpCurrentAndRestorePrevContext); + } + }; +} + function addInterface(rootSuite, options) { - const tracker = new options.Tracker({ rootSuite }); + const tracker = new options.Tracker({ rootSuite, suiteTracker: createSuiteTracker() }); + rootSuite.afterEach(tracker.cleanUpCurrentContext); rootSuite.on('pre-require', (context) => { const ui = createLazyVarInterface(context, tracker, options); const describe = context.describe; diff --git a/lib/metadata.js b/lib/metadata.js index b6734ce..865b146 100644 --- a/lib/metadata.js +++ b/lib/metadata.js @@ -1,12 +1,11 @@ const Symbol = require('./symbol'); const LAZY_VARS_FIELD = Symbol.for('__lazyVars'); -const noop = () => {}; class VariableMetadata { - constructor(name, definition) { + constructor(name, definition, metadata) { this.value = definition; - this.parent = null; + this.parent = metadata; this.names = { [name]: true }; } @@ -20,9 +19,7 @@ class VariableMetadata { } evaluate() { - const value = this.value; - - return typeof value === 'function' ? value() : value; + return typeof this.value === 'function' ? this.value() : this.value; } } @@ -44,7 +41,7 @@ class Metadata { static setVirtual(context, metadata) { const virtualMetadata = Object.create(metadata); - virtualMetadata.releaseVars = noop; + virtualMetadata.values = {}; context[LAZY_VARS_FIELD] = virtualMetadata; } @@ -58,12 +55,16 @@ class Metadata { getVar(name) { if (!this.values.hasOwnProperty(name) && this.defs[name]) { this.hasValues = true; - this.values[name] = this.defs[name].evaluate(); + this.values[name] = this.evaluate(name); } return this.values[name]; } + evaluate(name) { + return this.defs[name].evaluate(); + } + addChild(child) { child.defs = Object.assign(Object.create(this.defs), child.defs); child.parent = this.defined ? this : this.parent; @@ -75,7 +76,7 @@ class Metadata { } this.defined = true; - this.defs[name] = new VariableMetadata(name, definition); + this.defs[name] = new VariableMetadata(name, definition, this); return this; } @@ -90,6 +91,17 @@ class Metadata { this.hasValues = false; } } + + lookupMetadataFor(varName) { + const varMeta = this.defs[varName]; + const definedIn = varMeta.parent; + + if (!varMeta || !definedIn.parent.defs[varName]) { + throw new Error(`Unknown parent variable "${varName}".`); + } + + return definedIn.parent; + } } module.exports = { Metadata }; diff --git a/lib/suite_tracker.js b/lib/suite_tracker.js index 4c814de..6cc0a09 100644 --- a/lib/suite_tracker.js +++ b/lib/suite_tracker.js @@ -3,22 +3,10 @@ const { Metadata } = require('./metadata'); class SuiteTracker { constructor(config = {}) { this.state = { currentlyDefinedSuite: config.rootSuite }; - this.suiteTracker = config.suiteTracker || this.createSuiteTracker(); + this.suiteTracker = config.suiteTracker; this.suites = []; - } - - createSuiteTracker() { - return { - before(tracker, suite) { - suite.beforeAll(tracker.registerSuite); - }, - - after(tracker, suite) { - suite.beforeAll(tracker.cleanUp); - suite.afterEach(tracker.cleanUp); - suite.afterAll(tracker.cleanUpAndRestorePrev); - } - }; + this.cleanUpCurrentContext = this.cleanUpCurrentContext.bind(this); + this.cleanUpCurrentAndRestorePrevContext = this.cleanUpCurrentAndRestorePrevContext.bind(this); } get currentContext() { @@ -53,24 +41,14 @@ class SuiteTracker { } execute(defineTests, suite, args) { - const tracker = this.buildRuntimeTrackerFor(suite); - - this.suiteTracker.before(tracker, suite); + this.suiteTracker.before(this, suite); defineTests.apply(suite, args); if (Metadata.of(suite)) { - this.suiteTracker.after(tracker, suite); + this.suiteTracker.after(this, suite); } } - buildRuntimeTrackerFor(suite) { - return { - registerSuite: this.registerSuite.bind(this, suite), - cleanUp: this.cleanUp.bind(this, suite), - cleanUpAndRestorePrev: this.cleanUpAndRestorePrev.bind(this, suite) - }; - } - isRoot(suite) { return !(suite.parent ? suite.parent.parent : suite.parentSuite.parentSuite); } @@ -108,9 +86,13 @@ class SuiteTracker { } } - cleanUpAndRestorePrev(context) { + cleanUpCurrentContext() { + this.cleanUp(this.currentContext); + } + + cleanUpCurrentAndRestorePrevContext() { + this.cleanUpCurrentContext(); this.state.currentTestContext = this.state.prevTestContext; - return this.cleanUp(context); } } diff --git a/lib/variable.js b/lib/variable.js index 8e8d24d..dd9ac4b 100644 --- a/lib/variable.js +++ b/lib/variable.js @@ -12,6 +12,10 @@ class Variable { } static evaluate(varName, options) { + if (!options.in) { + throw new Error(`It looke like you are trying to evaluate "${varName}" too early`); + } + let variable = Variable.fromStack(options.in); if (variable.isSame(varName)) { @@ -22,7 +26,7 @@ class Variable { variable = Variable.allocate(varName, options); return variable.value(); } finally { - variable.release(); + variable.pullFromStack(); } } @@ -33,7 +37,7 @@ class Variable { constructor(varName, context) { this.name = varName; this.context = context; - this.meta = context ? Metadata.of(context) : null; + this.evaluationMeta = context ? Metadata.of(context) : null; } isSame(anotherVarName) { @@ -44,8 +48,7 @@ class Variable { } value() { - // console.log('<-------', this.context.result.description) - return Metadata.of(this.context).getVar(this.name); + return this.evaluationMeta.getVar(this.name); } addToStack() { @@ -55,30 +58,20 @@ class Variable { return this; } - release() { + pullFromStack() { this.context[CURRENTLY_RETRIEVED_VAR_FIELD].pop(); } valueInParentContext(varOrAliasName) { - const prevMeta = this.meta; + const meta = this.evaluationMeta; try { - this.meta = this.getParentMetadataFor(varOrAliasName); - return this.meta.getVar(varOrAliasName); + this.evaluationMeta = meta.lookupMetadataFor(varOrAliasName); + return this.evaluationMeta.evaluate(varOrAliasName); } finally { - this.meta = prevMeta; + this.evaluationMeta = meta; } } - - getParentMetadataFor(varName) { - const metadata = this.meta; - - if (!metadata || !metadata.defs[varName]) { - throw new Error(`Unknown parent variable "${varName}".`); - } - - return metadata.parent; - } } Variable.EMPTY = new Variable(null, null); diff --git a/package.json b/package.json index edef964..4b5f22f 100644 --- a/package.json +++ b/package.json @@ -74,9 +74,9 @@ "test.jest-getter": "jest --findRelatedTests spec/getter_defs_spec.js getter.js", "test.jest": "npm run test.jest-ui && npm run test.jest-global && npm run test.jest-getter", "test": "npm run test.mocha && npm run test.mocha-in-browser && npm run test.jasmine && npm run test.jasmine-in-browser && npm run test.jest", - "build.ui": "DEST_FILE=index.js SRC_FILE=bdd rollup -c tools/rollup.umd.js", - "build.global-ui": "DEST_FILE=global.js SRC_FILE=bdd_global_var rollup -c tools/rollup.umd.js", - "build.getter-ui": "DEST_FILE=getter.js SRC_FILE=bdd_getter_var rollup -c tools/rollup.umd.js", + "build.ui": "rollup -c tools/rollup.umd.js -i lib/interface/dialects/bdd.js -o index.js", + "build.global-ui": "rollup -c tools/rollup.umd.js -i lib/interface/dialects/bdd_global_var.js -o global.js", + "build.getter-ui": "rollup -c tools/rollup.umd.js -i lib/interface/dialects/bdd_getter_var.js -o getter.js", "build": "npm run build.ui && npm run build.global-ui && npm run build.getter-ui", "lint": "eslint lib" }, diff --git a/spec/interface_examples.js b/spec/interface_examples.js index 75fe1cc..cd7f493 100644 --- a/spec/interface_examples.js +++ b/spec/interface_examples.js @@ -253,4 +253,32 @@ sharedExamplesFor('Lazy Vars Interface', function(getVar) { }); }); }); + + describe('when calls variable defined in parent suites', function() { + subject(function() { + return { isRoot: getVar('isRoot') }; + }); + + def('isRoot', true); + + describe('one more level which overrides parent variable', function() { + subject(function() { + return getVar('subject').isRoot; + }); + + describe('suite that calls parent variable and redefines dependent variable', function() { + def('isRoot', false); + + it('gets the correct variable', function() { + expect(getVar('subject')).to.be.false; + }); + }); + + describe('suite that calls parent variable', function () { + it('gets the correct variable', function() { + expect(getVar('subject')).to.be.true; + }); + }); + }); + }); }); diff --git a/tools/rollup.umd.js b/tools/rollup.umd.js index a3076e9..3e705ec 100644 --- a/tools/rollup.umd.js +++ b/tools/rollup.umd.js @@ -38,7 +38,6 @@ function useSafeDependencies(deps) { export default { external: ['mocha', 'jasmine'], - input: `lib/interface/dialects/${process.env.SRC_FILE}`, output: { format: 'umd', name: MODULE_NAME, @@ -46,7 +45,6 @@ export default { mocha: 'Mocha', jasmine: 'jasmine' }, - file: process.env.DEST_FILE, }, plugins: [ commonjs({