github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/types/types_test.go (about)

     1  package types_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"time"
     6  
     7  	. "github.com/onsi/ginkgo"
     8  	. "github.com/onsi/gomega"
     9  
    10  	"github.com/onsi/ginkgo/types"
    11  )
    12  
    13  var _ = Describe("Types", func() {
    14  	Describe("Report", func() {
    15  		Describe("Add", func() {
    16  			It("concatenates spec reports, combines success, and computes a new RunTime", func() {
    17  				t := time.Now()
    18  				reportA := types.Report{
    19  					SuitePath:                  "foo",
    20  					SuiteSucceeded:             true,
    21  					StartTime:                  t.Add(-time.Minute),
    22  					EndTime:                    t.Add(2 * time.Minute),
    23  					SpecialSuiteFailureReasons: []string{"blame jim", "blame alice"},
    24  					SpecReports: types.SpecReports{
    25  						types.SpecReport{NumAttempts: 3},
    26  						types.SpecReport{NumAttempts: 4},
    27  					},
    28  				}
    29  
    30  				reportB := types.Report{
    31  					SuitePath:                  "bar",
    32  					SuiteSucceeded:             false,
    33  					StartTime:                  t.Add(-2 * time.Minute),
    34  					EndTime:                    t.Add(time.Minute),
    35  					SpecialSuiteFailureReasons: []string{"blame bob", "blame jim"},
    36  					SpecReports: types.SpecReports{
    37  						types.SpecReport{NumAttempts: 5},
    38  						types.SpecReport{NumAttempts: 6},
    39  					},
    40  				}
    41  
    42  				composite := reportA.Add(reportB)
    43  				Ω(composite).Should(Equal(types.Report{
    44  					SuitePath:                  "foo",
    45  					SuiteSucceeded:             false,
    46  					StartTime:                  t.Add(-2 * time.Minute),
    47  					EndTime:                    t.Add(2 * time.Minute),
    48  					RunTime:                    4 * time.Minute,
    49  					SpecialSuiteFailureReasons: []string{"blame jim", "blame alice", "blame bob"},
    50  					SpecReports: types.SpecReports{
    51  						types.SpecReport{NumAttempts: 3},
    52  						types.SpecReport{NumAttempts: 4},
    53  						types.SpecReport{NumAttempts: 5},
    54  						types.SpecReport{NumAttempts: 6},
    55  					},
    56  				}))
    57  
    58  			})
    59  		})
    60  	})
    61  
    62  	Describe("NodeType", func() {
    63  		Describe("Is", func() {
    64  			It("returns true when the NodeType is in the passed-in list", func() {
    65  				Ω(types.NodeTypeContainer.Is(types.NodeTypeIt | types.NodeTypeContainer)).Should(BeTrue())
    66  			})
    67  
    68  			It("returns false when the NodeType is not in the passed-in list", func() {
    69  				Ω(types.NodeTypeContainer.Is(types.NodeTypeIt | types.NodeTypeBeforeEach)).Should(BeFalse())
    70  			})
    71  		})
    72  
    73  		DescribeTable("Representation and Encoding", func(nodeType types.NodeType, expectedString string) {
    74  			Ω(nodeType.String()).Should(Equal(expectedString))
    75  
    76  			marshalled, err := json.Marshal(nodeType)
    77  			Ω(err).ShouldNot(HaveOccurred())
    78  			var unmarshalled types.NodeType
    79  			json.Unmarshal(marshalled, &unmarshalled)
    80  			Ω(unmarshalled).Should(Equal(nodeType))
    81  		},
    82  			func(nodeType types.NodeType, expectedString string) string {
    83  				return expectedString
    84  			},
    85  			Entry(nil, types.NodeTypeContainer, "Container"),
    86  			Entry(nil, types.NodeTypeIt, "It"),
    87  			Entry(nil, types.NodeTypeBeforeEach, "BeforeEach"),
    88  			Entry(nil, types.NodeTypeJustBeforeEach, "JustBeforeEach"),
    89  			Entry(nil, types.NodeTypeAfterEach, "AfterEach"),
    90  			Entry(nil, types.NodeTypeJustAfterEach, "JustAfterEach"),
    91  			Entry(nil, types.NodeTypeBeforeAll, "BeforeAll"),
    92  			Entry(nil, types.NodeTypeAfterAll, "AfterAll"),
    93  			Entry(nil, types.NodeTypeBeforeSuite, "BeforeSuite"),
    94  			Entry(nil, types.NodeTypeSynchronizedBeforeSuite, "SynchronizedBeforeSuite"),
    95  			Entry(nil, types.NodeTypeAfterSuite, "AfterSuite"),
    96  			Entry(nil, types.NodeTypeSynchronizedAfterSuite, "SynchronizedAfterSuite"),
    97  			Entry(nil, types.NodeTypeReportBeforeEach, "ReportBeforeEach"),
    98  			Entry(nil, types.NodeTypeReportAfterEach, "ReportAfterEach"),
    99  			Entry(nil, types.NodeTypeReportAfterSuite, "ReportAfterSuite"),
   100  			Entry(nil, types.NodeTypeCleanupInvalid, "INVALID CLEANUP NODE"),
   101  			Entry(nil, types.NodeTypeCleanupAfterEach, "DeferCleanup (AfterEach)"),
   102  			Entry(nil, types.NodeTypeCleanupAfterAll, "DeferCleanup (AfterAll)"),
   103  			Entry(nil, types.NodeTypeCleanupAfterSuite, "DeferCleanup (AfterSuite)"),
   104  			Entry(nil, types.NodeTypeInvalid, "INVALID NODE TYPE"),
   105  		)
   106  	})
   107  
   108  	Describe("FailureNodeContext", func() {
   109  		DescribeTable("Representation and Encoding", func(context types.FailureNodeContext) {
   110  			marshalled, err := json.Marshal(context)
   111  			Ω(err).ShouldNot(HaveOccurred())
   112  			var unmarshalled types.FailureNodeContext
   113  			json.Unmarshal(marshalled, &unmarshalled)
   114  			Ω(unmarshalled).Should(Equal(context))
   115  		},
   116  			Entry("LeafNode", types.FailureNodeIsLeafNode),
   117  			Entry("TopLevel", types.FailureNodeAtTopLevel),
   118  			Entry("InContainer", types.FailureNodeInContainer),
   119  			Entry("Invalid", types.FailureNodeContextInvalid),
   120  		)
   121  	})
   122  
   123  	Describe("SpecState", func() {
   124  		DescribeTable("Representation and Encoding", func(specState types.SpecState, expectedString string) {
   125  			Ω(specState.String()).Should(Equal(expectedString))
   126  
   127  			marshalled, err := json.Marshal(specState)
   128  			Ω(err).ShouldNot(HaveOccurred())
   129  			var unmarshalled types.SpecState
   130  			json.Unmarshal(marshalled, &unmarshalled)
   131  			Ω(unmarshalled).Should(Equal(specState))
   132  		},
   133  			Entry("Pending", types.SpecStatePending, "pending"),
   134  			Entry("Skipped", types.SpecStateSkipped, "skipped"),
   135  			Entry("Passed", types.SpecStatePassed, "passed"),
   136  			Entry("Failed", types.SpecStateFailed, "failed"),
   137  			Entry("Panicked", types.SpecStatePanicked, "panicked"),
   138  			Entry("Aborted", types.SpecStateAborted, "aborted"),
   139  			Entry("Interrupted", types.SpecStateInterrupted, "interrupted"),
   140  			Entry("Invalid", types.SpecStateInvalid, "INVALID SPEC STATE"),
   141  		)
   142  	})
   143  
   144  	Describe("SpecReport Helper Functions", func() {
   145  		Describe("CombinedOutput", func() {
   146  			Context("with no GinkgoWriter or StdOutErr output", func() {
   147  				It("comes back empty", func() {
   148  					Ω(types.SpecReport{}.CombinedOutput()).Should(Equal(""))
   149  				})
   150  			})
   151  
   152  			Context("wtih only StdOutErr output", func() {
   153  				It("returns that output", func() {
   154  					Ω(types.SpecReport{
   155  						CapturedStdOutErr: "hello",
   156  					}.CombinedOutput()).Should(Equal("hello"))
   157  				})
   158  			})
   159  
   160  			Context("wtih only GinkgoWriter output", func() {
   161  				It("returns that output", func() {
   162  					Ω(types.SpecReport{
   163  						CapturedGinkgoWriterOutput: "hello",
   164  					}.CombinedOutput()).Should(Equal("hello"))
   165  				})
   166  			})
   167  
   168  			Context("with both", func() {
   169  				It("returns both concatenated", func() {
   170  					Ω(types.SpecReport{
   171  						CapturedGinkgoWriterOutput: "gw",
   172  						CapturedStdOutErr:          "std",
   173  					}.CombinedOutput()).Should(Equal("std\ngw"))
   174  				})
   175  			})
   176  		})
   177  
   178  		Describe("Labels", Label("TestA", "TestB"), func() {
   179  			It("returns a concatenated, deduped, set of labels", Label("TestB", "TestC"), func() {
   180  				Ω(CurrentSpecReport().Labels()).Should(Equal([]string{"TestA", "TestB", "TestC"}))
   181  			})
   182  		})
   183  
   184  		Describe("MatchesLabelFilter", Label("dog", "cat"), func() {
   185  			It("returns an error when passed an invalid filter query", func() {
   186  				matches, err := CurrentSpecReport().MatchesLabelFilter("(welp")
   187  				Ω(err).Should(HaveOccurred())
   188  				Ω(matches).Should(BeFalse())
   189  			})
   190  
   191  			It("returns whether or not the query matches", Label("catfish"), func() {
   192  				Ω(CurrentSpecReport().MatchesLabelFilter("dog")).Should(BeTrue())
   193  				Ω(CurrentSpecReport().MatchesLabelFilter("cow || cat")).Should(BeTrue())
   194  				Ω(CurrentSpecReport().MatchesLabelFilter("/fish/")).Should(BeTrue())
   195  				Ω(CurrentSpecReport().MatchesLabelFilter("dog && !/fish/")).Should(BeFalse())
   196  			})
   197  		})
   198  
   199  		It("can report on whether state is a failed state", func() {
   200  			Ω(types.SpecReport{State: types.SpecStatePending}.Failed()).Should(BeFalse())
   201  			Ω(types.SpecReport{State: types.SpecStateSkipped}.Failed()).Should(BeFalse())
   202  			Ω(types.SpecReport{State: types.SpecStatePassed}.Failed()).Should(BeFalse())
   203  			Ω(types.SpecReport{State: types.SpecStateFailed}.Failed()).Should(BeTrue())
   204  			Ω(types.SpecReport{State: types.SpecStatePanicked}.Failed()).Should(BeTrue())
   205  			Ω(types.SpecReport{State: types.SpecStateAborted}.Failed()).Should(BeTrue())
   206  			Ω(types.SpecReport{State: types.SpecStateInterrupted}.Failed()).Should(BeTrue())
   207  		})
   208  
   209  		It("can return a concatenated set of texts", func() {
   210  			Ω(CurrentSpecReport().FullText()).Should(Equal("Types SpecReport Helper Functions can return a concatenated set of texts"))
   211  		})
   212  
   213  		It("can return the name of the file it's spec is in", func() {
   214  			cl := types.NewCodeLocation(0)
   215  			Ω(CurrentSpecReport().FileName()).Should(Equal(cl.FileName))
   216  		})
   217  
   218  		It("can return the linenumber of the file it's spec is in", func() {
   219  			cl := types.NewCodeLocation(0)
   220  			Ω(CurrentSpecReport().LineNumber()).Should(Equal(cl.LineNumber - 1))
   221  		})
   222  
   223  		It("can return it's failure's message", func() {
   224  			report := types.SpecReport{
   225  				Failure: types.Failure{Message: "why this failed"},
   226  			}
   227  			Ω(report.FailureMessage()).Should(Equal("why this failed"))
   228  		})
   229  
   230  		It("can return it's failure's code location", func() {
   231  			cl := types.NewCodeLocation(0)
   232  			report := types.SpecReport{
   233  				Failure: types.Failure{Location: cl},
   234  			}
   235  			Ω(report.FailureLocation()).Should(Equal(cl))
   236  		})
   237  	})
   238  
   239  	Describe("SpecReports", func() {
   240  		Describe("Encoding to JSON", func() {
   241  			var report types.SpecReport
   242  			BeforeEach(func() {
   243  				report = types.SpecReport{
   244  					ContainerHierarchyTexts: []string{"A", "B"},
   245  					ContainerHierarchyLocations: []types.CodeLocation{
   246  						types.NewCodeLocation(0),
   247  						types.NewCodeLocationWithStackTrace(0),
   248  						types.NewCustomCodeLocation("welp"),
   249  					},
   250  					LeafNodeType:               types.NodeTypeIt,
   251  					LeafNodeLocation:           types.NewCodeLocation(0),
   252  					LeafNodeText:               "C",
   253  					State:                      types.SpecStateFailed,
   254  					StartTime:                  time.Date(2012, 06, 19, 05, 32, 12, 0, time.UTC),
   255  					EndTime:                    time.Date(2012, 06, 19, 05, 33, 12, 0, time.UTC),
   256  					RunTime:                    time.Minute,
   257  					ParallelProcess:            2,
   258  					NumAttempts:                3,
   259  					CapturedGinkgoWriterOutput: "gw",
   260  					CapturedStdOutErr:          "std",
   261  					Failure: types.Failure{
   262  						Message:                   "boom",
   263  						Location:                  types.NewCodeLocation(1),
   264  						ForwardedPanic:            "bam",
   265  						FailureNodeContext:        types.FailureNodeInContainer,
   266  						FailureNodeType:           types.NodeTypeBeforeEach,
   267  						FailureNodeLocation:       types.NewCodeLocation(0),
   268  						FailureNodeContainerIndex: 1,
   269  					},
   270  				}
   271  			})
   272  
   273  			Context("with a failure", func() {
   274  				It("round-trips correctly", func() {
   275  					marshalled, err := json.Marshal(report)
   276  					Ω(err).ShouldNot(HaveOccurred())
   277  					unmarshalled := types.SpecReport{}
   278  					err = json.Unmarshal(marshalled, &unmarshalled)
   279  					Ω(err).ShouldNot(HaveOccurred())
   280  					Ω(unmarshalled).Should(Equal(report))
   281  				})
   282  			})
   283  
   284  			Context("without a failure", func() {
   285  				BeforeEach(func() {
   286  					report.Failure = types.Failure{}
   287  				})
   288  				It("round-trips correclty and doesn't include the Failure struct", func() {
   289  					marshalled, err := json.Marshal(report)
   290  					Ω(string(marshalled)).ShouldNot(ContainSubstring("Failure"))
   291  					Ω(err).ShouldNot(HaveOccurred())
   292  					unmarshalled := types.SpecReport{}
   293  					err = json.Unmarshal(marshalled, &unmarshalled)
   294  					Ω(err).ShouldNot(HaveOccurred())
   295  					Ω(unmarshalled).Should(Equal(report))
   296  				})
   297  			})
   298  		})
   299  
   300  		Describe("WithLeafNodeType", func() {
   301  			It("returns reports with the matching LeafNodeTypes", func() {
   302  				reports := types.SpecReports{
   303  					{LeafNodeType: types.NodeTypeIt, NumAttempts: 2},
   304  					{LeafNodeType: types.NodeTypeIt, NumAttempts: 3},
   305  					{LeafNodeType: types.NodeTypeBeforeSuite, NumAttempts: 4},
   306  					{LeafNodeType: types.NodeTypeAfterSuite, NumAttempts: 5},
   307  					{LeafNodeType: types.NodeTypeSynchronizedAfterSuite, NumAttempts: 6},
   308  				}
   309  
   310  				Ω(reports.WithLeafNodeType(types.NodeTypeIt | types.NodeTypeAfterSuite)).Should(Equal(types.SpecReports{
   311  					{LeafNodeType: types.NodeTypeIt, NumAttempts: 2},
   312  					{LeafNodeType: types.NodeTypeIt, NumAttempts: 3},
   313  					{LeafNodeType: types.NodeTypeAfterSuite, NumAttempts: 5},
   314  				}))
   315  			})
   316  		})
   317  
   318  		Describe("WithState", func() {
   319  			It("returns reports with the matching SpecStates", func() {
   320  				reports := types.SpecReports{
   321  					{State: types.SpecStatePassed, NumAttempts: 2},
   322  					{State: types.SpecStatePassed, NumAttempts: 3},
   323  					{State: types.SpecStateFailed, NumAttempts: 4},
   324  					{State: types.SpecStatePending, NumAttempts: 5},
   325  					{State: types.SpecStateSkipped, NumAttempts: 6},
   326  				}
   327  
   328  				Ω(reports.WithState(types.SpecStatePassed | types.SpecStatePending)).Should(Equal(types.SpecReports{
   329  					{State: types.SpecStatePassed, NumAttempts: 2},
   330  					{State: types.SpecStatePassed, NumAttempts: 3},
   331  					{State: types.SpecStatePending, NumAttempts: 5},
   332  				}))
   333  			})
   334  		})
   335  
   336  		Describe("CountWithState", func() {
   337  			It("returns the number with the matching SpecStates", func() {
   338  				reports := types.SpecReports{
   339  					{State: types.SpecStatePassed, NumAttempts: 2},
   340  					{State: types.SpecStatePassed, NumAttempts: 3},
   341  					{State: types.SpecStateFailed, NumAttempts: 4},
   342  					{State: types.SpecStatePending, NumAttempts: 5},
   343  					{State: types.SpecStateSkipped, NumAttempts: 6},
   344  				}
   345  
   346  				Ω(reports.CountWithState(types.SpecStatePassed | types.SpecStatePending)).Should(Equal(3))
   347  			})
   348  		})
   349  
   350  		Describe("CountOfFlakedSpecs", func() {
   351  			It("returns the number of passing specs with NumAttempts > 1", func() {
   352  				reports := types.SpecReports{
   353  					{State: types.SpecStatePassed, NumAttempts: 2},
   354  					{State: types.SpecStatePassed, NumAttempts: 2},
   355  					{State: types.SpecStatePassed, NumAttempts: 1},
   356  					{State: types.SpecStatePassed, NumAttempts: 1},
   357  					{State: types.SpecStateFailed, NumAttempts: 2},
   358  				}
   359  
   360  				Ω(reports.CountOfFlakedSpecs()).Should(Equal(2))
   361  			})
   362  		})
   363  	})
   364  })