7 "github.com/onsi/gomega/internal/oraclematcher"
8 "github.com/onsi/gomega/types"
11 type WithTransformMatcher struct {
13 Transform interface{} // must be a function of one parameter that returns one value
14 Matcher types.GomegaMatcher
17 transformArgType reflect.Type
20 transformedValue interface{}
23 func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) *WithTransformMatcher {
25 panic("transform function cannot be nil")
27 txType := reflect.TypeOf(transform)
28 if txType.NumIn() != 1 {
29 panic("transform function must have 1 argument")
31 if txType.NumOut() != 1 {
32 panic("transform function must have 1 return value")
35 return &WithTransformMatcher{
38 transformArgType: reflect.TypeOf(transform).In(0),
42 func (m *WithTransformMatcher) Match(actual interface{}) (bool, error) {
43 // return error if actual's type is incompatible with Transform function's argument type
44 actualType := reflect.TypeOf(actual)
45 if !actualType.AssignableTo(m.transformArgType) {
46 return false, fmt.Errorf("Transform function expects '%s' but we have '%s'", m.transformArgType, actualType)
49 // call the Transform function with `actual`
50 fn := reflect.ValueOf(m.Transform)
51 result := fn.Call([]reflect.Value{reflect.ValueOf(actual)})
52 m.transformedValue = result[0].Interface() // expect exactly one value
54 return m.Matcher.Match(m.transformedValue)
57 func (m *WithTransformMatcher) FailureMessage(_ interface{}) (message string) {
58 return m.Matcher.FailureMessage(m.transformedValue)
61 func (m *WithTransformMatcher) NegatedFailureMessage(_ interface{}) (message string) {
62 return m.Matcher.NegatedFailureMessage(m.transformedValue)
65 func (m *WithTransformMatcher) MatchMayChangeInTheFuture(_ interface{}) bool {
66 // TODO: Maybe this should always just return true? (Only an issue for non-deterministic transformers.)
68 // Querying the next matcher is fine if the transformer always will return the same value.
69 // But if the transformer is non-deterministic and returns a different value each time, then there
70 // is no point in querying the next matcher, since it can only comment on the last transformed value.
71 return oraclematcher.MatchMayChangeInTheFuture(m.Matcher, m.transformedValue)