diff --git a/CHANGELOG.md b/CHANGELOG.md index 4910007..c4f7a8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Remove the `step` alias for `it` since that's meant for use with `try`. * Remove the `include` global function. * Remove `HACK_NO_XPCALL`. With recent changes to the definition of xpcall, this is no longer necessary. Since people are still using it, it will now print out a warning asking them to delete that call instead. +* Guarantee that `init.spec.lua` will run before any `it` or `describe` blocks in the folder under it. * Major changes to the internals of test planning. * The major visible change is that `describe` and `it` blocks with duplicate descriptions will now not overwrite the earlier copies of those nodes. * Duplicate `it` nodes within one `describe` will raise an error. diff --git a/src/TestPlan.lua b/src/TestPlan.lua index 6529ec2..ed31f47 100644 --- a/src/TestPlan.lua +++ b/src/TestPlan.lua @@ -25,9 +25,6 @@ local function newEnvironment(currentNode, extraEnvironment) local function addChild(phrase, callback, nodeType, nodeModifier) local node = currentNode:addChild(phrase, nodeType, nodeModifier) node.callback = callback - if nodeType == TestEnum.NodeType.Describe then - node:expand() - end return node end @@ -177,10 +174,14 @@ function TestNode:getFullName() end --[[ - Expand a node by setting its callback environment and then calling it. Any - further it and describe calls within the callback will be added to the tree. + Expand a node by setting its callback environment and then calling it. Only + expands this one node. ]] function TestNode:expand() + if not self.callback then + return + end + local originalEnv = getfenv(self.callback) local callbackEnv = setmetatable({}, { __index = originalEnv }) for key, value in pairs(self.environment) do @@ -245,7 +246,17 @@ function TestPlan:addRoot(path, method) end curNode.callback = method - curNode:expand() +end + +--[[ + Expands all describe nodes, leaving the plan in a runnable state. +]] +function TestPlan:finalize() + self:visitAllNodes(function(node) + if node.type == TestEnum.NodeType.Describe then + node:expand() + end + end) end --[[ diff --git a/src/TestPlanner.lua b/src/TestPlanner.lua index 4b9772a..484157d 100644 --- a/src/TestPlanner.lua +++ b/src/TestPlanner.lua @@ -20,6 +20,7 @@ function TestPlanner.createPlan(specFunctions, testNamePattern, extraEnvironment plan:addRoot(module.path, module.method) end + plan:finalize() return plan end diff --git a/tests/expandOrder.lua b/tests/expandOrder.lua new file mode 100644 index 0000000..2dbf01e --- /dev/null +++ b/tests/expandOrder.lua @@ -0,0 +1,89 @@ +local TestEZ = require(script.Parent.Parent.TestEZ) + +return { + ["init.spec.lua is run before children are expanded"] = function() + local initialized = false + + local plan = TestEZ.TestPlanner.createPlan({ + { + method = function() + assert(initialized, "init.spec was not called before bar.spec") + end, + path = {'bar.spec', 'foo'} + }, + { + method = function() + initialized = true + end, + path = {'foo'} + }, + }) + + local results = TestEZ.TestRunner.runPlan(plan) + assert(#results.errors == 0, "init test failed: " .. tostring(results.errors[1])) + end, + ["init.spec.lua afterAll can correctly undo changes"] = function() + local initialized = false + + -- luacheck: globals it + local plan = TestEZ.TestPlanner.createPlan({ + { + method = function() + print("Ad") + it("A", function() + print("Ai") + assert(not initialized, "initialized was true in foo/a.spec") + end) + end, + path = {'a.spec', 'foo'} + }, + { + method = function() + print("Bd") + it("B", function() + print("Bi") + assert(initialized, "initialized was false in foo/bar/b.spec") + end) + end, + path = {'b.spec', 'bar', 'foo'} + }, + { + method = function() + print("Init") + initialized = true + + -- luacheck: globals afterAll + afterAll(function() + print("After") + initialized = false + end) + end, + path = {'bar', 'foo'} + }, + { + method = function() + print("Cd") + it("C", function() + print("Ci") + assert(initialized, "initialized was false in foo/bar/c.spec") + end) + end, + path = {'c.spec', 'bar', 'foo'} + }, + { + method = function() + print("Dd") + it("D", function() + print("Di") + assert(not initialized, "initialized was true in foo/d.spec") + end) + end, + path = {'d.spec', 'foo'} + }, + }) + + local results = TestEZ.TestRunner.runPlan(plan) + assert(#results.errors == 0, "init test failed:\n" .. + table.concat(results.errors, "\n")) + end, +} \ No newline at end of file diff --git a/tests/planning/init.spec.lua b/tests/planning/init.spec.lua new file mode 100644 index 0000000..eef2433 --- /dev/null +++ b/tests/planning/init.spec.lua @@ -0,0 +1,4 @@ +-- This should be added to the "planning" node of the tree instead of creating +-- a new node. +return function() +end