diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index 668d0db6..147c2a50 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -236,6 +236,60 @@ describe("Env integration", function() { env.execute(); }); + it("calls associated beforeAlls/afterAlls with the cascaded 'this'", function(done) { + var env = new j$.Env(); + + env.addReporter({jasmineDone: done}); + + env.describe("with beforeAll and afterAll", function() { + env.beforeAll(function() { + this.x = 1; + }); + + env.it("has an x at the root", function() { + expect(this.x).toBe(1); + }); + + env.describe("child that deletes", function() { + env.beforeAll(function() { + expect(this.x).toBe(1); + delete this.x; + }); + + env.it("has no x", function() { + expect(this.x).not.toBeDefined(); + }); + }); + + env.describe("child should still have x", function() { + env.beforeAll(function(innerDone) { + expect(this.x).toBe(1); + innerDone(); + }); + + env.it("has an x", function() { + expect(this.x).toBe(1); + delete this.x; + }); + + env.it("still has an x", function() { + expect(this.x).toBe(1); + }); + + env.it("adds a y", function() { + this.y = 2; + expect(this.y).toBe(2); + }); + + env.it("doesn't have y that was added in sibling", function() { + expect(this.y).not.toBeDefined(); + }); + }); + }); + + env.execute(); + }); + it("Allows specifying which specs and suites to run", function(done) { var env = new j$.Env(), calls = [], diff --git a/src/core/Env.js b/src/core/Env.js index 682a3923..31b96928 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -272,6 +272,7 @@ getJasmineRequireObj().Env = function(j$) { description: description, expectationResultFactory: expectationResultFactory, queueRunnerFactory: queueRunnerFactory, + userContext: function() { return suite.clonedSharedUserContext(); }, fn: fn }); diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index 4a0e66f2..f9846786 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -17,7 +17,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { this.onException = attrs.onException || function() {}; this.catchException = attrs.catchException || function() { return true; }; this.enforceTimeout = attrs.enforceTimeout || function() { return false; }; - this.userContext = {}; + this.userContext = attrs.userContext || {}; this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; } diff --git a/src/core/Spec.js b/src/core/Spec.js index 0e1135f7..e28050fd 100644 --- a/src/core/Spec.js +++ b/src/core/Spec.js @@ -7,6 +7,7 @@ getJasmineRequireObj().Spec = function(j$) { this.fn = attrs.fn; this.beforeFns = attrs.beforeFns || function() { return []; }; this.afterFns = attrs.afterFns || function() { return []; }; + this.userContext = attrs.userContext || function() { return {}; }; this.onStart = attrs.onStart || function() {}; this.exceptionFormatter = attrs.exceptionFormatter || function() {}; this.getSpecName = attrs.getSpecName || function() { return ''; }; @@ -53,7 +54,8 @@ getJasmineRequireObj().Spec = function(j$) { fns: allFns, onException: onException, onComplete: complete, - enforceTimeout: function() { return true; } + enforceTimeout: function() { return true; }, + userContext: this.userContext() }); function onException(e) { diff --git a/src/core/Suite.js b/src/core/Suite.js index ebdc9c4a..601c6115 100644 --- a/src/core/Suite.js +++ b/src/core/Suite.js @@ -86,7 +86,8 @@ getJasmineRequireObj().Suite = function() { this.queueRunner({ fns: allFns, - onComplete: complete + onComplete: complete, + userContext: this.sharedUserContext() }); function complete() { @@ -113,6 +114,29 @@ getJasmineRequireObj().Suite = function() { return foundActive; }; + Suite.prototype.sharedUserContext = function() { + if (!this.sharedContext) { + this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {}; + } + + return this.sharedContext; + }; + + Suite.prototype.clonedSharedUserContext = function() { + return clone(this.sharedUserContext()); + }; + + function clone(obj) { + var clonedObj = {}; + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + clonedObj[prop] = obj[prop]; + } + } + + return clonedObj; + } + return Suite; };