1 package ldevents
2
3 import (
4 "encoding/json"
5
6 "github.com/launchdarkly/go-sdk-common/v3/ldcontext"
7 "github.com/launchdarkly/go-sdk-common/v3/ldreason"
8 "github.com/launchdarkly/go-sdk-common/v3/ldtime"
9 "github.com/launchdarkly/go-sdk-common/v3/ldvalue"
10
11 "github.com/launchdarkly/go-test-helpers/v3/jsonhelpers"
12 m "github.com/launchdarkly/go-test-helpers/v3/matchers"
13 )
14
15 func equalNumericTime(unixTime ldtime.UnixMillisecondTime) m.Matcher {
16
17 return m.JSONEqual(unixTime)
18 }
19
20 func eventKindIs(kind string) m.Matcher {
21 return m.JSONProperty("kind").Should(m.Equal(kind))
22 }
23
24 func anyIndexEvent() m.Matcher {
25 return eventKindIs("index")
26 }
27
28 func anyIdentifyEvent() m.Matcher {
29 return eventKindIs("identify")
30 }
31
32 func anyFeatureEvent() m.Matcher {
33 return eventKindIs("feature")
34 }
35
36 func anyCustomEvent() m.Matcher {
37 return eventKindIs("custom")
38 }
39
40 func anySummaryEvent() m.Matcher {
41 return eventKindIs("summary")
42 }
43
44 func identifyEventForContextKey(key string) m.Matcher {
45 return m.AllOf(
46 eventKindIs("identify"),
47 m.JSONProperty("context").Should(m.JSONProperty("key").Should(m.Equal(key))),
48 )
49 }
50
51 func indexEventForContextKey(key string) m.Matcher {
52 return m.AllOf(
53 eventKindIs("index"),
54 m.JSONProperty("context").Should(m.JSONProperty("key").Should(m.Equal(key))),
55 )
56 }
57
58 func featureEventForFlag(flag FlagEventProperties) m.Matcher {
59 return m.AllOf(
60 m.JSONProperty("kind").Should(m.Equal("feature")),
61 m.JSONProperty("key").Should(m.Equal(flag.Key)))
62 }
63
64 func featureEventWithAllProperties(sourceEvent EvaluationData, flag FlagEventProperties) m.Matcher {
65 return matchFeatureOrDebugEvent(sourceEvent, flag, false, nil)
66 }
67
68 func debugEventWithAllProperties(sourceEvent EvaluationData, flag FlagEventProperties, contextJSON interface{}) m.Matcher {
69 return matchFeatureOrDebugEvent(sourceEvent, flag, true, contextJSON)
70 }
71
72 func matchFeatureOrDebugEvent(sourceEvent EvaluationData, flag FlagEventProperties,
73 debug bool, inlineContext interface{}) m.Matcher {
74 props := map[string]interface{}{
75 "kind": "feature",
76 "key": flag.Key,
77 "creationDate": sourceEvent.CreationDate,
78 "version": flag.Version,
79 "value": sourceEvent.Value,
80 "default": nil,
81 }
82 if debug {
83 props["kind"] = "debug"
84 }
85 if sourceEvent.Variation.IsDefined() {
86 props["variation"] = sourceEvent.Variation.IntValue()
87 }
88 if sourceEvent.Reason.GetKind() != "" {
89 props["reason"] = json.RawMessage(jsonhelpers.ToJSON(sourceEvent.Reason))
90 }
91 if inlineContext == nil {
92 props["contextKeys"] = expectedContextKeys(sourceEvent.Context.context)
93 } else {
94 props["context"] = inlineContext
95 }
96 return m.JSONEqual(props)
97 }
98
99 func customEventWithEventKey(eventKey string) m.Matcher {
100 return m.AllOf(
101 eventKindIs("custom"),
102 m.JSONProperty("key").Should(m.Equal(eventKey)),
103 )
104 }
105
106 func summaryEventWithFlag(flag FlagEventProperties, counterProps ...[]m.Matcher) m.Matcher {
107 counters := make([]m.Matcher, 0, len(counterProps))
108 for _, cp := range counterProps {
109 counters = append(counters, m.AllOf(
110 append(cp, m.JSONProperty("version").Should(m.Equal(flag.Version)))...,
111 ))
112 }
113 return m.AllOf(
114 m.JSONProperty("kind").Should(m.Equal("summary")),
115 m.JSONProperty("features").Should(
116 m.JSONProperty(flag.Key).Should(
117 m.JSONProperty("counters").Should(m.ItemsInAnyOrder(counters...)),
118 ),
119 ),
120 )
121 }
122
123 func summaryCounterProps(variation ldvalue.OptionalInt, value ldvalue.Value, count int) []m.Matcher {
124 return []m.Matcher{
125 m.JSONProperty("value").Should(m.JSONEqual(value)),
126 m.JSONProperty("count").Should(m.Equal(count)),
127 m.JSONOptProperty("variation").Should(m.JSONEqual(variation)),
128 }
129 }
130
131 func summaryCounterPropsFromEval(evalDetail ldreason.EvaluationDetail, count int) []m.Matcher {
132 return summaryCounterProps(evalDetail.VariationIndex, evalDetail.Value, count)
133 }
134
135 func valueIsPositiveNonZeroInteger() m.Matcher {
136 return m.New(
137 func(value interface{}) bool {
138 v := ldvalue.Parse(jsonhelpers.ToJSON(value))
139 return v.IsInt() && v.IntValue() > 0
140 },
141 func() string {
142 return "is an int > 0"
143 },
144 func(value interface{}) string {
145 return "was not an int or was negative"
146 },
147 )
148 }
149
150 func expectedContextKeys(c ldcontext.Context) map[string]string {
151 ret := make(map[string]string)
152 for i := 0; i < c.IndividualContextCount(); i++ {
153 if ic := c.IndividualContextByIndex(i); ic.IsDefined() {
154 ret[string(ic.Kind())] = ic.Key()
155 }
156 }
157 return ret
158 }
159
View as plain text