Add e2e tests

This commit is contained in:
Manuel de Brito Fontes 2017-10-17 19:50:27 -03:00
parent 99a355f25d
commit 601fb7dacf
1163 changed files with 289217 additions and 14195 deletions

View file

@ -0,0 +1,151 @@
package containernode
import (
"math/rand"
"sort"
"github.com/onsi/ginkgo/internal/leafnodes"
"github.com/onsi/ginkgo/types"
)
type subjectOrContainerNode struct {
containerNode *ContainerNode
subjectNode leafnodes.SubjectNode
}
func (n subjectOrContainerNode) text() string {
if n.containerNode != nil {
return n.containerNode.Text()
} else {
return n.subjectNode.Text()
}
}
type CollatedNodes struct {
Containers []*ContainerNode
Subject leafnodes.SubjectNode
}
type ContainerNode struct {
text string
flag types.FlagType
codeLocation types.CodeLocation
setupNodes []leafnodes.BasicNode
subjectAndContainerNodes []subjectOrContainerNode
}
func New(text string, flag types.FlagType, codeLocation types.CodeLocation) *ContainerNode {
return &ContainerNode{
text: text,
flag: flag,
codeLocation: codeLocation,
}
}
func (container *ContainerNode) Shuffle(r *rand.Rand) {
sort.Sort(container)
permutation := r.Perm(len(container.subjectAndContainerNodes))
shuffledNodes := make([]subjectOrContainerNode, len(container.subjectAndContainerNodes))
for i, j := range permutation {
shuffledNodes[i] = container.subjectAndContainerNodes[j]
}
container.subjectAndContainerNodes = shuffledNodes
}
func (node *ContainerNode) BackPropagateProgrammaticFocus() bool {
if node.flag == types.FlagTypePending {
return false
}
shouldUnfocus := false
for _, subjectOrContainerNode := range node.subjectAndContainerNodes {
if subjectOrContainerNode.containerNode != nil {
shouldUnfocus = subjectOrContainerNode.containerNode.BackPropagateProgrammaticFocus() || shouldUnfocus
} else {
shouldUnfocus = (subjectOrContainerNode.subjectNode.Flag() == types.FlagTypeFocused) || shouldUnfocus
}
}
if shouldUnfocus {
if node.flag == types.FlagTypeFocused {
node.flag = types.FlagTypeNone
}
return true
}
return node.flag == types.FlagTypeFocused
}
func (node *ContainerNode) Collate() []CollatedNodes {
return node.collate([]*ContainerNode{})
}
func (node *ContainerNode) collate(enclosingContainers []*ContainerNode) []CollatedNodes {
collated := make([]CollatedNodes, 0)
containers := make([]*ContainerNode, len(enclosingContainers))
copy(containers, enclosingContainers)
containers = append(containers, node)
for _, subjectOrContainer := range node.subjectAndContainerNodes {
if subjectOrContainer.containerNode != nil {
collated = append(collated, subjectOrContainer.containerNode.collate(containers)...)
} else {
collated = append(collated, CollatedNodes{
Containers: containers,
Subject: subjectOrContainer.subjectNode,
})
}
}
return collated
}
func (node *ContainerNode) PushContainerNode(container *ContainerNode) {
node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{containerNode: container})
}
func (node *ContainerNode) PushSubjectNode(subject leafnodes.SubjectNode) {
node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{subjectNode: subject})
}
func (node *ContainerNode) PushSetupNode(setupNode leafnodes.BasicNode) {
node.setupNodes = append(node.setupNodes, setupNode)
}
func (node *ContainerNode) SetupNodesOfType(nodeType types.SpecComponentType) []leafnodes.BasicNode {
nodes := []leafnodes.BasicNode{}
for _, setupNode := range node.setupNodes {
if setupNode.Type() == nodeType {
nodes = append(nodes, setupNode)
}
}
return nodes
}
func (node *ContainerNode) Text() string {
return node.text
}
func (node *ContainerNode) CodeLocation() types.CodeLocation {
return node.codeLocation
}
func (node *ContainerNode) Flag() types.FlagType {
return node.flag
}
//sort.Interface
func (node *ContainerNode) Len() int {
return len(node.subjectAndContainerNodes)
}
func (node *ContainerNode) Less(i, j int) bool {
return node.subjectAndContainerNodes[i].text() < node.subjectAndContainerNodes[j].text()
}
func (node *ContainerNode) Swap(i, j int) {
node.subjectAndContainerNodes[i], node.subjectAndContainerNodes[j] = node.subjectAndContainerNodes[j], node.subjectAndContainerNodes[i]
}

View file

@ -0,0 +1,13 @@
package containernode_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestContainernode(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Containernode Suite")
}

View file

@ -0,0 +1,212 @@
package containernode_test
import (
"github.com/onsi/ginkgo/internal/leafnodes"
"math/rand"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/ginkgo/internal/codelocation"
. "github.com/onsi/ginkgo/internal/containernode"
"github.com/onsi/ginkgo/types"
)
var _ = Describe("Container Node", func() {
var (
codeLocation types.CodeLocation
container *ContainerNode
)
BeforeEach(func() {
codeLocation = codelocation.New(0)
container = New("description text", types.FlagTypeFocused, codeLocation)
})
Describe("creating a container node", func() {
It("can answer questions about itself", func() {
Ω(container.Text()).Should(Equal("description text"))
Ω(container.Flag()).Should(Equal(types.FlagTypeFocused))
Ω(container.CodeLocation()).Should(Equal(codeLocation))
})
})
Describe("pushing setup nodes", func() {
It("can append setup nodes of various types and fetch them by type", func() {
befA := leafnodes.NewBeforeEachNode(func() {}, codelocation.New(0), 0, nil, 0)
befB := leafnodes.NewBeforeEachNode(func() {}, codelocation.New(0), 0, nil, 0)
aftA := leafnodes.NewAfterEachNode(func() {}, codelocation.New(0), 0, nil, 0)
aftB := leafnodes.NewAfterEachNode(func() {}, codelocation.New(0), 0, nil, 0)
jusBefA := leafnodes.NewJustBeforeEachNode(func() {}, codelocation.New(0), 0, nil, 0)
jusBefB := leafnodes.NewJustBeforeEachNode(func() {}, codelocation.New(0), 0, nil, 0)
container.PushSetupNode(befA)
container.PushSetupNode(befB)
container.PushSetupNode(aftA)
container.PushSetupNode(aftB)
container.PushSetupNode(jusBefA)
container.PushSetupNode(jusBefB)
subject := leafnodes.NewItNode("subject", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
container.PushSubjectNode(subject)
Ω(container.SetupNodesOfType(types.SpecComponentTypeBeforeEach)).Should(Equal([]leafnodes.BasicNode{befA, befB}))
Ω(container.SetupNodesOfType(types.SpecComponentTypeAfterEach)).Should(Equal([]leafnodes.BasicNode{aftA, aftB}))
Ω(container.SetupNodesOfType(types.SpecComponentTypeJustBeforeEach)).Should(Equal([]leafnodes.BasicNode{jusBefA, jusBefB}))
Ω(container.SetupNodesOfType(types.SpecComponentTypeIt)).Should(BeEmpty()) //subjects are not setup nodes
})
})
Context("With appended containers and subject nodes", func() {
var (
itA, itB, innerItA, innerItB leafnodes.SubjectNode
innerContainer *ContainerNode
)
BeforeEach(func() {
itA = leafnodes.NewItNode("Banana", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
itB = leafnodes.NewItNode("Apple", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
innerItA = leafnodes.NewItNode("inner A", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
innerItB = leafnodes.NewItNode("inner B", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
innerContainer = New("Orange", types.FlagTypeNone, codelocation.New(0))
container.PushSubjectNode(itA)
container.PushContainerNode(innerContainer)
innerContainer.PushSubjectNode(innerItA)
innerContainer.PushSubjectNode(innerItB)
container.PushSubjectNode(itB)
})
Describe("Collating", func() {
It("should return a collated set of containers and subject nodes in the correct order", func() {
collated := container.Collate()
Ω(collated).Should(HaveLen(4))
Ω(collated[0]).Should(Equal(CollatedNodes{
Containers: []*ContainerNode{container},
Subject: itA,
}))
Ω(collated[1]).Should(Equal(CollatedNodes{
Containers: []*ContainerNode{container, innerContainer},
Subject: innerItA,
}))
Ω(collated[2]).Should(Equal(CollatedNodes{
Containers: []*ContainerNode{container, innerContainer},
Subject: innerItB,
}))
Ω(collated[3]).Should(Equal(CollatedNodes{
Containers: []*ContainerNode{container},
Subject: itB,
}))
})
})
Describe("Backpropagating Programmatic Focus", func() {
//This allows inner focused specs to override the focus of outer focussed
//specs and more closely maps to what a developer wants to happen
//when debugging a test suite
Context("when a parent is focused *and* an inner subject is focused", func() {
BeforeEach(func() {
container = New("description text", types.FlagTypeFocused, codeLocation)
itA = leafnodes.NewItNode("A", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
container.PushSubjectNode(itA)
innerContainer = New("Orange", types.FlagTypeNone, codelocation.New(0))
container.PushContainerNode(innerContainer)
innerItA = leafnodes.NewItNode("inner A", func() {}, types.FlagTypeFocused, codelocation.New(0), 0, nil, 0)
innerContainer.PushSubjectNode(innerItA)
})
It("should unfocus the parent", func() {
container.BackPropagateProgrammaticFocus()
Ω(container.Flag()).Should(Equal(types.FlagTypeNone))
Ω(itA.Flag()).Should(Equal(types.FlagTypeNone))
Ω(innerContainer.Flag()).Should(Equal(types.FlagTypeNone))
Ω(innerItA.Flag()).Should(Equal(types.FlagTypeFocused))
})
})
Context("when a parent is focused *and* an inner container is focused", func() {
BeforeEach(func() {
container = New("description text", types.FlagTypeFocused, codeLocation)
itA = leafnodes.NewItNode("A", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
container.PushSubjectNode(itA)
innerContainer = New("Orange", types.FlagTypeFocused, codelocation.New(0))
container.PushContainerNode(innerContainer)
innerItA = leafnodes.NewItNode("inner A", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
innerContainer.PushSubjectNode(innerItA)
})
It("should unfocus the parent", func() {
container.BackPropagateProgrammaticFocus()
Ω(container.Flag()).Should(Equal(types.FlagTypeNone))
Ω(itA.Flag()).Should(Equal(types.FlagTypeNone))
Ω(innerContainer.Flag()).Should(Equal(types.FlagTypeFocused))
Ω(innerItA.Flag()).Should(Equal(types.FlagTypeNone))
})
})
Context("when a parent is pending and a child is focused", func() {
BeforeEach(func() {
container = New("description text", types.FlagTypeFocused, codeLocation)
itA = leafnodes.NewItNode("A", func() {}, types.FlagTypeNone, codelocation.New(0), 0, nil, 0)
container.PushSubjectNode(itA)
innerContainer = New("Orange", types.FlagTypePending, codelocation.New(0))
container.PushContainerNode(innerContainer)
innerItA = leafnodes.NewItNode("inner A", func() {}, types.FlagTypeFocused, codelocation.New(0), 0, nil, 0)
innerContainer.PushSubjectNode(innerItA)
})
It("should not do anything", func() {
container.BackPropagateProgrammaticFocus()
Ω(container.Flag()).Should(Equal(types.FlagTypeFocused))
Ω(itA.Flag()).Should(Equal(types.FlagTypeNone))
Ω(innerContainer.Flag()).Should(Equal(types.FlagTypePending))
Ω(innerItA.Flag()).Should(Equal(types.FlagTypeFocused))
})
})
})
Describe("Shuffling", func() {
var unshuffledCollation []CollatedNodes
BeforeEach(func() {
unshuffledCollation = container.Collate()
r := rand.New(rand.NewSource(17))
container.Shuffle(r)
})
It("should sort, and then shuffle, the top level contents of the container", func() {
shuffledCollation := container.Collate()
Ω(shuffledCollation).Should(HaveLen(len(unshuffledCollation)))
Ω(shuffledCollation).ShouldNot(Equal(unshuffledCollation))
for _, entry := range unshuffledCollation {
Ω(shuffledCollation).Should(ContainElement(entry))
}
innerAIndex, innerBIndex := 0, 0
for i, entry := range shuffledCollation {
if entry.Subject == innerItA {
innerAIndex = i
} else if entry.Subject == innerItB {
innerBIndex = i
}
}
Ω(innerAIndex).Should(Equal(innerBIndex - 1))
})
})
})
})