Repository: nvim-lua/plenary.nvim (lua)

Issue:
[Bug] nested `before_each` and `after_each` execute in random order
I have some test which would benefit by being able to nest `before_each` and `after_each` inside `describe`

For example like this:

```lua
describe("root tests", function()
    before_each(function()
        -- do something (1)
    end)
    after_each(function()
        -- do something (1) 
    end)

    describe("root tests", function()
        before_each(function()
            -- do something (2)
        end)
        after_each(function()
            -- do something (2) 
        end)
        
        it("something", function()
           -- before_each (1) first ran
           -- before_each (2) then ran

           -- your test

           -- after_each (2) first ran
           -- after_each (1) then ran
        end)
    end)
end)
```

Pull request:
Fixes #491 ;  Encountered the same problem as @OscarCreator.
Just changed the tables that store the before_each and after_each functions to be indexed by the parent `describe`s index in the current_describe table which uses sequential integers.  Then in the run_each function where these functions get executed, iterating thru them usning ipairs instead of pairs.  That seems to put things in the order I'd expect.

Of course if you run the tests using the old code, they might be successful occasionally (it's up to however lua decides to store/iterate the table keys each time).  But using the changes, the tests should succeed every time.

Patch:
diff --git a/lua/plenary/busted.lua b/lua/plenary/busted.lua
index 1b15fcec..10721602 100644
--- a/lua/plenary/busted.lua
+++ b/lua/plenary/busted.lua
@@ -59,13 +59,13 @@ local pop_description = function()
 end
 
 local add_new_each = function()
-  current_before_each[current_description[#current_description]] = {}
-  current_after_each[current_description[#current_description]] = {}
+  current_before_each[#current_description] = {}
+  current_after_each[#current_description] = {}
 end
 
 local clear_last_each = function()
-  current_before_each[current_description[#current_description]] = nil
-  current_after_each[current_description[#current_description]] = nil
+  current_before_each[#current_description] = nil
+  current_after_each[#current_description] = nil
 end
 
 local call_inner = function(desc, func)
@@ -140,11 +140,11 @@ mod.inner_describe = function(desc, func)
 end
 
 mod.before_each = function(fn)
-  table.insert(current_before_each[current_description[#current_description]], fn)
+  table.insert(current_before_each[#current_description], fn)
 end
 
 mod.after_each = function(fn)
-  table.insert(current_after_each[current_description[#current_description]], fn)
+  table.insert(current_after_each[#current_description], fn)
 end
 
 mod.clear = function()
@@ -161,7 +161,7 @@ local indent = function(msg, spaces)
 end
 
 local run_each = function(tbl)
-  for _, v in pairs(tbl) do
+  for _, v in ipairs(tbl) do
     for _, w in ipairs(v) do
       if type(w) == "function" then
         w()


Test patch:
diff --git a/tests/plenary/simple_busted_spec.lua b/tests/plenary/simple_busted_spec.lua
index f45e7577..ce81ebfd 100644
--- a/tests/plenary/simple_busted_spec.lua
+++ b/tests/plenary/simple_busted_spec.lua
@@ -67,6 +67,48 @@ describe("before each", function()
   end)
 end)
 
+describe("before_each ordering", function()
+  local order = ""
+  before_each(function()
+    order = order .. "1,"
+  end)
+  before_each(function()
+    order = order .. "2,"
+  end)
+  describe("nested 1 deep", function()
+    before_each(function()
+      order = order .. "3,"
+    end)
+    before_each(function()
+      order = order .. "4,"
+    end)
+    describe("nested 2 deep", function()
+      before_each(function()
+        order = order .. "5,"
+      end)
+      it("runs before_each`s in order", function()
+        eq("1,2,3,4,5,", order)
+      end)
+    end)
+  end)
+  describe("adjacent nested 1 deep", function()
+    before_each(function()
+      order = order .. "3a,"
+    end)
+    before_each(function()
+      order = order .. "4a,"
+    end)
+    describe("nested 2 deep", function()
+      before_each(function()
+        order = order .. "5a,"
+      end)
+      it("runs before_each`s in order", function()
+        eq("1,2,3,4,5,1,2,3a,4a,5a,", order)
+      end)
+    end)
+  end)
+end)
+
 describe("after each", function()
   local a = 2
   local b = 3
@@ -110,7 +152,54 @@ describe("after each", function()
   end)
 end)
 
-describe("fourth top level describe test", function()
+describe("after_each ordering", function()
+  local order = ""
+  describe("1st describe having after_each", function()
+    after_each(function()
+      order = order .. "1,"
+    end)
+    after_each(function()
+      order = order .. "2,"
+    end)
+    describe("nested 1 deep", function()
+      after_each(function()
+        order = order .. "3,"
+      end)
+      after_each(function()
+        order = order .. "4,"
+      end)
+      describe("nested 2 deep", function()
+        after_each(function()
+          order = order .. "5,"
+        end)
+        it("a test to trigger the after_each`s", function()
+          assert(true)
+        end)
+      end)
+    end)
+    describe("adjacent nested 1 deep", function()
+      after_each(function()
+        order = order .. "3a,"
+      end)
+      after_each(function()
+        order = order .. "4a,"
+      end)
+      describe("nested 2 deep", function()
+        after_each(function()
+          order = order .. "5a,"
+        end)
+        it("a test to trigger the adjacent after_each`s", function()
+          assert(true)
+        end)
+      end)
+    end)
+  end)
+  it("ran after_each`s in order", function()
+    eq("1,2,3,4,5,1,2,3a,4a,5a,", order)
+  end)
+end)
+
+describe("another top level describe test", function()
   it("should work", function()
     eq(1, 1)
   end)