152 lines
4.1 KiB
Go
152 lines
4.1 KiB
Go
|
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]
|
||
|
}
|