@terreno/feature-flags 0.20.2 → 0.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bunfig.toml +1 -1
- package/package.json +3 -2
- package/src/tests/bunSetup.ts +6 -33
- package/src/tests/featureFlagsApp.liveUpdates.test.ts +1 -1
- package/src/tests/featureFlagsApp.test.ts +1 -1
- package/src/tests/openFeatureProvider.test.ts +1 -1
- package/tsconfig.json +1 -1
- package/dist/tests/bunSetup.d.ts +0 -1
- package/dist/tests/bunSetup.js +0 -35
- package/dist/tests/evaluate.test.d.ts +0 -1
- package/dist/tests/evaluate.test.js +0 -594
- package/dist/tests/featureFlagModel.test.d.ts +0 -1
- package/dist/tests/featureFlagModel.test.js +0 -428
- package/dist/tests/featureFlagsApp.liveUpdates.test.d.ts +0 -1
- package/dist/tests/featureFlagsApp.liveUpdates.test.js +0 -203
- package/dist/tests/featureFlagsApp.test.d.ts +0 -1
- package/dist/tests/featureFlagsApp.test.js +0 -540
- package/dist/tests/openFeatureProvider.test.d.ts +0 -1
- package/dist/tests/openFeatureProvider.test.js +0 -395
|
@@ -1,540 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
-
};
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
var bun_test_1 = require("bun:test");
|
|
43
|
-
var server_sdk_1 = require("@openfeature/server-sdk");
|
|
44
|
-
var api_1 = require("@terreno/api");
|
|
45
|
-
var tests_1 = require("@terreno/api/src/tests");
|
|
46
|
-
var supertest_1 = __importDefault(require("supertest"));
|
|
47
|
-
var featureFlagModel_1 = require("../featureFlagModel");
|
|
48
|
-
var featureFlagsApp_1 = require("../featureFlagsApp");
|
|
49
|
-
var buildApp = function (options) {
|
|
50
|
-
var app = (0, tests_1.getBaseServer)();
|
|
51
|
-
(0, api_1.setupAuth)(app, tests_1.UserModel);
|
|
52
|
-
(0, api_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
53
|
-
var plugin = new featureFlagsApp_1.FeatureFlagsApp(options);
|
|
54
|
-
plugin.register(app);
|
|
55
|
-
app.use(api_1.apiUnauthorizedMiddleware);
|
|
56
|
-
app.use(api_1.apiErrorMiddleware);
|
|
57
|
-
return app;
|
|
58
|
-
};
|
|
59
|
-
(0, bun_test_1.describe)("FeatureFlagsApp", function () {
|
|
60
|
-
var app;
|
|
61
|
-
var adminAgent;
|
|
62
|
-
var notAdminAgent;
|
|
63
|
-
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
64
|
-
return __generator(this, function (_a) {
|
|
65
|
-
switch (_a.label) {
|
|
66
|
-
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
67
|
-
case 1:
|
|
68
|
-
_a.sent();
|
|
69
|
-
return [4 /*yield*/, featureFlagModel_1.FeatureFlag.deleteMany({})];
|
|
70
|
-
case 2:
|
|
71
|
-
_a.sent();
|
|
72
|
-
return [2 /*return*/];
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}); });
|
|
76
|
-
(0, bun_test_1.afterEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
77
|
-
return __generator(this, function (_a) {
|
|
78
|
-
switch (_a.label) {
|
|
79
|
-
case 0: return [4 /*yield*/, featureFlagModel_1.FeatureFlag.deleteMany({})];
|
|
80
|
-
case 1:
|
|
81
|
-
_a.sent();
|
|
82
|
-
return [4 /*yield*/, server_sdk_1.OpenFeature.clearProviders()];
|
|
83
|
-
case 2:
|
|
84
|
-
_a.sent();
|
|
85
|
-
return [2 /*return*/];
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}); });
|
|
89
|
-
(0, bun_test_1.describe)("construction", function () {
|
|
90
|
-
(0, bun_test_1.it)("defaults basePath to /feature-flags and segments to an empty object", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
91
|
-
var res;
|
|
92
|
-
return __generator(this, function (_a) {
|
|
93
|
-
switch (_a.label) {
|
|
94
|
-
case 0:
|
|
95
|
-
app = buildApp();
|
|
96
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
97
|
-
case 1:
|
|
98
|
-
adminAgent = _a.sent();
|
|
99
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/segments").expect(200)];
|
|
100
|
-
case 2:
|
|
101
|
-
res = _a.sent();
|
|
102
|
-
(0, bun_test_1.expect)(res.body.data).toEqual([]);
|
|
103
|
-
return [2 /*return*/];
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
}); });
|
|
107
|
-
(0, bun_test_1.it)("respects a custom basePath", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
108
|
-
return __generator(this, function (_a) {
|
|
109
|
-
switch (_a.label) {
|
|
110
|
-
case 0:
|
|
111
|
-
app = buildApp({ basePath: "/flags" });
|
|
112
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
113
|
-
case 1:
|
|
114
|
-
adminAgent = _a.sent();
|
|
115
|
-
return [4 /*yield*/, adminAgent.get("/flags/segments").expect(200)];
|
|
116
|
-
case 2:
|
|
117
|
-
_a.sent();
|
|
118
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/segments").expect(404)];
|
|
119
|
-
case 3:
|
|
120
|
-
_a.sent();
|
|
121
|
-
return [2 /*return*/];
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}); });
|
|
125
|
-
(0, bun_test_1.it)("accepts an empty options object", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
126
|
-
var res;
|
|
127
|
-
return __generator(this, function (_a) {
|
|
128
|
-
switch (_a.label) {
|
|
129
|
-
case 0:
|
|
130
|
-
app = buildApp({});
|
|
131
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
132
|
-
case 1:
|
|
133
|
-
adminAgent = _a.sent();
|
|
134
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/segments").expect(200)];
|
|
135
|
-
case 2:
|
|
136
|
-
res = _a.sent();
|
|
137
|
-
(0, bun_test_1.expect)(res.body.data).toEqual([]);
|
|
138
|
-
return [2 /*return*/];
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
}); });
|
|
142
|
-
});
|
|
143
|
-
(0, bun_test_1.describe)("admin CRUD routes", function () {
|
|
144
|
-
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
145
|
-
return __generator(this, function (_a) {
|
|
146
|
-
switch (_a.label) {
|
|
147
|
-
case 0:
|
|
148
|
-
app = buildApp();
|
|
149
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
150
|
-
case 1:
|
|
151
|
-
adminAgent = _a.sent();
|
|
152
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
153
|
-
case 2:
|
|
154
|
-
notAdminAgent = _a.sent();
|
|
155
|
-
return [2 /*return*/];
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
}); });
|
|
159
|
-
(0, bun_test_1.it)("lets admins create, list, read, update, and delete flags", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
160
|
-
var createRes, flagId, listRes, readRes, updateRes, finalList;
|
|
161
|
-
return __generator(this, function (_a) {
|
|
162
|
-
switch (_a.label) {
|
|
163
|
-
case 0: return [4 /*yield*/, adminAgent
|
|
164
|
-
.post("/feature-flags/flags")
|
|
165
|
-
.send({ enabled: true, key: "new-flag", name: "New Flag" })
|
|
166
|
-
.expect(201)];
|
|
167
|
-
case 1:
|
|
168
|
-
createRes = _a.sent();
|
|
169
|
-
flagId = createRes.body.data._id;
|
|
170
|
-
(0, bun_test_1.expect)(createRes.body.data.key).toBe("new-flag");
|
|
171
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/flags").expect(200)];
|
|
172
|
-
case 2:
|
|
173
|
-
listRes = _a.sent();
|
|
174
|
-
(0, bun_test_1.expect)(listRes.body.data.length).toBe(1);
|
|
175
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/flags/".concat(flagId)).expect(200)];
|
|
176
|
-
case 3:
|
|
177
|
-
readRes = _a.sent();
|
|
178
|
-
(0, bun_test_1.expect)(readRes.body.data.key).toBe("new-flag");
|
|
179
|
-
return [4 /*yield*/, adminAgent
|
|
180
|
-
.patch("/feature-flags/flags/".concat(flagId))
|
|
181
|
-
.send({ rolloutPercentage: 50 })
|
|
182
|
-
.expect(200)];
|
|
183
|
-
case 4:
|
|
184
|
-
updateRes = _a.sent();
|
|
185
|
-
(0, bun_test_1.expect)(updateRes.body.data.rolloutPercentage).toBe(50);
|
|
186
|
-
return [4 /*yield*/, adminAgent.delete("/feature-flags/flags/".concat(flagId)).expect(204)];
|
|
187
|
-
case 5:
|
|
188
|
-
_a.sent();
|
|
189
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/flags").expect(200)];
|
|
190
|
-
case 6:
|
|
191
|
-
finalList = _a.sent();
|
|
192
|
-
(0, bun_test_1.expect)(finalList.body.data.length).toBe(0);
|
|
193
|
-
return [2 /*return*/];
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
}); });
|
|
197
|
-
(0, bun_test_1.it)("rejects non-admins from the CRUD routes", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
198
|
-
return __generator(this, function (_a) {
|
|
199
|
-
switch (_a.label) {
|
|
200
|
-
case 0:
|
|
201
|
-
// modelRouter responds with 405 Method Not Allowed when permissions fail
|
|
202
|
-
return [4 /*yield*/, notAdminAgent.get("/feature-flags/flags").expect(405)];
|
|
203
|
-
case 1:
|
|
204
|
-
// modelRouter responds with 405 Method Not Allowed when permissions fail
|
|
205
|
-
_a.sent();
|
|
206
|
-
return [4 /*yield*/, notAdminAgent
|
|
207
|
-
.post("/feature-flags/flags")
|
|
208
|
-
.send({ key: "nope", name: "Nope" })
|
|
209
|
-
.expect(405)];
|
|
210
|
-
case 2:
|
|
211
|
-
_a.sent();
|
|
212
|
-
return [2 /*return*/];
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
}); });
|
|
216
|
-
(0, bun_test_1.it)("rejects unauthenticated requests to CRUD routes", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
217
|
-
var unauth;
|
|
218
|
-
return __generator(this, function (_a) {
|
|
219
|
-
switch (_a.label) {
|
|
220
|
-
case 0:
|
|
221
|
-
unauth = (0, supertest_1.default)(app);
|
|
222
|
-
return [4 /*yield*/, unauth.get("/feature-flags/flags").expect(401)];
|
|
223
|
-
case 1:
|
|
224
|
-
_a.sent();
|
|
225
|
-
return [2 /*return*/];
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
}); });
|
|
229
|
-
});
|
|
230
|
-
(0, bun_test_1.describe)("GET /feature-flags/evaluate", function () {
|
|
231
|
-
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
232
|
-
var segments;
|
|
233
|
-
return __generator(this, function (_a) {
|
|
234
|
-
segments = {
|
|
235
|
-
admins: function (user) { return user.admin === true; },
|
|
236
|
-
};
|
|
237
|
-
app = buildApp({ segments: segments });
|
|
238
|
-
return [2 /*return*/];
|
|
239
|
-
});
|
|
240
|
-
}); });
|
|
241
|
-
(0, bun_test_1.it)("returns 401 for unauthenticated callers", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
242
|
-
var unauth;
|
|
243
|
-
return __generator(this, function (_a) {
|
|
244
|
-
switch (_a.label) {
|
|
245
|
-
case 0:
|
|
246
|
-
unauth = (0, supertest_1.default)(app);
|
|
247
|
-
return [4 /*yield*/, unauth.get("/feature-flags/evaluate").expect(401)];
|
|
248
|
-
case 1:
|
|
249
|
-
_a.sent();
|
|
250
|
-
return [2 /*return*/];
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
}); });
|
|
254
|
-
(0, bun_test_1.it)("returns all enabled, non-archived flag values for the current user", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
255
|
-
var res;
|
|
256
|
-
return __generator(this, function (_a) {
|
|
257
|
-
switch (_a.label) {
|
|
258
|
-
case 0: return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
259
|
-
enabled: true,
|
|
260
|
-
key: "rolled-out",
|
|
261
|
-
name: "Rolled out",
|
|
262
|
-
rolloutPercentage: 100,
|
|
263
|
-
})];
|
|
264
|
-
case 1:
|
|
265
|
-
_a.sent();
|
|
266
|
-
return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
267
|
-
enabled: false,
|
|
268
|
-
key: "disabled-flag",
|
|
269
|
-
name: "Disabled",
|
|
270
|
-
rolloutPercentage: 100,
|
|
271
|
-
})];
|
|
272
|
-
case 2:
|
|
273
|
-
_a.sent();
|
|
274
|
-
return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
275
|
-
archived: true,
|
|
276
|
-
enabled: true,
|
|
277
|
-
key: "archived-flag",
|
|
278
|
-
name: "Archived",
|
|
279
|
-
rolloutPercentage: 100,
|
|
280
|
-
})];
|
|
281
|
-
case 3:
|
|
282
|
-
_a.sent();
|
|
283
|
-
return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
284
|
-
enabled: true,
|
|
285
|
-
key: "admins-only",
|
|
286
|
-
name: "Admins",
|
|
287
|
-
rolloutPercentage: 0,
|
|
288
|
-
rules: [{ enabled: true, segment: "admins" }],
|
|
289
|
-
})];
|
|
290
|
-
case 4:
|
|
291
|
-
_a.sent();
|
|
292
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
293
|
-
case 5:
|
|
294
|
-
adminAgent = _a.sent();
|
|
295
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/evaluate").expect(200)];
|
|
296
|
-
case 6:
|
|
297
|
-
res = _a.sent();
|
|
298
|
-
(0, bun_test_1.expect)(res.body.data["rolled-out"]).toBe(true);
|
|
299
|
-
(0, bun_test_1.expect)(res.body.data["admins-only"]).toBe(true);
|
|
300
|
-
(0, bun_test_1.expect)(res.body.data["disabled-flag"]).toBeUndefined();
|
|
301
|
-
(0, bun_test_1.expect)(res.body.data["archived-flag"]).toBeUndefined();
|
|
302
|
-
return [2 /*return*/];
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
}); });
|
|
306
|
-
(0, bun_test_1.it)("includes an admin's own evaluated flags", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
307
|
-
var res, notAdminRes;
|
|
308
|
-
return __generator(this, function (_a) {
|
|
309
|
-
switch (_a.label) {
|
|
310
|
-
case 0: return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
311
|
-
enabled: true,
|
|
312
|
-
key: "user-only",
|
|
313
|
-
name: "User only",
|
|
314
|
-
rolloutPercentage: 0,
|
|
315
|
-
rules: [{ enabled: true, field: "admin", operator: "eq", value: true }],
|
|
316
|
-
})];
|
|
317
|
-
case 1:
|
|
318
|
-
_a.sent();
|
|
319
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
320
|
-
case 2:
|
|
321
|
-
adminAgent = _a.sent();
|
|
322
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/evaluate").expect(200)];
|
|
323
|
-
case 3:
|
|
324
|
-
res = _a.sent();
|
|
325
|
-
(0, bun_test_1.expect)(res.body.data["user-only"]).toBe(true);
|
|
326
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
327
|
-
case 4:
|
|
328
|
-
notAdminAgent = _a.sent();
|
|
329
|
-
return [4 /*yield*/, notAdminAgent.get("/feature-flags/evaluate").expect(200)];
|
|
330
|
-
case 5:
|
|
331
|
-
notAdminRes = _a.sent();
|
|
332
|
-
// notAdmin isn't admin, rolloutPercentage is 0 → should evaluate false
|
|
333
|
-
(0, bun_test_1.expect)(notAdminRes.body.data["user-only"]).toBe(false);
|
|
334
|
-
return [2 /*return*/];
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
}); });
|
|
338
|
-
(0, bun_test_1.it)("includes Deprecation and Sunset headers on GET /evaluate", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
339
|
-
var res;
|
|
340
|
-
return __generator(this, function (_a) {
|
|
341
|
-
switch (_a.label) {
|
|
342
|
-
case 0: return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
343
|
-
enabled: true,
|
|
344
|
-
key: "hdr-flag",
|
|
345
|
-
name: "Hdr",
|
|
346
|
-
rolloutPercentage: 100,
|
|
347
|
-
})];
|
|
348
|
-
case 1:
|
|
349
|
-
_a.sent();
|
|
350
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
351
|
-
case 2:
|
|
352
|
-
adminAgent = _a.sent();
|
|
353
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/evaluate").expect(200)];
|
|
354
|
-
case 3:
|
|
355
|
-
res = _a.sent();
|
|
356
|
-
(0, bun_test_1.expect)(res.headers.deprecation).toBe("true");
|
|
357
|
-
(0, bun_test_1.expect)(res.headers.sunset).toBeDefined();
|
|
358
|
-
(0, bun_test_1.expect)(res.body.data["hdr-flag"]).toBe(true);
|
|
359
|
-
return [2 /*return*/];
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
}); });
|
|
363
|
-
});
|
|
364
|
-
(0, bun_test_1.describe)("GET /feature-flags/flagConfiguration", function () {
|
|
365
|
-
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
366
|
-
var segments;
|
|
367
|
-
return __generator(this, function (_a) {
|
|
368
|
-
segments = {
|
|
369
|
-
admins: function (user) { return user.admin === true; },
|
|
370
|
-
};
|
|
371
|
-
app = buildApp({ segments: segments });
|
|
372
|
-
return [2 /*return*/];
|
|
373
|
-
});
|
|
374
|
-
}); });
|
|
375
|
-
(0, bun_test_1.it)("returns 401 when unauthenticated", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
376
|
-
var unauth;
|
|
377
|
-
return __generator(this, function (_a) {
|
|
378
|
-
switch (_a.label) {
|
|
379
|
-
case 0:
|
|
380
|
-
unauth = (0, supertest_1.default)(app);
|
|
381
|
-
return [4 /*yield*/, unauth.get("/feature-flags/flagConfiguration").expect(401)];
|
|
382
|
-
case 1:
|
|
383
|
-
_a.sent();
|
|
384
|
-
return [2 /*return*/];
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
}); });
|
|
388
|
-
(0, bun_test_1.it)("returns OpenFeature-shaped entries for enabled flags and omits disabled and archived", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
389
|
-
var res, data;
|
|
390
|
-
var _a, _b, _c, _d;
|
|
391
|
-
return __generator(this, function (_e) {
|
|
392
|
-
switch (_e.label) {
|
|
393
|
-
case 0: return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
394
|
-
enabled: true,
|
|
395
|
-
key: "bool-active",
|
|
396
|
-
name: "Bool",
|
|
397
|
-
rolloutPercentage: 100,
|
|
398
|
-
type: "boolean",
|
|
399
|
-
})];
|
|
400
|
-
case 1:
|
|
401
|
-
_e.sent();
|
|
402
|
-
return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
403
|
-
defaultVariant: "compact",
|
|
404
|
-
enabled: true,
|
|
405
|
-
key: "profile",
|
|
406
|
-
name: "Profile",
|
|
407
|
-
rules: [],
|
|
408
|
-
type: "variant",
|
|
409
|
-
variants: [
|
|
410
|
-
{ key: "compact", weight: 50 },
|
|
411
|
-
{ key: "detailed", weight: 50 },
|
|
412
|
-
],
|
|
413
|
-
})];
|
|
414
|
-
case 2:
|
|
415
|
-
_e.sent();
|
|
416
|
-
return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
417
|
-
enabled: false,
|
|
418
|
-
key: "disabled-one",
|
|
419
|
-
name: "Off",
|
|
420
|
-
rolloutPercentage: 100,
|
|
421
|
-
type: "boolean",
|
|
422
|
-
})];
|
|
423
|
-
case 3:
|
|
424
|
-
_e.sent();
|
|
425
|
-
return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
426
|
-
archived: true,
|
|
427
|
-
enabled: true,
|
|
428
|
-
key: "archived-one",
|
|
429
|
-
name: "Archived",
|
|
430
|
-
rolloutPercentage: 100,
|
|
431
|
-
type: "boolean",
|
|
432
|
-
})];
|
|
433
|
-
case 4:
|
|
434
|
-
_e.sent();
|
|
435
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
436
|
-
case 5:
|
|
437
|
-
adminAgent = _e.sent();
|
|
438
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/flagConfiguration").expect(200)];
|
|
439
|
-
case 6:
|
|
440
|
-
res = _e.sent();
|
|
441
|
-
data = res.body.data;
|
|
442
|
-
(0, bun_test_1.expect)(data["bool-active"]).toEqual({
|
|
443
|
-
defaultVariant: "on",
|
|
444
|
-
disabled: false,
|
|
445
|
-
variants: { off: false, on: true },
|
|
446
|
-
});
|
|
447
|
-
(0, bun_test_1.expect)((_a = data.profile) === null || _a === void 0 ? void 0 : _a.disabled).toBe(false);
|
|
448
|
-
(0, bun_test_1.expect)(["compact", "detailed"].includes((_c = (_b = data.profile) === null || _b === void 0 ? void 0 : _b.defaultVariant) !== null && _c !== void 0 ? _c : "")).toBe(true);
|
|
449
|
-
(0, bun_test_1.expect)((_d = data.profile) === null || _d === void 0 ? void 0 : _d.variants.compact).toBe("compact");
|
|
450
|
-
(0, bun_test_1.expect)(data["disabled-one"]).toBeUndefined();
|
|
451
|
-
(0, bun_test_1.expect)(data["archived-one"]).toBeUndefined();
|
|
452
|
-
return [2 /*return*/];
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
}); });
|
|
456
|
-
(0, bun_test_1.it)("uses resolved boolean variant as defaultVariant (not the persisted schema default alone)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
457
|
-
var res;
|
|
458
|
-
return __generator(this, function (_a) {
|
|
459
|
-
switch (_a.label) {
|
|
460
|
-
case 0: return [4 /*yield*/, featureFlagModel_1.FeatureFlag.create({
|
|
461
|
-
defaultVariant: "off",
|
|
462
|
-
enabled: true,
|
|
463
|
-
key: "resolved-bool",
|
|
464
|
-
name: "Resolved",
|
|
465
|
-
rolloutPercentage: 100,
|
|
466
|
-
rules: [],
|
|
467
|
-
type: "boolean",
|
|
468
|
-
})];
|
|
469
|
-
case 1:
|
|
470
|
-
_a.sent();
|
|
471
|
-
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
472
|
-
case 2:
|
|
473
|
-
adminAgent = _a.sent();
|
|
474
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/flagConfiguration").expect(200)];
|
|
475
|
-
case 3:
|
|
476
|
-
res = _a.sent();
|
|
477
|
-
(0, bun_test_1.expect)(res.body.data["resolved-bool"].defaultVariant).toBe("on");
|
|
478
|
-
(0, bun_test_1.expect)(res.body.data["resolved-bool"].variants.on).toBe(true);
|
|
479
|
-
return [2 /*return*/];
|
|
480
|
-
}
|
|
481
|
-
});
|
|
482
|
-
}); });
|
|
483
|
-
});
|
|
484
|
-
(0, bun_test_1.describe)("GET /feature-flags/segments", function () {
|
|
485
|
-
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
486
|
-
return __generator(this, function (_a) {
|
|
487
|
-
app = buildApp({
|
|
488
|
-
segments: {
|
|
489
|
-
admins: function () { return true; },
|
|
490
|
-
"beta-testers": function () { return false; },
|
|
491
|
-
},
|
|
492
|
-
});
|
|
493
|
-
return [2 /*return*/];
|
|
494
|
-
});
|
|
495
|
-
}); });
|
|
496
|
-
(0, bun_test_1.it)("returns the registered segment keys for admins", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
497
|
-
var res;
|
|
498
|
-
return __generator(this, function (_a) {
|
|
499
|
-
switch (_a.label) {
|
|
500
|
-
case 0: return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
501
|
-
case 1:
|
|
502
|
-
adminAgent = _a.sent();
|
|
503
|
-
return [4 /*yield*/, adminAgent.get("/feature-flags/segments").expect(200)];
|
|
504
|
-
case 2:
|
|
505
|
-
res = _a.sent();
|
|
506
|
-
(0, bun_test_1.expect)(res.body.data.sort()).toEqual(["admins", "beta-testers"]);
|
|
507
|
-
return [2 /*return*/];
|
|
508
|
-
}
|
|
509
|
-
});
|
|
510
|
-
}); });
|
|
511
|
-
(0, bun_test_1.it)("rejects non-admin users", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
512
|
-
var res;
|
|
513
|
-
return __generator(this, function (_a) {
|
|
514
|
-
switch (_a.label) {
|
|
515
|
-
case 0: return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
516
|
-
case 1:
|
|
517
|
-
notAdminAgent = _a.sent();
|
|
518
|
-
return [4 /*yield*/, notAdminAgent.get("/feature-flags/segments").expect(403)];
|
|
519
|
-
case 2:
|
|
520
|
-
res = _a.sent();
|
|
521
|
-
(0, bun_test_1.expect)(res.body.title).toInclude("Only admins can view segments");
|
|
522
|
-
return [2 /*return*/];
|
|
523
|
-
}
|
|
524
|
-
});
|
|
525
|
-
}); });
|
|
526
|
-
(0, bun_test_1.it)("requires authentication", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
527
|
-
var unauth;
|
|
528
|
-
return __generator(this, function (_a) {
|
|
529
|
-
switch (_a.label) {
|
|
530
|
-
case 0:
|
|
531
|
-
unauth = (0, supertest_1.default)(app);
|
|
532
|
-
return [4 /*yield*/, unauth.get("/feature-flags/segments").expect(401)];
|
|
533
|
-
case 1:
|
|
534
|
-
_a.sent();
|
|
535
|
-
return [2 /*return*/];
|
|
536
|
-
}
|
|
537
|
-
});
|
|
538
|
-
}); });
|
|
539
|
-
});
|
|
540
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|