aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go
blob: 783e7964ada32c59e0a853af95ac51fc2fe04454 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package table

import (
	"fmt"
	"reflect"

	"github.com/onsi/ginkgo/internal/codelocation"
	"github.com/onsi/ginkgo/internal/global"
	"github.com/onsi/ginkgo/types"
)

/*
TableEntry represents an entry in a table test.  You generally use the `Entry` constructor.
*/
type TableEntry struct {
	Description  interface{}
	Parameters   []interface{}
	Pending      bool
	Focused      bool
	codeLocation types.CodeLocation
}

func (t TableEntry) generateIt(itBody reflect.Value) {
	if t.codeLocation == (types.CodeLocation{}) {
		// The user created the TableEntry struct directly instead of having used the (F/P/X)Entry constructors.
		// Therefore default to the code location of the surrounding DescribeTable.
		t.codeLocation = codelocation.New(5)
	}

	var description string
	descriptionValue := reflect.ValueOf(t.Description)
	switch descriptionValue.Kind() {
	case reflect.String:
		description = descriptionValue.String()
	case reflect.Func:
		values := castParameters(descriptionValue, t.Parameters)
		res := descriptionValue.Call(values)
		if len(res) != 1 {
			panic(fmt.Sprintf("The describe function should return only a value, returned %d", len(res)))
		}
		if res[0].Kind() != reflect.String {
			panic(fmt.Sprintf("The describe function should return a string, returned %#v", res[0]))
		}
		description = res[0].String()
	default:
		panic(fmt.Sprintf("Description can either be a string or a function, got %#v", descriptionValue))
	}

	if t.Pending {
		global.Suite.PushItNode(description, func() {}, types.FlagTypePending, t.codeLocation, 0)
		return
	}

	values := castParameters(itBody, t.Parameters)
	body := func() {
		itBody.Call(values)
	}

	if t.Focused {
		global.Suite.PushItNode(description, body, types.FlagTypeFocused, t.codeLocation, global.DefaultTimeout)
	} else {
		global.Suite.PushItNode(description, body, types.FlagTypeNone, t.codeLocation, global.DefaultTimeout)
	}
}

func castParameters(function reflect.Value, parameters []interface{}) []reflect.Value {
	res := make([]reflect.Value, len(parameters))
	funcType := function.Type()
	for i, param := range parameters {
		if param == nil {
			inType := funcType.In(i)
			res[i] = reflect.Zero(inType)
		} else {
			res[i] = reflect.ValueOf(param)
		}
	}
	return res
}

/*
Entry constructs a TableEntry.

The first argument is a required description (this becomes the content of the generated Ginkgo `It`).
Subsequent parameters are saved off and sent to the callback passed in to `DescribeTable`.

Each Entry ends up generating an individual Ginkgo It.
*/
func Entry(description interface{}, parameters ...interface{}) TableEntry {
	return TableEntry{
		Description:  description,
		Parameters:   parameters,
		Pending:      false,
		Focused:      false,
		codeLocation: codelocation.New(1),
	}
}

/*
You can focus a particular entry with FEntry.  This is equivalent to FIt.
*/
func FEntry(description interface{}, parameters ...interface{}) TableEntry {
	return TableEntry{
		Description:  description,
		Parameters:   parameters,
		Pending:      false,
		Focused:      true,
		codeLocation: codelocation.New(1),
	}
}

/*
You can mark a particular entry as pending with PEntry.  This is equivalent to PIt.
*/
func PEntry(description interface{}, parameters ...interface{}) TableEntry {
	return TableEntry{
		Description:  description,
		Parameters:   parameters,
		Pending:      true,
		Focused:      false,
		codeLocation: codelocation.New(1),
	}
}

/*
You can mark a particular entry as pending with XEntry.  This is equivalent to XIt.
*/
func XEntry(description interface{}, parameters ...interface{}) TableEntry {
	return TableEntry{
		Description:  description,
		Parameters:   parameters,
		Pending:      true,
		Focused:      false,
		codeLocation: codelocation.New(1),
	}
}