Skip to content

Commit

Permalink
Add JustAfterEach (#484)
Browse files Browse the repository at this point in the history
JustAfterEach is a useful addition for taking an action directly after a spec runs but before any global AfterEach blocks run
  • Loading branch information
lwr20 authored and williammartin committed Nov 5, 2018
1 parent aec9277 commit 0d4f080
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ tmp/**/*
*.coverprofile
.vscode
.idea/
*.log
*.log
1 change: 1 addition & 0 deletions ginkgo/nodot/nodot_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ var SynchronizedBeforeSuite = ginkgo.SynchronizedBeforeSuite
var SynchronizedAfterSuite = ginkgo.SynchronizedAfterSuite
var BeforeEach = ginkgo.BeforeEach
var JustBeforeEach = ginkgo.JustBeforeEach
var JustAfterEach = ginkgo.JustAfterEach
var AfterEach = ginkgo.AfterEach

// Declarations for Gomega DSL
Expand Down
10 changes: 10 additions & 0 deletions ginkgo_dsl.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,16 @@ func JustBeforeEach(body interface{}, timeout ...float64) bool {
return true
}

//JustAfterEach blocks are run after It blocks but *before* all AfterEach blocks. For more details,
//read the [documentation](http://onsi.github.io/ginkgo/#separating_creation_and_configuration_)
//
//Like It blocks, JustAfterEach blocks can be made asynchronous by providing a body function that accepts
//a Done channel
func JustAfterEach(body interface{}, timeout ...float64) bool {
globalSuite.PushJustAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
return true
}

//AfterEach blocks are run after It blocks. When multiple AfterEach blocks are defined in nested
//Describe and Context blocks the innermost AfterEach blocks are run first.
//
Expand Down
6 changes: 6 additions & 0 deletions internal/leafnodes/setup_nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,9 @@ func NewJustBeforeEachNode(body interface{}, codeLocation types.CodeLocation, ti
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeJustBeforeEach, componentIndex),
}
}

func NewJustAfterEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *SetupNode {
return &SetupNode{
runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeJustAfterEach, componentIndex),
}
}
8 changes: 8 additions & 0 deletions internal/leafnodes/setup_nodes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,12 @@ var _ = Describe("Setup Nodes", func() {
Ω(justBeforeEach.CodeLocation()).Should(Equal(codeLocation))
})
})
Describe("JustAfterEachNodes", func() {
It("should report the correct type and code location", func() {
codeLocation := codelocation.New(0)
justAfterEach := NewJustAfterEachNode(func() {}, codeLocation, 0, nil, 3)
Ω(justAfterEach.Type()).Should(Equal(types.SpecComponentTypeJustAfterEach))
Ω(justAfterEach.CodeLocation()).Should(Equal(codeLocation))
})
})
})
12 changes: 12 additions & 0 deletions internal/spec/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ func (spec *Spec) runSample(sample int, writer io.Writer) {
innerMostContainerIndexToUnwind := -1

defer func() {
for i := innerMostContainerIndexToUnwind; i >= 0; i-- {
container := spec.containers[i]
for _, justAfterEach := range container.SetupNodesOfType(types.SpecComponentTypeJustAfterEach) {
spec.announceSetupNode(writer, "JustAfterEach", container, justAfterEach)
justAfterEachState, justAfterEachFailure := justAfterEach.Run()
if justAfterEachState != types.SpecStatePassed && spec.state == types.SpecStatePassed {
spec.state = justAfterEachState
spec.failure = justAfterEachFailure
}
}
}

for i := innerMostContainerIndexToUnwind; i >= 0; i-- {
container := spec.containers[i]
for _, afterEach := range container.SetupNodesOfType(types.SpecComponentTypeAfterEach) {
Expand Down
77 changes: 76 additions & 1 deletion internal/spec/spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ var _ = Describe("Spec", func() {
return leafnodes.NewJustBeforeEachNode(newBody(text, fail), codeLocation, 0, failer, 0)
}

newJusAft := func(text string, fail bool) leafnodes.BasicNode {
return leafnodes.NewJustAfterEachNode(newBody(text, fail), codeLocation, 0, failer, 0)
}

newContainer := func(text string, flag types.FlagType, setupNodes ...leafnodes.BasicNode) *containernode.ContainerNode {
c := containernode.New(text, flag, codeLocation)
for _, node := range setupNodes {
Expand Down Expand Up @@ -279,6 +283,8 @@ var _ = Describe("Spec", func() {
newBef("outer bef B", failingNodes["outer bef B"]),
newJusBef("outer jusbef A", failingNodes["outer jusbef A"]),
newJusBef("outer jusbef B", failingNodes["outer jusbef B"]),
newJusAft("outer jusaft A", failingNodes["outer jusaft A"]),
newJusAft("outer jusaft B", failingNodes["outer jusaft B"]),
newAft("outer aft A", failingNodes["outer aft A"]),
newAft("outer aft B", failingNodes["outer aft B"]),
),
Expand All @@ -287,6 +293,8 @@ var _ = Describe("Spec", func() {
newBef("inner bef B", failingNodes["inner bef B"]),
newJusBef("inner jusbef A", failingNodes["inner jusbef A"]),
newJusBef("inner jusbef B", failingNodes["inner jusbef B"]),
newJusAft("inner jusaft A", failingNodes["inner jusaft A"]),
newJusAft("inner jusaft B", failingNodes["inner jusaft B"]),
newAft("inner aft A", failingNodes["inner aft A"]),
newAft("inner aft B", failingNodes["inner aft B"]),
),
Expand All @@ -310,6 +318,10 @@ var _ = Describe("Spec", func() {
"inner jusbef A",
"inner jusbef B",
"it node",
"inner jusaft A",
"inner jusaft B",
"outer jusaft A",
"outer jusaft B",
"inner aft A",
"inner aft B",
"outer aft A",
Expand All @@ -336,6 +348,10 @@ var _ = Describe("Spec", func() {
"inner jusbef A",
"inner jusbef B",
"it node",
"inner jusaft A",
"inner jusaft B",
"outer jusaft A",
"outer jusaft B",
"inner aft A",
"inner aft B",
"outer aft A",
Expand All @@ -357,6 +373,10 @@ var _ = Describe("Spec", func() {
"outer bef A",
"outer bef B",
"inner bef A",
"inner jusaft A",
"inner jusaft B",
"outer jusaft A",
"outer jusaft B",
"inner aft A",
"inner aft B",
"outer aft A",
Expand All @@ -377,6 +397,8 @@ var _ = Describe("Spec", func() {
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"outer jusaft A",
"outer jusaft B",
"outer aft A",
"outer aft B",
}))
Expand All @@ -402,6 +424,10 @@ var _ = Describe("Spec", func() {
"inner jusbef A",
"inner jusbef B",
"it node",
"inner jusaft A",
"inner jusaft B",
"outer jusaft A",
"outer jusaft B",
"inner aft A",
"inner aft B",
"outer aft A",
Expand All @@ -426,6 +452,10 @@ var _ = Describe("Spec", func() {
"inner bef B",
"outer jusbef A",
"outer jusbef B",
"inner jusaft A",
"inner jusaft B",
"outer jusaft A",
"outer jusaft B",
"inner aft A",
"inner aft B",
"outer aft A",
Expand All @@ -435,6 +465,37 @@ var _ = Describe("Spec", func() {
})
})

Context("when a just after each fails", func() {
BeforeEach(func() {
failingNodes["outer jusaft A"] = true
})

It("should run all other afters, but mark the test as failed", func() {
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"inner bef A",
"inner bef B",
"outer jusbef A",
"outer jusbef B",
"inner jusbef A",
"inner jusbef B",
"it node",
"inner jusaft A",
"inner jusaft B",
"outer jusaft A",
"outer jusaft B",
"inner aft A",
"inner aft B",
"outer aft A",
"outer aft B",
}))
Ω(spec.Summary("").Failure.Message).Should(Equal("outer jusaft A"))
})
})

Context("when an after fails after an earlier node has failed", func() {
BeforeEach(func() {
failingNodes["it node"] = true
Expand All @@ -454,6 +515,10 @@ var _ = Describe("Spec", func() {
"inner jusbef A",
"inner jusbef B",
"it node",
"inner jusaft A",
"inner jusaft B",
"outer jusaft A",
"outer jusaft B",
"inner aft A",
"inner aft B",
"outer aft A",
Expand All @@ -474,6 +539,7 @@ var _ = Describe("Spec", func() {
newContainer("container", noneFlag,
newBef("bef A", false),
newJusBef("jusbef A", false),
newJusAft("jusaft A", false),
newAft("aft A", false),
),
),
Expand All @@ -487,14 +553,17 @@ var _ = Describe("Spec", func() {
"bef A",
"jusbef A",
"measure node",
"jusaft A",
"aft A",
"bef A",
"jusbef A",
"measure node",
"jusaft A",
"aft A",
"bef A",
"jusbef A",
"measure node",
"jusaft A",
"aft A",
}))
})
Expand All @@ -508,6 +577,7 @@ var _ = Describe("Spec", func() {
newContainer("container", noneFlag,
newBef("bef A", false),
newJusBef("jusbef A", false),
newJusAft("jusaft A", false),
newAft("aft A", false),
),
),
Expand All @@ -521,6 +591,7 @@ var _ = Describe("Spec", func() {
"bef A",
"jusbef A",
"measure node",
"jusaft A",
"aft A",
}))
})
Expand Down Expand Up @@ -628,11 +699,13 @@ var _ = Describe("Spec", func() {
newContainer("outer container", noneFlag,
newBef("outer bef A", false),
newJusBef("outer jusbef A", false),
newJusAft("outer jusaft A", false),
newAft("outer aft A", false),
),
newContainer("inner container", noneFlag,
newBef("inner bef A", false),
newJusBef("inner jusbef A", false),
newJusAft("inner jusaft A", false),
newAft("inner aft A", false),
),
),
Expand All @@ -645,11 +718,13 @@ var _ = Describe("Spec", func() {
Ω(buffer).Should(gbytes.Say(`\[JustBeforeEach\] outer container`))
Ω(buffer).Should(gbytes.Say(`\[JustBeforeEach\] inner container`))
Ω(buffer).Should(gbytes.Say(`\[It\] it node`))
Ω(buffer).Should(gbytes.Say(`\[JustAfterEach\] inner container`))
Ω(buffer).Should(gbytes.Say(`\[JustAfterEach\] outer container`))
Ω(buffer).Should(gbytes.Say(`\[AfterEach\] inner container`))
Ω(buffer).Should(gbytes.Say(`\[AfterEach\] outer container`))
})

It("should emit progress to the writer as it runs Befores, JustBefores, Afters, and Measures", func() {
It("should emit progress to the writer as it runs Befores, JustBefores, JustAfters, Afters, and Measures", func() {
spec = New(
newMeasure("measure node", noneFlag, false, 2),
containers(),
Expand Down
7 changes: 7 additions & 0 deletions internal/suite/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ func (suite *Suite) PushJustBeforeEachNode(body interface{}, codeLocation types.
suite.currentContainer.PushSetupNode(leafnodes.NewJustBeforeEachNode(body, codeLocation, timeout, suite.failer, suite.containerIndex))
}

func (suite *Suite) PushJustAfterEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
if suite.running {
suite.failer.Fail("You may only call JustAfterEach from within a Describe or Context", codeLocation)
}
suite.currentContainer.PushSetupNode(leafnodes.NewJustAfterEachNode(body, codeLocation, timeout, suite.failer, suite.containerIndex))
}

func (suite *Suite) PushAfterEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration) {
if suite.running {
suite.failer.Fail("You may only call AfterEach from within a Describe, Context or When", codeLocation)
Expand Down
1 change: 1 addition & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ const (
SpecComponentTypeAfterSuite
SpecComponentTypeBeforeEach
SpecComponentTypeJustBeforeEach
SpecComponentTypeJustAfterEach
SpecComponentTypeAfterEach
SpecComponentTypeIt
SpecComponentTypeMeasure
Expand Down

0 comments on commit 0d4f080

Please sign in to comment.