Skip to content

Commit

Permalink
Calling By in a container node now emits a useful error.
Browse files Browse the repository at this point in the history
  • Loading branch information
onsi committed Feb 15, 2022
1 parent dcba0f3 commit ff12cee
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 0 deletions.
3 changes: 3 additions & 0 deletions core_dsl.go
Expand Up @@ -478,6 +478,9 @@ Note that By does not generate a new Ginkgo node - rather it is simply synctacti
You can learn more about By here: https://onsi.github.io/ginkgo/#documenting-complex-specs-by
*/
func By(text string, callback ...func()) {
if !global.Suite.InRunPhase() {
exitIfErr(types.GinkgoErrors.ByNotDuringRunPhase(types.NewCodeLocation(1)))
}
value := struct {
Text string
Duration time.Duration
Expand Down
@@ -0,0 +1,21 @@
package malformed_fixture_test

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestMalformedFixture(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "MalformedFixture Suite")
}

var _ = Describe("Malformed by...", func() {
By("right here...")

It("should never run", func() {

})
})
16 changes: 16 additions & 0 deletions integration/fail_test.go
Expand Up @@ -63,4 +63,20 @@ var _ = Describe("Failing Specs", func() {
Ω(output).Should(ContainSubstring("malformed_fixture_test.go:9"))
})
})

Describe("when By is called outside of a runnable node", func() {
BeforeEach(func() {
fm.MountFixture("malformed_by")
})

It("exits early with a helpful error message", func() {
session := startGinkgo(fm.PathTo("malformed_by"), "--no-color", "--procs=2")
Eventually(session).Should(gexec.Exit(1))
output := string(session.Out.Contents()) + string(session.Err.Contents())

Ω(output).Should(ContainSubstring("Ginkgo detected an issue with your spec structure"))
Ω(output).Should(ContainSubstring("malformed_by_fixture_suite_test.go:16"))

})
})
})
4 changes: 4 additions & 0 deletions internal/suite.go
Expand Up @@ -85,6 +85,10 @@ func (suite *Suite) Run(description string, suiteLabels Labels, suitePath string
return success, hasProgrammaticFocus
}

func (suite *Suite) InRunPhase() bool {
return suite.phase == PhaseRun
}

/*
Tree Construction methods
Expand Down
21 changes: 21 additions & 0 deletions internal/suite_test.go
Expand Up @@ -72,6 +72,27 @@ var _ = Describe("Suite", func() {
})
})

Describe("InRunPhase", func() {
It("returns true when in the run phase and false when not in the run phase", func() {
falsey := true
truey := false

err := suite.PushNode(N(ntCon, "a top-level container", func() {
falsey = suite.InRunPhase()
suite.PushNode(N(ntIt, "an it", func() {
truey = suite.InRunPhase()
}))
}))

Ω(suite.BuildTree()).Should(Succeed())
suite.Run("suite", Labels{}, "/path/to/suite", failer, reporter, writer, outputInterceptor, interruptHandler, client, conf)

Ω(err).ShouldNot(HaveOccurred())
Ω(truey).Should(BeTrue())
Ω(falsey).Should(BeFalse())
})
})

Context("when pushing nodes during PhaseRun", func() {
var pushNodeErrDuringRun error

Expand Down
10 changes: 10 additions & 0 deletions types/errors.go
Expand Up @@ -292,6 +292,16 @@ func (g ginkgoErrors) AddReportEntryNotDuringRunPhase(cl CodeLocation) error {
}
}

/* By errors */
func (g ginkgoErrors) ByNotDuringRunPhase(cl CodeLocation) error {
return GinkgoError{
Heading: "Ginkgo detected an issue with your spec structure",
Message: formatter.F(`It looks like you are calling {{bold}}By{{/}} outside of a running spec. Make sure you call {{bold}}By{{/}} inside a runnable node such as It or BeforeEach and not inside the body of a container such as Describe or Context.`),
CodeLocation: cl,
DocLink: "documenting-complex-specs-by",
}
}

/* FileFilter and SkipFilter errors */
func (g ginkgoErrors) InvalidFileFilter(filter string) error {
return GinkgoError{
Expand Down

0 comments on commit ff12cee

Please sign in to comment.