Skip to content
This repository was archived by the owner on Sep 14, 2024. It is now read-only.

Commit cb2a713

Browse files
authored
Merge pull request #119 from MagiMaster/context2
Add Context object to lifecycle hooks and it blocks
2 parents 7a4f7b8 + 602f1f6 commit cb2a713

File tree

6 files changed

+89
-5
lines changed

6 files changed

+89
-5
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
* `beforeAll` now runs on entering the block, rather than on the first `it` encountered after entering the block. The major difference for the moment is that a `beforeAll` will now run even if there are no `it` blocks under it, which is now consistent with how `afterAll` worked.
66
* `beforeAll` and `afterAll` now report errors by creating a dummy node in the results to contain the error. Previously, errors in `afterAll` were not reported.
77
* A failure in a `beforeAll` block will now halt all further test execution within its enclosing `describe` block except for any remaining `beforeAll` blocks and any `afterAll` blocks. Multiple `beforeAll` or `afterAll` blocks within one `describe` block should not count on running in any specific order. `afterAll` blocks should account for the possibility of a partially setup state when cleaning up.
8+
* Add a context object visible from lifecycle hooks and `it` blocks. This is a write-once store for whatever you need to communicate between hooks and tests. It can be ignored until you need it.
9+
* In particular, you can usually just use upvalues to comminucate between hooks and tests, but that won't work if your hooks are in a separate file (e.g. `init.spec.lua`).
10+
* Also, this provides a cleaner alternative to extraEnvironment for passing along helper functions to large numbers of tests as the context can be scoped to particular directories as needed.
811

912
## 0.3.0 (2020-06-12)
1013
* Remove the `try` node type.

src/TestRunner.lua

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,16 @@ function TestRunner.runPlanNode(session, planNode, lifecycleHooks)
7070
errorMessage = messagePrefix .. message .. "\n" .. debug.traceback()
7171
end
7272

73-
local nodeSuccess, nodeResult = xpcall(callback, function(message)
74-
return messagePrefix .. message .. "\n" .. debug.traceback()
75-
end)
73+
local context = session:getContext()
74+
75+
local nodeSuccess, nodeResult = xpcall(
76+
function()
77+
callback(context)
78+
end,
79+
function(message)
80+
return messagePrefix .. message .. "\n" .. debug.traceback()
81+
end
82+
)
7683

7784
-- If a node threw an error, we prefer to use that message over
7885
-- one created by fail() if it was set.

src/TestSession.lua

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
local TestEnum = require(script.Parent.TestEnum)
1111
local TestResults = require(script.Parent.TestResults)
12+
local Context = require(script.Parent.Context)
1213

1314
local TestSession = {}
1415

@@ -23,6 +24,7 @@ function TestSession.new(plan)
2324
local self = {
2425
results = TestResults.new(plan),
2526
nodeStack = {},
27+
contextStack = {},
2628
hasFocusNodes = false
2729
}
2830

@@ -95,11 +97,13 @@ end
9597
]]
9698
function TestSession:pushNode(planNode)
9799
local node = TestResults.createNode(planNode)
98-
99100
local lastNode = self.nodeStack[#self.nodeStack] or self.results
101+
local lastContext = self.contextStack[#self.contextStack]
102+
local context = Context.new(lastContext)
100103

101104
table.insert(lastNode.children, node)
102105
table.insert(self.nodeStack, node)
106+
table.insert(self.contextStack, context)
103107
end
104108

105109
--[[
@@ -108,6 +112,15 @@ end
108112
function TestSession:popNode()
109113
assert(#self.nodeStack > 0, "Tried to pop from an empty node stack!")
110114
table.remove(self.nodeStack, #self.nodeStack)
115+
table.remove(self.contextStack, #self.contextStack)
116+
end
117+
118+
--[[
119+
Gets the Context object for the current node.
120+
]]
121+
function TestSession:getContext()
122+
assert(#self.contextStack > 0, "Tried to get context from an empty stack!")
123+
return self.contextStack[#self.contextStack]
111124
end
112125

113126
--[[
@@ -172,7 +185,9 @@ function TestSession:setError(message)
172185
end
173186

174187
--[[
175-
Add a dummy node below the current one to hold an error message.
188+
Add a dummy child node to the current node to hold the given error. This
189+
allows an otherwise empty describe node to report an error in a more natural
190+
way.
176191
]]
177192
function TestSession:addDummyError(phrase, message)
178193
self:pushNode({type = TestEnum.NodeType.It, phrase = phrase})

tests/passing/context.spec.lua

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-- luacheck: globals describe beforeAll beforeEach it expect afterEach afterAll
2+
3+
return function()
4+
describe("context is passed between lifecycle hooks and it blocks", function()
5+
beforeAll(function(context)
6+
context.a = 1
7+
end)
8+
9+
beforeEach(function(context)
10+
context.b = 1
11+
end)
12+
13+
it("before hooks should run", function(context)
14+
expect(context.a).to.equal(1)
15+
expect(context.b).to.equal(1)
16+
end)
17+
18+
afterEach(function(context)
19+
expect(context.b).to.equal(1)
20+
end)
21+
22+
afterAll(function(context)
23+
-- Failures in afterAll aren't reported.
24+
expect(context.a).to.equal(1)
25+
end)
26+
end)
27+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- luacheck: globals describe expect
2+
3+
return function()
4+
describe("this shouldn't be able to access context", function(context)
5+
expect(context).to.never.be.ok()
6+
end)
7+
end

tests/passing/nestedContext.spec.lua

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-- luacheck: globals describe beforeAll it expect
2+
3+
return function()
4+
describe("setting context here", function()
5+
beforeAll(function(context)
6+
context.a = 1
7+
end)
8+
9+
describe("should apply here", function()
10+
beforeAll(function(context)
11+
context.b = context.a + 1
12+
end)
13+
14+
it("should see a and b", function(context)
15+
expect(context.a).to.equal(1)
16+
expect(context.b).to.equal(2)
17+
end)
18+
end)
19+
20+
it("should not see b here", function(context)
21+
expect(context.a).to.equal(1)
22+
expect(context.b).to.never.be.ok()
23+
end)
24+
end)
25+
end

0 commit comments

Comments
 (0)