1/*
2Ginkgo is a BDD-style testing framework for Golang
3
4The godoc documentation describes Ginkgo's API.  More comprehensive documentation (with examples!) is available at http://onsi.github.io/ginkgo/
5
6Ginkgo's preferred matcher library is [Gomega](http://github.com/onsi/gomega)
7
8Ginkgo on Github: http://github.com/onsi/ginkgo
9
10Ginkgo is MIT-Licensed
11*/
12package ginkgo
13
14import (
15	"flag"
16	"fmt"
17	"io"
18	"net/http"
19	"os"
20	"strings"
21	"time"
22
23	"github.com/onsi/ginkgo/config"
24	"github.com/onsi/ginkgo/internal/codelocation"
25	"github.com/onsi/ginkgo/internal/failer"
26	"github.com/onsi/ginkgo/internal/remote"
27	"github.com/onsi/ginkgo/internal/suite"
28	"github.com/onsi/ginkgo/internal/testingtproxy"
29	"github.com/onsi/ginkgo/internal/writer"
30	"github.com/onsi/ginkgo/reporters"
31	"github.com/onsi/ginkgo/reporters/stenographer"
32	colorable "github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable"
33	"github.com/onsi/ginkgo/types"
34)
35
36const GINKGO_VERSION = config.VERSION
37const GINKGO_PANIC = `
38Your test failed.
39Ginkgo panics to prevent subsequent assertions from running.
40Normally Ginkgo rescues this panic so you shouldn't see it.
41
42But, if you make an assertion in a goroutine, Ginkgo can't capture the panic.
43To circumvent this, you should call
44
45	defer GinkgoRecover()
46
47at the top of the goroutine that caused this panic.
48`
49const defaultTimeout = 1
50
51var globalSuite *suite.Suite
52var globalFailer *failer.Failer
53
54func init() {
55	config.Flags(flag.CommandLine, "ginkgo", true)
56	GinkgoWriter = writer.New(os.Stdout)
57	globalFailer = failer.New()
58	globalSuite = suite.New(globalFailer)
59}
60
61//GinkgoWriter implements an io.Writer
62//When running in verbose mode any writes to GinkgoWriter will be immediately printed
63//to stdout.  Otherwise, GinkgoWriter will buffer any writes produced during the current test and flush them to screen
64//only if the current test fails.
65var GinkgoWriter io.Writer
66
67//The interface by which Ginkgo receives *testing.T
68type GinkgoTestingT interface {
69	Fail()
70}
71
72//GinkgoRandomSeed returns the seed used to randomize spec execution order.  It is
73//useful for seeding your own pseudorandom number generators (PRNGs) to ensure
74//consistent executions from run to run, where your tests contain variability (for
75//example, when selecting random test data).
76func GinkgoRandomSeed() int64 {
77	return config.GinkgoConfig.RandomSeed
78}
79
80//GinkgoParallelNode returns the parallel node number for the current ginkgo process
81//The node number is 1-indexed
82func GinkgoParallelNode() int {
83	return config.GinkgoConfig.ParallelNode
84}
85
86//Some matcher libraries or legacy codebases require a *testing.T
87//GinkgoT implements an interface analogous to *testing.T and can be used if
88//the library in question accepts *testing.T through an interface
89//
90// For example, with testify:
91// assert.Equal(GinkgoT(), 123, 123, "they should be equal")
92//
93// Or with gomock:
94// gomock.NewController(GinkgoT())
95//
96// GinkgoT() takes an optional offset argument that can be used to get the
97// correct line number associated with the failure.
98func GinkgoT(optionalOffset ...int) GinkgoTInterface {
99	offset := 3
100	if len(optionalOffset) > 0 {
101		offset = optionalOffset[0]
102	}
103	return testingtproxy.New(GinkgoWriter, Fail, offset)
104}
105
106//The interface returned by GinkgoT().  This covers most of the methods
107//in the testing package's T.
108type GinkgoTInterface interface {
109	Fail()
110	Error(args ...interface{})
111	Errorf(format string, args ...interface{})
112	FailNow()
113	Fatal(args ...interface{})
114	Fatalf(format string, args ...interface{})
115	Log(args ...interface{})
116	Logf(format string, args ...interface{})
117	Failed() bool
118	Parallel()
119	Skip(args ...interface{})
120	Skipf(format string, args ...interface{})
121	SkipNow()
122	Skipped() bool
123}
124
125//Custom Ginkgo test reporters must implement the Reporter interface.
126//
127//The custom reporter is passed in a SuiteSummary when the suite begins and ends,
128//and a SpecSummary just before a spec begins and just after a spec ends
129type Reporter reporters.Reporter
130
131//Asynchronous specs are given a channel of the Done type.  You must close or write to the channel
132//to tell Ginkgo that your async test is done.
133type Done chan<- interface{}
134
135//GinkgoTestDescription represents the information about the current running test returned by CurrentGinkgoTestDescription
136//	FullTestText: a concatenation of ComponentTexts and the TestText
137//	ComponentTexts: a list of all texts for the Describes & Contexts leading up to the current test
138//	TestText: the text in the actual It or Measure node
139//	IsMeasurement: true if the current test is a measurement
140//	FileName: the name of the file containing the current test
141//	LineNumber: the line number for the current test
142//	Failed: if the current test has failed, this will be true (useful in an AfterEach)
143type GinkgoTestDescription struct {
144	FullTestText   string
145	ComponentTexts []string
146	TestText       string
147
148	IsMeasurement bool
149
150	FileName   string
151	LineNumber int
152
153	Failed   bool
154	Duration time.Duration
155}
156
157//CurrentGinkgoTestDescripton returns information about the current running test.
158func CurrentGinkgoTestDescription() GinkgoTestDescription {
159	summary, ok := globalSuite.CurrentRunningSpecSummary()
160	if !ok {
161		return GinkgoTestDescription{}
162	}
163
164	subjectCodeLocation := summary.ComponentCodeLocations[len(summary.ComponentCodeLocations)-1]
165
166	return GinkgoTestDescription{
167		ComponentTexts: summary.ComponentTexts[1:],
168		FullTestText:   strings.Join(summary.ComponentTexts[1:], " "),
169		TestText:       summary.ComponentTexts[len(summary.ComponentTexts)-1],
170		IsMeasurement:  summary.IsMeasurement,
171		FileName:       subjectCodeLocation.FileName,
172		LineNumber:     subjectCodeLocation.LineNumber,
173		Failed:         summary.HasFailureState(),
174		Duration:       summary.RunTime,
175	}
176}
177
178//Measurement tests receive a Benchmarker.
179//
180//You use the Time() function to time how long the passed in body function takes to run
181//You use the RecordValue() function to track arbitrary numerical measurements.
182//The RecordValueWithPrecision() function can be used alternatively to provide the unit
183//and resolution of the numeric measurement.
184//The optional info argument is passed to the test reporter and can be used to
185// provide the measurement data to a custom reporter with context.
186//
187//See http://onsi.github.io/ginkgo/#benchmark_tests for more details
188type Benchmarker interface {
189	Time(name string, body func(), info ...interface{}) (elapsedTime time.Duration)
190	RecordValue(name string, value float64, info ...interface{})
191	RecordValueWithPrecision(name string, value float64, units string, precision int, info ...interface{})
192}
193
194//RunSpecs is the entry point for the Ginkgo test runner.
195//You must call this within a Golang testing TestX(t *testing.T) function.
196//
197//To bootstrap a test suite you can use the Ginkgo CLI:
198//
199//	ginkgo bootstrap
200func RunSpecs(t GinkgoTestingT, description string) bool {
201	specReporters := []Reporter{buildDefaultReporter()}
202	return RunSpecsWithCustomReporters(t, description, specReporters)
203}
204
205//To run your tests with Ginkgo's default reporter and your custom reporter(s), replace
206//RunSpecs() with this method.
207func RunSpecsWithDefaultAndCustomReporters(t GinkgoTestingT, description string, specReporters []Reporter) bool {
208	specReporters = append(specReporters, buildDefaultReporter())
209	return RunSpecsWithCustomReporters(t, description, specReporters)
210}
211
212//To run your tests with your custom reporter(s) (and *not* Ginkgo's default reporter), replace
213//RunSpecs() with this method.  Note that parallel tests will not work correctly without the default reporter
214func RunSpecsWithCustomReporters(t GinkgoTestingT, description string, specReporters []Reporter) bool {
215	writer := GinkgoWriter.(*writer.Writer)
216	writer.SetStream(config.DefaultReporterConfig.Verbose)
217	reporters := make([]reporters.Reporter, len(specReporters))
218	for i, reporter := range specReporters {
219		reporters[i] = reporter
220	}
221	passed, hasFocusedTests := globalSuite.Run(t, description, reporters, writer, config.GinkgoConfig)
222	if passed && hasFocusedTests && strings.TrimSpace(os.Getenv("GINKGO_EDITOR_INTEGRATION")) == "" {
223		fmt.Println("PASS | FOCUSED")
224		os.Exit(types.GINKGO_FOCUS_EXIT_CODE)
225	}
226	return passed
227}
228
229func buildDefaultReporter() Reporter {
230	remoteReportingServer := config.GinkgoConfig.StreamHost
231	if remoteReportingServer == "" {
232		stenographer := stenographer.New(!config.DefaultReporterConfig.NoColor, config.GinkgoConfig.FlakeAttempts > 1, colorable.NewColorableStdout())
233		return reporters.NewDefaultReporter(config.DefaultReporterConfig, stenographer)
234	} else {
235		debugFile := ""
236		if config.GinkgoConfig.DebugParallel {
237			debugFile = fmt.Sprintf("ginkgo-node-%d.log", config.GinkgoConfig.ParallelNode)
238		}
239		return remote.NewForwardingReporter(config.DefaultReporterConfig, remoteReportingServer, &http.Client{}, remote.NewOutputInterceptor(), GinkgoWriter.(*writer.Writer), debugFile)
240	}
241}
242
243//Skip notifies Ginkgo that the current spec was skipped.
244func Skip(message string, callerSkip ...int) {
245	skip := 0
246	if len(callerSkip) > 0 {
247		skip = callerSkip[0]
248	}
249
250	globalFailer.Skip(message, codelocation.New(skip+1))
251	panic(GINKGO_PANIC)
252}
253
254//Fail notifies Ginkgo that the current spec has failed. (Gomega will call Fail for you automatically when an assertion fails.)
255func Fail(message string, callerSkip ...int) {
256	skip := 0
257	if len(callerSkip) > 0 {
258		skip = callerSkip[0]
259	}
260
261	globalFailer.Fail(message, codelocation.New(skip+1))
262	panic(GINKGO_PANIC)
263}
264
265//GinkgoRecover should be deferred at the top of any spawned goroutine that (may) call `Fail`
266//Since Gomega assertions call fail, you should throw a `defer GinkgoRecover()` at the top of any goroutine that
267//calls out to Gomega
268//
269//Here's why: Ginkgo's `Fail` method records the failure and then panics to prevent
270//further assertions from running.  This panic must be recovered.  Ginkgo does this for you
271//if the panic originates in a Ginkgo node (an It, BeforeEach, etc...)
272//
273//Unfortunately, if a panic originates on a goroutine *launched* from one of these nodes there's no
274//way for Ginkgo to rescue the panic.  To do this, you must remember to `defer GinkgoRecover()` at the top of such a goroutine.
275func GinkgoRecover() {
276	e := recover()
277	if e != nil {
278		globalFailer.Panic(codelocation.New(1), e)
279	}
280}
281
282//Describe blocks allow you to organize your specs.  A Describe block can contain any number of
283//BeforeEach, AfterEach, JustBeforeEach, It, and Measurement blocks.
284//
285//In addition you can nest Describe, Context and When blocks.  Describe, Context and When blocks are functionally
286//equivalent.  The difference is purely semantic -- you typical Describe the behavior of an object
287//or method and, within that Describe, outline a number of Contexts and Whens.
288func Describe(text string, body func()) bool {
289	globalSuite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
290	return true
291}
292
293//You can focus the tests within a describe block using FDescribe
294func FDescribe(text string, body func()) bool {
295	globalSuite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
296	return true
297}
298
299//You can mark the tests within a describe block as pending using PDescribe
300func PDescribe(text string, body func()) bool {
301	globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
302	return true
303}
304
305//You can mark the tests within a describe block as pending using XDescribe
306func XDescribe(text string, body func()) bool {
307	globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
308	return true
309}
310
311//Context blocks allow you to organize your specs.  A Context block can contain any number of
312//BeforeEach, AfterEach, JustBeforeEach, It, and Measurement blocks.
313//
314//In addition you can nest Describe, Context and When blocks.  Describe, Context and When blocks are functionally
315//equivalent.  The difference is purely semantic -- you typical Describe the behavior of an object
316//or method and, within that Describe, outline a number of Contexts and Whens.
317func Context(text string, body func()) bool {
318	globalSuite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
319	return true
320}
321
322//You can focus the tests within a describe block using FContext
323func FContext(text string, body func()) bool {
324	globalSuite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
325	return true
326}
327
328//You can mark the tests within a describe block as pending using PContext
329func PContext(text string, body func()) bool {
330	globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
331	return true
332}
333
334//You can mark the tests within a describe block as pending using XContext
335func XContext(text string, body func()) bool {
336	globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
337	return true
338}
339
340//When blocks allow you to organize your specs.  A When block can contain any number of
341//BeforeEach, AfterEach, JustBeforeEach, It, and Measurement blocks.
342//
343//In addition you can nest Describe, Context and When blocks.  Describe, Context and When blocks are functionally
344//equivalent.  The difference is purely semantic -- you typical Describe the behavior of an object
345//or method and, within that Describe, outline a number of Contexts and Whens.
346func When(text string, body func()) bool {
347	globalSuite.PushContainerNode("when "+text, body, types.FlagTypeNone, codelocation.New(1))
348	return true
349}
350
351//You can focus the tests within a describe block using FWhen
352func FWhen(text string, body func()) bool {
353	globalSuite.PushContainerNode("when "+text, body, types.FlagTypeFocused, codelocation.New(1))
354	return true
355}
356
357//You can mark the tests within a describe block as pending using PWhen
358func PWhen(text string, body func()) bool {
359	globalSuite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
360	return true
361}
362
363//You can mark the tests within a describe block as pending using XWhen
364func XWhen(text string, body func()) bool {
365	globalSuite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
366	return true
367}
368
369//It blocks contain your test code and assertions.  You cannot nest any other Ginkgo blocks
370//within an It block.
371//
372//Ginkgo will normally run It blocks synchronously.  To perform asynchronous tests, pass a
373//function that accepts a Done channel.  When you do this, you can also provide an optional timeout.
374func It(text string, body interface{}, timeout ...float64) bool {
375	globalSuite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
376	return true
377}
378
379//You can focus individual Its using FIt
380func FIt(text string, body interface{}, timeout ...float64) bool {
381	globalSuite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
382	return true
383}
384
385//You can mark Its as pending using PIt
386func PIt(text string, _ ...interface{}) bool {
387	globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
388	return true
389}
390
391//You can mark Its as pending using XIt
392func XIt(text string, _ ...interface{}) bool {
393	globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
394	return true
395}
396
397//Specify blocks are aliases for It blocks and allow for more natural wording in situations
398//which "It" does not fit into a natural sentence flow. All the same protocols apply for Specify blocks
399//which apply to It blocks.
400func Specify(text string, body interface{}, timeout ...float64) bool {
401	globalSuite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
402	return true
403}
404
405//You can focus individual Specifys using FSpecify
406func FSpecify(text string, body interface{}, timeout ...float64) bool {
407	globalSuite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
408	return true
409}
410
411//You can mark Specifys as pending using PSpecify
412func PSpecify(text string, is ...interface{}) bool {
413	globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
414	return true
415}
416
417//You can mark Specifys as pending using XSpecify
418func XSpecify(text string, is ...interface{}) bool {
419	globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
420	return true
421}
422
423//By allows you to better document large Its.
424//
425//Generally you should try to keep your Its short and to the point.  This is not always possible, however,
426//especially in the context of integration tests that capture a particular workflow.
427//
428//By allows you to document such flows.  By must be called within a runnable node (It, BeforeEach, Measure, etc...)
429//By will simply log the passed in text to the GinkgoWriter.  If By is handed a function it will immediately run the function.
430func By(text string, callbacks ...func()) {
431	preamble := "\x1b[1mSTEP\x1b[0m"
432	if config.DefaultReporterConfig.NoColor {
433		preamble = "STEP"
434	}
435	fmt.Fprintln(GinkgoWriter, preamble+": "+text)
436	if len(callbacks) == 1 {
437		callbacks[0]()
438	}
439	if len(callbacks) > 1 {
440		panic("just one callback per By, please")
441	}
442}
443
444//Measure blocks run the passed in body function repeatedly (determined by the samples argument)
445//and accumulate metrics provided to the Benchmarker by the body function.
446//
447//The body function must have the signature:
448//	func(b Benchmarker)
449func Measure(text string, body interface{}, samples int) bool {
450	globalSuite.PushMeasureNode(text, body, types.FlagTypeNone, codelocation.New(1), samples)
451	return true
452}
453
454//You can focus individual Measures using FMeasure
455func FMeasure(text string, body interface{}, samples int) bool {
456	globalSuite.PushMeasureNode(text, body, types.FlagTypeFocused, codelocation.New(1), samples)
457	return true
458}
459
460//You can mark Measurements as pending using PMeasure
461func PMeasure(text string, _ ...interface{}) bool {
462	globalSuite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
463	return true
464}
465
466//You can mark Measurements as pending using XMeasure
467func XMeasure(text string, _ ...interface{}) bool {
468	globalSuite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
469	return true
470}
471
472//BeforeSuite blocks are run just once before any specs are run.  When running in parallel, each
473//parallel node process will call BeforeSuite.
474//
475//BeforeSuite blocks can be made asynchronous by providing a body function that accepts a Done channel
476//
477//You may only register *one* BeforeSuite handler per test suite.  You typically do so in your bootstrap file at the top level.
478func BeforeSuite(body interface{}, timeout ...float64) bool {
479	globalSuite.SetBeforeSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
480	return true
481}
482
483//AfterSuite blocks are *always* run after all the specs regardless of whether specs have passed or failed.
484//Moreover, if Ginkgo receives an interrupt signal (^C) it will attempt to run the AfterSuite before exiting.
485//
486//When running in parallel, each parallel node process will call AfterSuite.
487//
488//AfterSuite blocks can be made asynchronous by providing a body function that accepts a Done channel
489//
490//You may only register *one* AfterSuite handler per test suite.  You typically do so in your bootstrap file at the top level.
491func AfterSuite(body interface{}, timeout ...float64) bool {
492	globalSuite.SetAfterSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
493	return true
494}
495
496//SynchronizedBeforeSuite blocks are primarily meant to solve the problem of setting up singleton external resources shared across
497//nodes when running tests in parallel.  For example, say you have a shared database that you can only start one instance of that
498//must be used in your tests.  When running in parallel, only one node should set up the database and all other nodes should wait
499//until that node is done before running.
500//
501//SynchronizedBeforeSuite accomplishes this by taking *two* function arguments.  The first is only run on parallel node #1.  The second is
502//run on all nodes, but *only* after the first function completes succesfully.  Ginkgo also makes it possible to send data from the first function (on Node 1)
503//to the second function (on all the other nodes).
504//
505//The functions have the following signatures.  The first function (which only runs on node 1) has the signature:
506//
507//	func() []byte
508//
509//or, to run asynchronously:
510//
511//	func(done Done) []byte
512//
513//The byte array returned by the first function is then passed to the second function, which has the signature:
514//
515//	func(data []byte)
516//
517//or, to run asynchronously:
518//
519//	func(data []byte, done Done)
520//
521//Here's a simple pseudo-code example that starts a shared database on Node 1 and shares the database's address with the other nodes:
522//
523//	var dbClient db.Client
524//	var dbRunner db.Runner
525//
526//	var _ = SynchronizedBeforeSuite(func() []byte {
527//		dbRunner = db.NewRunner()
528//		err := dbRunner.Start()
529//		Ω(err).ShouldNot(HaveOccurred())
530//		return []byte(dbRunner.URL)
531//	}, func(data []byte) {
532//		dbClient = db.NewClient()
533//		err := dbClient.Connect(string(data))
534//		Ω(err).ShouldNot(HaveOccurred())
535//	})
536func SynchronizedBeforeSuite(node1Body interface{}, allNodesBody interface{}, timeout ...float64) bool {
537	globalSuite.SetSynchronizedBeforeSuiteNode(
538		node1Body,
539		allNodesBody,
540		codelocation.New(1),
541		parseTimeout(timeout...),
542	)
543	return true
544}
545
546//SynchronizedAfterSuite blocks complement the SynchronizedBeforeSuite blocks in solving the problem of setting up
547//external singleton resources shared across nodes when running tests in parallel.
548//
549//SynchronizedAfterSuite accomplishes this by taking *two* function arguments.  The first runs on all nodes.  The second runs only on parallel node #1
550//and *only* after all other nodes have finished and exited.  This ensures that node 1, and any resources it is running, remain alive until
551//all other nodes are finished.
552//
553//Both functions have the same signature: either func() or func(done Done) to run asynchronously.
554//
555//Here's a pseudo-code example that complements that given in SynchronizedBeforeSuite.  Here, SynchronizedAfterSuite is used to tear down the shared database
556//only after all nodes have finished:
557//
558//	var _ = SynchronizedAfterSuite(func() {
559//		dbClient.Cleanup()
560//	}, func() {
561//		dbRunner.Stop()
562//	})
563func SynchronizedAfterSuite(allNodesBody interface{}, node1Body interface{}, timeout ...float64) bool {
564	globalSuite.SetSynchronizedAfterSuiteNode(
565		allNodesBody,
566		node1Body,
567		codelocation.New(1),
568		parseTimeout(timeout...),
569	)
570	return true
571}
572
573//BeforeEach blocks are run before It blocks.  When multiple BeforeEach blocks are defined in nested
574//Describe and Context blocks the outermost BeforeEach blocks are run first.
575//
576//Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts
577//a Done channel
578func BeforeEach(body interface{}, timeout ...float64) bool {
579	globalSuite.PushBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
580	return true
581}
582
583//JustBeforeEach blocks are run before It blocks but *after* all BeforeEach blocks.  For more details,
584//read the [documentation](http://onsi.github.io/ginkgo/#separating_creation_and_configuration_)
585//
586//Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts
587//a Done channel
588func JustBeforeEach(body interface{}, timeout ...float64) bool {
589	globalSuite.PushJustBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
590	return true
591}
592
593//JustAfterEach blocks are run after It blocks but *before* all AfterEach blocks.  For more details,
594//read the [documentation](http://onsi.github.io/ginkgo/#separating_creation_and_configuration_)
595//
596//Like It blocks, JustAfterEach blocks can be made asynchronous by providing a body function that accepts
597//a Done channel
598func JustAfterEach(body interface{}, timeout ...float64) bool {
599	globalSuite.PushJustAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
600	return true
601}
602
603//AfterEach blocks are run after It blocks.   When multiple AfterEach blocks are defined in nested
604//Describe and Context blocks the innermost AfterEach blocks are run first.
605//
606//Like It blocks, AfterEach blocks can be made asynchronous by providing a body function that accepts
607//a Done channel
608func AfterEach(body interface{}, timeout ...float64) bool {
609	globalSuite.PushAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
610	return true
611}
612
613func parseTimeout(timeout ...float64) time.Duration {
614	if len(timeout) == 0 {
615		return time.Duration(defaultTimeout * int64(time.Second))
616	} else {
617		return time.Duration(timeout[0] * float64(time.Second))
618	}
619}
620