How to use packageAndIdentNamesFromCallExpr method of outline Package

Best Ginkgo code snippet using outline.packageAndIdentNamesFromCallExpr

Run Ginkgo automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

ginkgo.go

Source: ginkgo.go Github

copy
1package outline
2
3import (
4	"go/ast"
5	"go/token"
6	"strconv"
7)
8
9const (
10	// undefinedTextAlt is used if the spec/container text cannot be derived
11	undefinedTextAlt = "undefined"
12)
13
14// ginkgoMetadata holds useful bits of information for every entry in the outline
15type ginkgoMetadata struct {
16	// Name is the spec or container function name, e.g. `Describe` or `It`
17	Name string `json:"name"`
18
19	// Text is the `text` argument passed to specs, and some containers
20	Text string `json:"text"`
21
22	// Start is the position of first character of the spec or container block
23	Start int `json:"start"`
24
25	// End is the position of first character immediately after the spec or container block
26	End int `json:"end"`
27
28	Spec    bool `json:"spec"`
29	Focused bool `json:"focused"`
30	Pending bool `json:"pending"`
31}
32
33// ginkgoNode is used to construct the outline as a tree
34type ginkgoNode struct {
35	ginkgoMetadata
36	Nodes []*ginkgoNode `json:"nodes"`
37}
38
39type walkFunc func(n *ginkgoNode)
40
41func (n *ginkgoNode) PreOrder(f walkFunc) {
42	f(n)
43	for _, m := range n.Nodes {
44		m.PreOrder(f)
45	}
46}
47
48func (n *ginkgoNode) PostOrder(f walkFunc) {
49	for _, m := range n.Nodes {
50		m.PostOrder(f)
51	}
52	f(n)
53}
54
55func (n *ginkgoNode) Walk(pre, post walkFunc) {
56	pre(n)
57	for _, m := range n.Nodes {
58		m.Walk(pre, post)
59	}
60	post(n)
61}
62
63// PropagateInheritedProperties propagates the Pending and Focused properties
64// through the subtree rooted at n.
65func (n *ginkgoNode) PropagateInheritedProperties() {
66	n.PreOrder(func(thisNode *ginkgoNode) {
67		for _, descendantNode := range thisNode.Nodes {
68			if thisNode.Pending {
69				descendantNode.Pending = true
70				descendantNode.Focused = false
71			}
72			if thisNode.Focused && !descendantNode.Pending {
73				descendantNode.Focused = true
74			}
75		}
76	})
77}
78
79// BackpropagateUnfocus propagates the Focused property through the subtree
80// rooted at n. It applies the rule described in the Ginkgo docs:
81// > Nested programmatically focused specs follow a simple rule: if a
82// > leaf-node is marked focused, any of its ancestor nodes that are marked
83// > focus will be unfocused.
84func (n *ginkgoNode) BackpropagateUnfocus() {
85	focusedSpecInSubtreeStack := []bool{}
86	n.PostOrder(func(thisNode *ginkgoNode) {
87		if thisNode.Spec {
88			focusedSpecInSubtreeStack = append(focusedSpecInSubtreeStack, thisNode.Focused)
89			return
90		}
91		focusedSpecInSubtree := false
92		for range thisNode.Nodes {
93			focusedSpecInSubtree = focusedSpecInSubtree || focusedSpecInSubtreeStack[len(focusedSpecInSubtreeStack)-1]
94			focusedSpecInSubtreeStack = focusedSpecInSubtreeStack[0 : len(focusedSpecInSubtreeStack)-1]
95		}
96		focusedSpecInSubtreeStack = append(focusedSpecInSubtreeStack, focusedSpecInSubtree)
97		if focusedSpecInSubtree {
98			thisNode.Focused = false
99		}
100	})
101
102}
103
104func packageAndIdentNamesFromCallExpr(ce *ast.CallExpr) (string, string, bool) {
105	switch ex := ce.Fun.(type) {
106	case *ast.Ident:
107		return "", ex.Name, true
108	case *ast.SelectorExpr:
109		pkgID, ok := ex.X.(*ast.Ident)
110		if !ok {
111			return "", "", false
112		}
113		// A package identifier is top-level, so Obj must be nil
114		if pkgID.Obj != nil {
115			return "", "", false
116		}
117		if ex.Sel == nil {
118			return "", "", false
119		}
120		return pkgID.Name, ex.Sel.Name, true
121	default:
122		return "", "", false
123	}
124}
125
126// absoluteOffsetsForNode derives the absolute character offsets of the node start and
127// end positions.
128func absoluteOffsetsForNode(fset *token.FileSet, n ast.Node) (start, end int) {
129	return fset.PositionFor(n.Pos(), false).Offset, fset.PositionFor(n.End(), false).Offset
130}
131
132// ginkgoNodeFromCallExpr derives an outline entry from a go AST subtree
133// corresponding to a Ginkgo container or spec.
134func ginkgoNodeFromCallExpr(fset *token.FileSet, ce *ast.CallExpr, ginkgoPackageName, tablePackageName *string) (*ginkgoNode, bool) {
135	packageName, identName, ok := packageAndIdentNamesFromCallExpr(ce)
136	if !ok {
137		return nil, false
138	}
139
140	n := ginkgoNode{}
141	n.Name = identName
142	n.Start, n.End = absoluteOffsetsForNode(fset, ce)
143	n.Nodes = make([]*ginkgoNode, 0)
144	switch identName {
145	case "It", "Measure", "Specify":
146		n.Spec = true
147		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
148		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
149	case "Entry":
150		n.Spec = true
151		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
152		return &n, tablePackageName != nil && *tablePackageName == packageName
153	case "FIt", "FMeasure", "FSpecify":
154		n.Spec = true
155		n.Focused = true
156		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
157		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
158	case "FEntry":
159		n.Spec = true
160		n.Focused = true
161		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
162		return &n, tablePackageName != nil && *tablePackageName == packageName
163	case "PIt", "PMeasure", "PSpecify", "XIt", "XMeasure", "XSpecify":
164		n.Spec = true
165		n.Pending = true
166		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
167		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
168	case "PEntry", "XEntry":
169		n.Spec = true
170		n.Pending = true
171		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
172		return &n, tablePackageName != nil && *tablePackageName == packageName
173	case "Context", "Describe", "When":
174		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
175		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
176	case "DescribeTable":
177		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
178		return &n, tablePackageName != nil && *tablePackageName == packageName
179	case "FContext", "FDescribe", "FWhen":
180		n.Focused = true
181		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
182		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
183	case "FDescribeTable":
184		n.Focused = true
185		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
186		return &n, tablePackageName != nil && *tablePackageName == packageName
187	case "PContext", "PDescribe", "PWhen", "XContext", "XDescribe", "XWhen":
188		n.Pending = true
189		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
190		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
191	case "PDescribeTable", "XDescribeTable":
192		n.Pending = true
193		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
194		return &n, tablePackageName != nil && *tablePackageName == packageName
195	case "By":
196		n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt)
197		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
198	case "AfterEach", "BeforeEach":
199		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
200	case "JustAfterEach", "JustBeforeEach":
201		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
202	case "AfterSuite", "BeforeSuite":
203		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
204	case "SynchronizedAfterSuite", "SynchronizedBeforeSuite":
205		return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName
206	default:
207		return nil, false
208	}
209}
210
211// textOrAltFromCallExpr tries to derive the "text" of a Ginkgo spec or
212// container. If it cannot derive it, it returns the alt text.
213func textOrAltFromCallExpr(ce *ast.CallExpr, alt string) string {
214	text, defined := textFromCallExpr(ce)
215	if !defined {
216		return alt
217	}
218	return text
219}
220
221// textFromCallExpr tries to derive the "text" of a Ginkgo spec or container. If
222// it cannot derive it, it returns false.
223func textFromCallExpr(ce *ast.CallExpr) (string, bool) {
224	if len(ce.Args) < 1 {
225		return "", false
226	}
227	text, ok := ce.Args[0].(*ast.BasicLit)
228	if !ok {
229		return "", false
230	}
231	switch text.Kind {
232	case token.CHAR, token.STRING:
233		// For token.CHAR and token.STRING, Value is quoted
234		unquoted, err := strconv.Unquote(text.Value)
235		if err != nil {
236			// If unquoting fails, just use the raw Value
237			return text.Value, true
238		}
239		return unquoted, true
240	default:
241		return text.Value, true
242	}
243}
244
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Trigger packageAndIdentNamesFromCallExpr code on LambdaTest Cloud Grid

Execute automation tests with packageAndIdentNamesFromCallExpr on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)