1
1
package dev .openfeature .sdk .e2e .steps ;
2
2
3
3
import static dev .openfeature .sdk .testutils .TestFlagsUtils .buildFlags ;
4
+ import static org .assertj .core .api .Assertions .assertThat ;
5
+ import static org .mockito .ArgumentMatchers .any ;
6
+ import static org .mockito .ArgumentMatchers .anyString ;
7
+ import static org .mockito .Mockito .doAnswer ;
8
+ import static org .mockito .Mockito .doThrow ;
9
+ import static org .mockito .Mockito .spy ;
10
+ import static org .mockito .Mockito .when ;
4
11
12
+ import dev .openfeature .sdk .ErrorCode ;
13
+ import dev .openfeature .sdk .EventProvider ;
14
+ import dev .openfeature .sdk .FeatureProvider ;
5
15
import dev .openfeature .sdk .OpenFeatureAPI ;
16
+ import dev .openfeature .sdk .ProviderEvaluation ;
17
+ import dev .openfeature .sdk .ProviderEventDetails ;
18
+ import dev .openfeature .sdk .ProviderState ;
19
+ import dev .openfeature .sdk .Reason ;
20
+ import dev .openfeature .sdk .Value ;
6
21
import dev .openfeature .sdk .e2e .State ;
22
+ import dev .openfeature .sdk .exceptions .FatalError ;
7
23
import dev .openfeature .sdk .providers .memory .Flag ;
8
24
import dev .openfeature .sdk .providers .memory .InMemoryProvider ;
9
25
import io .cucumber .java .en .Given ;
26
+ import io .cucumber .java .en .Then ;
10
27
import java .util .Map ;
28
+ import org .awaitility .Awaitility ;
11
29
12
30
public class ProviderSteps {
13
31
private final State state ;
@@ -16,11 +34,127 @@ public ProviderSteps(State state) {
16
34
this .state = state ;
17
35
}
18
36
19
- @ Given ("a stable provider" )
20
- public void aStableProvider () {
37
+ @ Given ("a {} provider" )
38
+ public void a_provider_with_status (String providerType ) throws Exception {
39
+ // Normalize input to handle both single word and quoted strings
40
+ String normalizedType =
41
+ providerType .toLowerCase ().replaceAll ("[\" \\ s]+" , " " ).trim ();
42
+
43
+ switch (normalizedType ) {
44
+ case "not ready" :
45
+ setupMockProvider (ErrorCode .PROVIDER_NOT_READY , "Provider in not ready state" , ProviderState .NOT_READY );
46
+ break ;
47
+ case "stable" :
48
+ case "ready" :
49
+ setupStableProvider ();
50
+ break ;
51
+ case "fatal" :
52
+ setupMockProvider (ErrorCode .PROVIDER_FATAL , "Provider in fatal state" , ProviderState .FATAL );
53
+ break ;
54
+ case "error" :
55
+ setupMockProvider (ErrorCode .GENERAL , "Provider in error state" , ProviderState .ERROR );
56
+ break ;
57
+ case "stale" :
58
+ setupMockProvider (null , null , ProviderState .STALE );
59
+ break ;
60
+ default :
61
+ throw new IllegalArgumentException ("Unsupported provider type: " + providerType );
62
+ }
63
+ }
64
+
65
+ // ===============================
66
+ // Provider Status Assertion Steps
67
+ // ===============================
68
+
69
+ @ Then ("the provider status should be {string}" )
70
+ public void the_provider_status_should_be (String expectedStatus ) {
71
+ ProviderState actualStatus = state .client .getProviderState ();
72
+ ProviderState expected = ProviderState .valueOf (expectedStatus );
73
+ assertThat (actualStatus ).isEqualTo (expected );
74
+ }
75
+
76
+ // ===============================
77
+ // Helper Methods
78
+ // ===============================
79
+
80
+ private void setupStableProvider () throws Exception {
21
81
Map <String , Flag <?>> flags = buildFlags ();
22
82
InMemoryProvider provider = new InMemoryProvider (flags );
23
83
OpenFeatureAPI .getInstance ().setProviderAndWait (provider );
24
84
state .client = OpenFeatureAPI .getInstance ().getClient ();
25
85
}
86
+
87
+ private void setupMockProvider (ErrorCode errorCode , String errorMessage , ProviderState providerState )
88
+ throws Exception {
89
+ EventProvider mockProvider = spy (EventProvider .class );
90
+
91
+ switch (providerState ) {
92
+ case NOT_READY :
93
+ doAnswer (invocationOnMock -> {
94
+ while (true ) {}
95
+ })
96
+ .when (mockProvider )
97
+ .initialize (any ());
98
+ break ;
99
+ case FATAL :
100
+ doThrow (new FatalError (errorMessage )).when (mockProvider ).initialize (any ());
101
+ break ;
102
+ }
103
+ // Configure all evaluation methods with a single helper
104
+ configureMockEvaluations (mockProvider , errorCode , errorMessage );
105
+
106
+ OpenFeatureAPI .getInstance ().setProvider (providerState .name (), mockProvider );
107
+ state .client = OpenFeatureAPI .getInstance ().getClient (providerState .name ());
108
+
109
+ ProviderEventDetails details =
110
+ ProviderEventDetails .builder ().errorCode (errorCode ).build ();
111
+ switch (providerState ) {
112
+ case FATAL :
113
+ case ERROR :
114
+ mockProvider .emitProviderReady (details );
115
+ mockProvider .emitProviderError (details );
116
+ break ;
117
+ case STALE :
118
+ mockProvider .emitProviderReady (details );
119
+ mockProvider .emitProviderStale (details );
120
+ break ;
121
+ default :
122
+ }
123
+ Awaitility .await ().until (() -> {
124
+ ProviderState providerState1 = state .client .getProviderState ();
125
+ return providerState1 == providerState ;
126
+ });
127
+ }
128
+
129
+ private void configureMockEvaluations (FeatureProvider mockProvider , ErrorCode errorCode , String errorMessage ) {
130
+ // Configure Boolean evaluation
131
+ when (mockProvider .getBooleanEvaluation (anyString (), any (Boolean .class ), any ()))
132
+ .thenAnswer (invocation -> createProviderEvaluation (invocation .getArgument (1 ), errorCode , errorMessage ));
133
+
134
+ // Configure String evaluation
135
+ when (mockProvider .getStringEvaluation (anyString (), any (String .class ), any ()))
136
+ .thenAnswer (invocation -> createProviderEvaluation (invocation .getArgument (1 ), errorCode , errorMessage ));
137
+
138
+ // Configure Integer evaluation
139
+ when (mockProvider .getIntegerEvaluation (anyString (), any (Integer .class ), any ()))
140
+ .thenAnswer (invocation -> createProviderEvaluation (invocation .getArgument (1 ), errorCode , errorMessage ));
141
+
142
+ // Configure Double evaluation
143
+ when (mockProvider .getDoubleEvaluation (anyString (), any (Double .class ), any ()))
144
+ .thenAnswer (invocation -> createProviderEvaluation (invocation .getArgument (1 ), errorCode , errorMessage ));
145
+
146
+ // Configure Object evaluation
147
+ when (mockProvider .getObjectEvaluation (anyString (), any (Value .class ), any ()))
148
+ .thenAnswer (invocation -> createProviderEvaluation (invocation .getArgument (1 ), errorCode , errorMessage ));
149
+ }
150
+
151
+ private <T > ProviderEvaluation <T > createProviderEvaluation (
152
+ T defaultValue , ErrorCode errorCode , String errorMessage ) {
153
+ return ProviderEvaluation .<T >builder ()
154
+ .value (defaultValue )
155
+ .errorCode (errorCode )
156
+ .errorMessage (errorMessage )
157
+ .reason (Reason .ERROR .toString ())
158
+ .build ();
159
+ }
26
160
}
0 commit comments