-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathProviderSteps.java
More file actions
157 lines (137 loc) · 6.46 KB
/
ProviderSteps.java
File metadata and controls
157 lines (137 loc) · 6.46 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package dev.openfeature.sdk.e2e.steps;
import static dev.openfeature.sdk.testutils.TestFlagsUtils.buildFlags;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import dev.openfeature.sdk.Client;
import dev.openfeature.sdk.ErrorCode;
import dev.openfeature.sdk.EventProvider;
import dev.openfeature.sdk.FeatureProvider;
import dev.openfeature.sdk.OpenFeatureAPI;
import dev.openfeature.sdk.ProviderEvaluation;
import dev.openfeature.sdk.ProviderEventDetails;
import dev.openfeature.sdk.ProviderState;
import dev.openfeature.sdk.Reason;
import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.e2e.State;
import dev.openfeature.sdk.exceptions.FatalError;
import dev.openfeature.sdk.providers.memory.Flag;
import dev.openfeature.sdk.providers.memory.InMemoryProvider;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import java.util.Map;
public class ProviderSteps {
private final State state;
public ProviderSteps(State state) {
this.state = state;
}
@Given("a {} provider")
public void a_provider_with_status(String providerType) throws Exception {
// Normalize input to handle both single word and quoted strings
String normalizedType =
providerType.toLowerCase().replaceAll("[\"\\s]+", " ").trim();
switch (normalizedType) {
case "not ready":
setupMockProvider(ErrorCode.PROVIDER_NOT_READY, "Provider in not ready state", ProviderState.NOT_READY);
break;
case "stable":
case "ready":
setupStableProvider();
break;
case "fatal":
setupMockProvider(ErrorCode.PROVIDER_FATAL, "Provider in fatal state", ProviderState.FATAL);
break;
case "error":
setupMockProvider(ErrorCode.GENERAL, "Provider in error state", ProviderState.ERROR);
break;
case "stale":
setupMockProvider(null, null, ProviderState.STALE);
break;
default:
throw new IllegalArgumentException("Unsupported provider type: " + providerType);
}
}
// ===============================
// Provider Status Assertion Steps
// ===============================
@Then("the provider status should be {string}")
public void the_provider_status_should_be(String expectedStatus) {
ProviderState actualStatus = state.client.getProviderState();
ProviderState expected = ProviderState.valueOf(expectedStatus);
assertThat(actualStatus).isEqualTo(expected);
}
// ===============================
// Helper Methods
// ===============================
private void setupStableProvider() throws Exception {
Map<String, Flag<?>> flags = buildFlags();
InMemoryProvider provider = new InMemoryProvider(flags);
OpenFeatureAPI.getInstance().setProviderAndWait(provider);
state.client = OpenFeatureAPI.getInstance().getClient();
}
private void setupMockProvider(ErrorCode errorCode, String errorMessage, ProviderState providerState)
throws Exception {
EventProvider mockProvider = spy(EventProvider.class);
switch (providerState) {
case NOT_READY:
doAnswer(invocationOnMock -> {
while (true) {}
})
.when(mockProvider)
.initialize(any());
break;
case FATAL:
doThrow(new FatalError(errorMessage)).when(mockProvider).initialize(any());
break;
}
// Configure all evaluation methods with a single helper
configureMockEvaluations(mockProvider, errorCode, errorMessage);
OpenFeatureAPI.getInstance().setProvider(providerState.name(), mockProvider);
Client client = OpenFeatureAPI.getInstance().getClient(providerState.name());
state.client = client;
ProviderEventDetails details =
ProviderEventDetails.builder().errorCode(errorCode).build();
switch (providerState) {
case FATAL:
case ERROR:
// mockProvider.emitProviderReady(details).await();
mockProvider.emitProviderError(details).await();
break;
case STALE:
// mockProvider.emitProviderReady(details).await();
mockProvider.emitProviderStale(details).await();
break;
default:
}
}
private void configureMockEvaluations(FeatureProvider mockProvider, ErrorCode errorCode, String errorMessage) {
// Configure Boolean evaluation
when(mockProvider.getBooleanEvaluation(anyString(), any(Boolean.class), any()))
.thenAnswer(invocation -> createProviderEvaluation(invocation.getArgument(1), errorCode, errorMessage));
// Configure String evaluation
when(mockProvider.getStringEvaluation(anyString(), any(String.class), any()))
.thenAnswer(invocation -> createProviderEvaluation(invocation.getArgument(1), errorCode, errorMessage));
// Configure Integer evaluation
when(mockProvider.getIntegerEvaluation(anyString(), any(Integer.class), any()))
.thenAnswer(invocation -> createProviderEvaluation(invocation.getArgument(1), errorCode, errorMessage));
// Configure Double evaluation
when(mockProvider.getDoubleEvaluation(anyString(), any(Double.class), any()))
.thenAnswer(invocation -> createProviderEvaluation(invocation.getArgument(1), errorCode, errorMessage));
// Configure Object evaluation
when(mockProvider.getObjectEvaluation(anyString(), any(Value.class), any()))
.thenAnswer(invocation -> createProviderEvaluation(invocation.getArgument(1), errorCode, errorMessage));
}
private <T> ProviderEvaluation<T> createProviderEvaluation(
T defaultValue, ErrorCode errorCode, String errorMessage) {
return ProviderEvaluation.<T>builder()
.value(defaultValue)
.errorCode(errorCode)
.errorMessage(errorMessage)
.reason(Reason.ERROR.toString())
.build();
}
}