@plyaz/types 1.3.2 → 1.3.3

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.
Files changed (49) hide show
  1. package/dist/api/index.d.ts +1 -0
  2. package/dist/api/types.d.ts +84 -0
  3. package/dist/auth/enums.d.ts +32 -0
  4. package/dist/auth/index.d.ts +3 -0
  5. package/dist/auth/schemas.d.ts +27 -0
  6. package/dist/auth/types.d.ts +34 -0
  7. package/dist/common/index.d.ts +2 -0
  8. package/dist/common/types.d.ts +22 -0
  9. package/dist/entities/index.d.ts +1 -0
  10. package/dist/errors/enums.d.ts +33 -0
  11. package/dist/errors/index.d.ts +2 -0
  12. package/dist/errors/types.d.ts +79 -0
  13. package/dist/events/enums.d.ts +25 -0
  14. package/dist/events/index.d.ts +3 -0
  15. package/dist/events/payload.d.ts +6 -0
  16. package/dist/events/types.d.ts +136 -0
  17. package/dist/features/cache/index.d.ts +1 -0
  18. package/dist/features/cache/types.d.ts +142 -0
  19. package/dist/features/feature-flag/index.d.ts +1 -0
  20. package/dist/features/feature-flag/types.d.ts +491 -0
  21. package/dist/features/index.d.ts +2 -0
  22. package/dist/index.d.ts +12 -0
  23. package/dist/store/index.d.ts +1 -0
  24. package/dist/testing/common/assertions/index.d.ts +1 -0
  25. package/dist/testing/common/assertions/types.d.ts +137 -0
  26. package/dist/testing/common/factories/index.d.ts +1 -0
  27. package/dist/testing/common/factories/types.d.ts +701 -0
  28. package/dist/testing/common/index.d.ts +6 -0
  29. package/dist/testing/common/mocks/index.d.ts +1 -0
  30. package/dist/testing/common/mocks/types.d.ts +1662 -0
  31. package/dist/testing/common/patterns/index.d.ts +1 -0
  32. package/dist/testing/common/patterns/types.d.ts +397 -0
  33. package/dist/testing/common/utils/index.d.ts +1 -0
  34. package/dist/testing/common/utils/types.d.ts +1970 -0
  35. package/dist/testing/common/wrappers/index.d.ts +1 -0
  36. package/dist/testing/common/wrappers/types.d.ts +373 -0
  37. package/dist/testing/features/cache/index.d.ts +1 -0
  38. package/dist/testing/features/cache/types.d.ts +43 -0
  39. package/dist/testing/features/feature-flags/index.d.ts +1 -0
  40. package/dist/testing/features/feature-flags/types.d.ts +1133 -0
  41. package/dist/testing/features/index.d.ts +2 -0
  42. package/dist/testing/index.d.ts +2 -0
  43. package/dist/translations/index.d.ts +1 -0
  44. package/dist/translations/types.d.ts +390 -0
  45. package/dist/ui/index.d.ts +1 -0
  46. package/dist/web3/enums.d.ts +17 -0
  47. package/dist/web3/index.d.ts +2 -0
  48. package/dist/web3/types.d.ts +63 -0
  49. package/package.json +2 -2
@@ -0,0 +1,1133 @@
1
+ /**
2
+ * @fileoverview Feature Flag Testing Types
3
+ *
4
+ * Comprehensive type definitions for testing feature flag functionality across
5
+ * different providers, evaluation strategies, and contexts. Provides type safety
6
+ * for feature flag test scenarios, mocking, and validation.
7
+ *
8
+ * This module includes types for:
9
+ * - Feature flag builders and factories
10
+ * - Mock feature flag providers
11
+ * - Feature flag test scenarios and assertions
12
+ * - Context and evaluation testing
13
+ * - Integration with React components and hooks
14
+ * - Provider switching and configuration testing
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import type {
19
+ * FeatureFlagBuilder,
20
+ * MockFeatureFlagProvider,
21
+ * FeatureFlagTestScenario
22
+ * } from './types';
23
+ *
24
+ * // Build test feature flags
25
+ * const flag = featureFlagBuilder
26
+ * .withKey('new-checkout')
27
+ * .withValue(true)
28
+ * .withContext({ userId: '123' })
29
+ * .build();
30
+ *
31
+ * // Mock provider for testing
32
+ * const mockProvider: MockFeatureFlagProvider = createMockProvider();
33
+ * mockProvider.get.mockResolvedValue(true);
34
+ *
35
+ * // Test scenarios
36
+ * const scenario: FeatureFlagTestScenario = {
37
+ * name: 'Checkout flag enabled',
38
+ * flags: { 'new-checkout': true },
39
+ * expectedBehavior: () => expect(checkoutButton).toBeVisible()
40
+ * };
41
+ * ```
42
+ *
43
+ * @module FeatureFlagTestingTypes
44
+ * @since 1.0.0
45
+ */
46
+ import type * as Vitest from 'vitest';
47
+ import type * as React from 'react';
48
+ import type { FeatureFlag, FeatureFlagCondition, FeatureFlagConfig, FeatureFlagContext, FeatureFlagEvaluation, FeatureFlagRule, FeatureFlagValue, FeatureFlagProvider as IFeatureFlagProvider, FeatureFlagContextValue } from '../../../features';
49
+ import type { MockLogger, RenderFunction, RenderHookFunction } from '../../common';
50
+ /**
51
+ * Builder interface for creating feature flag test objects with fluent API
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * const flag = featureFlagBuilder
56
+ * .withKey('new-checkout')
57
+ * .withValue(true)
58
+ * .withEnabled(true)
59
+ * .withRolloutPercentage(50)
60
+ * .withCondition({ field: 'userId', operator: 'in', value: ['user1', 'user2'] })
61
+ * .build();
62
+ * ```
63
+ */
64
+ export interface FeatureFlagBuilder<FeatureFlagKey extends string> {
65
+ /** Set the feature flag key */
66
+ withKey: (key: FeatureFlagKey) => FeatureFlagBuilder<FeatureFlagKey>;
67
+ /** Set the feature flag value */
68
+ withValue: (value: FeatureFlagValue) => FeatureFlagBuilder<FeatureFlagKey>;
69
+ /** Set whether the flag is enabled */
70
+ withEnabled: (enabled: boolean) => FeatureFlagBuilder<FeatureFlagKey>;
71
+ /** Set the flag description */
72
+ withDescription: (description: string) => FeatureFlagBuilder<FeatureFlagKey>;
73
+ /** Set the rollout percentage (0-100) */
74
+ withRolloutPercentage: (percentage: number) => FeatureFlagBuilder<FeatureFlagKey>;
75
+ /** Add a single condition */
76
+ withCondition: (condition: FeatureFlagCondition) => FeatureFlagBuilder<FeatureFlagKey>;
77
+ /** Set multiple conditions */
78
+ withConditions: (conditions: FeatureFlagCondition[]) => FeatureFlagBuilder<FeatureFlagKey>;
79
+ /** Set the creation date */
80
+ withCreatedAt: (date: Date) => FeatureFlagBuilder<FeatureFlagKey>;
81
+ /** Set the last update date */
82
+ withUpdatedAt: (date: Date) => FeatureFlagBuilder<FeatureFlagKey>;
83
+ /** Build the final feature flag object */
84
+ build: () => FeatureFlag<FeatureFlagKey>;
85
+ }
86
+ /**
87
+ * Mock objects for feature flag module testing
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const mocks: SetupFeatureFlagModuleMocks = {
92
+ * mockLogger: createMockLogger(),
93
+ * HttpException: vi.fn(),
94
+ * HttpStatus: { OK: 200, NOT_FOUND: 404, INTERNAL_SERVER_ERROR: 500 }
95
+ * };
96
+ * ```
97
+ */
98
+ export interface SetupFeatureFlagModuleMocks {
99
+ /** Mock logger instance */
100
+ mockLogger: MockLogger;
101
+ /** Mock HTTP exception constructor */
102
+ HttpException: Vitest.Mock;
103
+ /** HTTP status code constants */
104
+ HttpStatus: Record<string, number>;
105
+ }
106
+ /**
107
+ * Builder interface for creating feature flag context objects
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const context = contextBuilder
112
+ * .withUserId('user-123')
113
+ * .withEnvironment('production')
114
+ * .withCountry('US')
115
+ * .withCustom({ tier: 'premium', beta: true })
116
+ * .build();
117
+ * ```
118
+ */
119
+ export interface FeatureFlagContextBuilder {
120
+ /** Set the user identifier */
121
+ withUserId: (userId: string) => FeatureFlagContextBuilder;
122
+ /** Set the group identifier */
123
+ withGroupId: (groupId: string) => FeatureFlagContextBuilder;
124
+ /** Set the environment (dev, staging, prod) */
125
+ withEnvironment: (environment: string) => FeatureFlagContextBuilder;
126
+ /** Set the user's country */
127
+ withCountry: (country: string) => FeatureFlagContextBuilder;
128
+ /** Set the user's language */
129
+ withLanguage: (language: string) => FeatureFlagContextBuilder;
130
+ /** Set the platform (web, mobile, api) */
131
+ withPlatform: (platform: string) => FeatureFlagContextBuilder;
132
+ /** Set the application version */
133
+ withVersion: (version: string) => FeatureFlagContextBuilder;
134
+ /** Set custom context properties */
135
+ withCustom: (custom: Record<string, unknown>) => FeatureFlagContextBuilder;
136
+ /** Build the final context object */
137
+ build: () => FeatureFlagContext;
138
+ }
139
+ /**
140
+ * Builder interface for creating feature flag condition objects
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const condition = conditionBuilder
145
+ * .withField('userId')
146
+ * .withOperator('in')
147
+ * .withValue(['user1', 'user2', 'user3'])
148
+ * .build();
149
+ * ```
150
+ */
151
+ export interface FeatureFlagConditionBuilder {
152
+ /** Set the field to evaluate */
153
+ withField: (field: FeatureFlagCondition['field']) => FeatureFlagConditionBuilder;
154
+ /** Set the comparison operator */
155
+ withOperator: (operator: FeatureFlagCondition['operator']) => FeatureFlagConditionBuilder;
156
+ /** Set the comparison value(s) */
157
+ withValue: (value: string | number | string[] | number[]) => FeatureFlagConditionBuilder;
158
+ /** Build the final condition object */
159
+ build: () => FeatureFlagCondition;
160
+ }
161
+ /**
162
+ * Factory interface for creating various types of feature flag test objects
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const factory: FeatureFlagFactory = createFeatureFlagFactory();
167
+ *
168
+ * // Create basic flag
169
+ * const flag = factory.create({ key: 'my-flag', enabled: true });
170
+ *
171
+ * // Create rollout flag
172
+ * const rolloutFlag = factory.createWithRollout(25, { key: 'gradual-rollout' });
173
+ *
174
+ * // Create typed flags
175
+ * const boolFlag = factory.createBoolean('feature-enabled', true);
176
+ * const stringFlag = factory.createString('theme', 'dark');
177
+ * ```
178
+ */
179
+ export interface FeatureFlagFactory<FeatureFlagKey extends string> {
180
+ /** Create a basic feature flag */
181
+ create: (overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
182
+ /** Create multiple feature flags */
183
+ createList: (count: number, overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>[];
184
+ /** Create an enabled feature flag */
185
+ createEnabled: (overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
186
+ /** Create a disabled feature flag */
187
+ createDisabled: (overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
188
+ /** Create a feature flag with rollout percentage */
189
+ createWithRollout: (percentage: number, overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
190
+ /** Create a feature flag with conditions */
191
+ createWithConditions: (conditions: FeatureFlagCondition[], overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
192
+ /** Create a boolean feature flag */
193
+ createBoolean: (key: string, value: boolean, overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
194
+ /** Create a string feature flag */
195
+ createString: (key: string, value: string, overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
196
+ /** Create a number feature flag */
197
+ createNumber: (key: string, value: number, overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
198
+ /** Create an object feature flag */
199
+ createObject: (key: string, value: Record<string, unknown>, overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>;
200
+ }
201
+ /**
202
+ * Pre-defined feature flag scenario generators for common testing patterns
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const scenarios: FeatureFlagScenarios = createFeatureFlagScenarios();
207
+ *
208
+ * // Get basic enabled/disabled flags
209
+ * const basicFlags = scenarios.basic();
210
+ *
211
+ * // Get flags with rollout percentages
212
+ * const rolloutFlags = scenarios.rollout();
213
+ *
214
+ * // Get flags with complex conditions
215
+ * const conditionalFlags = scenarios.conditional();
216
+ * ```
217
+ */
218
+ export interface FeatureFlagScenarios<FeatureFlagKey extends string> {
219
+ /** Generate basic enabled/disabled flags */
220
+ basic: () => FeatureFlag<FeatureFlagKey>[];
221
+ /** Generate flags with rollout percentages */
222
+ rollout: () => FeatureFlag<FeatureFlagKey>[];
223
+ /** Generate flags with conditions */
224
+ conditional: () => FeatureFlag<FeatureFlagKey>[];
225
+ /** Generate flags with multiple variants */
226
+ multiVariant: () => FeatureFlag<FeatureFlagKey>[];
227
+ /** Generate flags targeting specific users */
228
+ userTargeting: () => FeatureFlag<FeatureFlagKey>[];
229
+ /** Generate flags targeting user groups */
230
+ groupTargeting: () => FeatureFlag<FeatureFlagKey>[];
231
+ /** Generate flags targeting environments */
232
+ environmentTargeting: () => FeatureFlag<FeatureFlagKey>[];
233
+ /** Generate mixed scenario flags */
234
+ mixed: () => FeatureFlag<FeatureFlagKey>[];
235
+ }
236
+ /**
237
+ * Mock feature flag provider interface for testing provider interactions
238
+ *
239
+ * @example
240
+ * ```typescript
241
+ * const mockProvider: MockFeatureFlagProvider = {
242
+ * getFlag: vi.fn().mockResolvedValue(mockFlag),
243
+ * getAllFlags: vi.fn().mockResolvedValue([mockFlag1, mockFlag2]),
244
+ * evaluateFlag: vi.fn().mockResolvedValue({ value: true, reason: 'enabled' }),
245
+ * isEnabled: vi.fn().mockResolvedValue(true),
246
+ * getValue: vi.fn().mockResolvedValue('default-value'),
247
+ * // ... other methods
248
+ * };
249
+ * ```
250
+ */
251
+ export interface MockFeatureFlagProvider {
252
+ /** Get a specific feature flag */
253
+ getFlag: Vitest.Mock;
254
+ /** Get all feature flags */
255
+ getAllFlags: Vitest.Mock;
256
+ /** Evaluate a feature flag */
257
+ evaluateFlag: Vitest.Mock;
258
+ /** Check if a flag is enabled */
259
+ isEnabled: Vitest.Mock;
260
+ /** Get a flag's value */
261
+ getValue: Vitest.Mock;
262
+ /** Update a feature flag */
263
+ updateFlag: Vitest.Mock;
264
+ /** Delete a feature flag */
265
+ deleteFlag: Vitest.Mock;
266
+ /** Refresh flag data */
267
+ refresh: Vitest.Mock;
268
+ /** Subscribe to flag changes */
269
+ subscribe: Vitest.Mock;
270
+ /** Unsubscribe from flag changes */
271
+ unsubscribe: Vitest.Mock;
272
+ }
273
+ /**
274
+ * Mock feature flag repository interface for database operations testing
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * const mockRepository: MockFeatureFlagRepository = {
279
+ * find: vi.fn().mockResolvedValue(mockFlag),
280
+ * findAll: vi.fn().mockResolvedValue([mockFlag1, mockFlag2]),
281
+ * create: vi.fn().mockResolvedValue(newMockFlag),
282
+ * update: vi.fn().mockResolvedValue(updatedMockFlag),
283
+ * delete: vi.fn().mockResolvedValue(true),
284
+ * save: vi.fn().mockResolvedValue(savedMockFlag),
285
+ * exists: vi.fn().mockResolvedValue(true),
286
+ * count: vi.fn().mockResolvedValue(5)
287
+ * };
288
+ * ```
289
+ */
290
+ export interface MockFeatureFlagRepository {
291
+ /** Find a single flag by criteria */
292
+ find: Vitest.Mock;
293
+ /** Find all flags */
294
+ findAll: Vitest.Mock;
295
+ /** Create a new flag */
296
+ create: Vitest.Mock;
297
+ /** Update an existing flag */
298
+ update: Vitest.Mock;
299
+ /** Delete a flag */
300
+ delete: Vitest.Mock;
301
+ /** Save a flag */
302
+ save: Vitest.Mock;
303
+ /** Check if a flag exists */
304
+ exists: Vitest.Mock;
305
+ /** Count total flags */
306
+ count: Vitest.Mock;
307
+ }
308
+ /**
309
+ * Mock feature flag service interface for business logic testing
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * const mockService: MockFeatureFlagService = {
314
+ * evaluate: vi.fn().mockResolvedValue({ value: true, reason: 'enabled' }),
315
+ * evaluateAll: vi.fn().mockResolvedValue(evaluationResults),
316
+ * isEnabled: vi.fn().mockResolvedValue(true),
317
+ * getValue: vi.fn().mockResolvedValue('variant-a'),
318
+ * getVariation: vi.fn().mockResolvedValue('control'),
319
+ * track: vi.fn().mockResolvedValue(undefined),
320
+ * refresh: vi.fn().mockResolvedValue(undefined),
321
+ * invalidateCache: vi.fn().mockResolvedValue(undefined)
322
+ * };
323
+ * ```
324
+ */
325
+ export interface MockFeatureFlagService {
326
+ /** Evaluate a single flag */
327
+ evaluate: Vitest.Mock;
328
+ /** Evaluate all flags */
329
+ evaluateAll: Vitest.Mock;
330
+ /** Check if flag is enabled */
331
+ isEnabled: Vitest.Mock;
332
+ /** Get flag value */
333
+ getValue: Vitest.Mock;
334
+ /** Get flag variation */
335
+ getVariation: Vitest.Mock;
336
+ /** Track flag usage */
337
+ track: Vitest.Mock;
338
+ /** Refresh flag data */
339
+ refresh: Vitest.Mock;
340
+ /** Clear cache */
341
+ invalidateCache: Vitest.Mock;
342
+ }
343
+ /**
344
+ * Mock feature flag evaluation engine interface for testing flag logic
345
+ *
346
+ * @example
347
+ * ```typescript
348
+ * const mockEngine: MockFeatureFlagEngine = {
349
+ * evaluate: vi.fn().mockReturnValue({ value: true, reason: 'match' }),
350
+ * evaluateConditions: vi.fn().mockReturnValue(true),
351
+ * checkRollout: vi.fn().mockReturnValue(true),
352
+ * calculateVariation: vi.fn().mockReturnValue('variant-b'),
353
+ * getDefaultValue: vi.fn().mockReturnValue(false)
354
+ * };
355
+ * ```
356
+ */
357
+ export interface MockFeatureFlagEngine {
358
+ /** Evaluate flag with context */
359
+ evaluate: Vitest.Mock;
360
+ /** Evaluate conditions */
361
+ evaluateConditions: Vitest.Mock;
362
+ /** Check rollout eligibility */
363
+ checkRollout: Vitest.Mock;
364
+ /** Calculate variation */
365
+ calculateVariation: Vitest.Mock;
366
+ /** Get default value */
367
+ getDefaultValue: Vitest.Mock;
368
+ }
369
+ /**
370
+ * Mock feature flag cache interface for testing caching behavior
371
+ *
372
+ * @example
373
+ * ```typescript
374
+ * const mockCache: MockFeatureFlagCache = {
375
+ * get: vi.fn().mockResolvedValue(cachedFlag),
376
+ * set: vi.fn().mockResolvedValue(undefined),
377
+ * delete: vi.fn().mockResolvedValue(true),
378
+ * clear: vi.fn().mockResolvedValue(undefined),
379
+ * has: vi.fn().mockResolvedValue(true),
380
+ * keys: vi.fn().mockResolvedValue(['flag1', 'flag2']),
381
+ * values: vi.fn().mockResolvedValue([flag1, flag2]),
382
+ * size: vi.fn().mockResolvedValue(10)
383
+ * };
384
+ * ```
385
+ */
386
+ export interface MockFeatureFlagCache {
387
+ /** Get cached value */
388
+ get: Vitest.Mock;
389
+ /** Set cache value */
390
+ set: Vitest.Mock;
391
+ /** Delete cached value */
392
+ delete: Vitest.Mock;
393
+ /** Clear all cache */
394
+ clear: Vitest.Mock;
395
+ /** Check if key exists */
396
+ has: Vitest.Mock;
397
+ /** Get all cache keys */
398
+ keys: Vitest.Mock;
399
+ /** Get all cache values */
400
+ values: Vitest.Mock;
401
+ /** Get cache size */
402
+ size: Vitest.Mock;
403
+ }
404
+ /**
405
+ * Test context for feature flag testing with React components
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * const testContext: FeatureFlagTestContext = await setupFeatureFlagTest<FeatureFlagKey>({
410
+ * flags: [testFlag1, testFlag2],
411
+ * context: { userId: 'test-user' }
412
+ * });
413
+ *
414
+ * // Use in component tests
415
+ * const { getByText } = testContext.render(
416
+ * <testContext.wrapper>
417
+ * <MyComponent />
418
+ * </testContext.wrapper>
419
+ * );
420
+ *
421
+ * // Clean up after test
422
+ * await testContext.cleanup();
423
+ * ```
424
+ */
425
+ export interface FeatureFlagTestContext<FeatureFlagKey extends string> {
426
+ /** Feature flag provider instance */
427
+ provider: IFeatureFlagProvider<FeatureFlagKey>;
428
+ /** Cleanup function for test teardown */
429
+ cleanup: () => Promise<void>;
430
+ /** React wrapper component with provider */
431
+ wrapper: (props: {
432
+ children: React.ReactNode;
433
+ }) => React.ReactNode;
434
+ /** Enhanced render function */
435
+ render: RenderFunction;
436
+ /** Enhanced renderHook function */
437
+ renderHook: RenderHookFunction;
438
+ }
439
+ /**
440
+ * Options for configuring feature flag tests
441
+ *
442
+ * @example
443
+ * ```typescript
444
+ * const options: FeatureFlagTestOptions = {
445
+ * flags: [enabledFlag, disabledFlag],
446
+ * context: { userId: 'test-user', environment: 'test' },
447
+ * provider: 'memory',
448
+ * cache: false,
449
+ * timeout: 5000
450
+ * };
451
+ *
452
+ * const testContext = await setupFeatureFlagTest<FeatureFlagKey>(options);
453
+ * ```
454
+ */
455
+ export interface FeatureFlagTestOptions<FeatureFlagKey extends string> {
456
+ /** Initial flags to load */
457
+ flags?: FeatureFlag<FeatureFlagKey>[];
458
+ /** Default evaluation context */
459
+ context?: FeatureFlagContext;
460
+ /** Provider type to use */
461
+ provider?: 'memory' | 'file' | 'database' | 'api' | 'redis';
462
+ /** Enable caching */
463
+ cache?: boolean;
464
+ /** Enable auto-refresh */
465
+ refresh?: boolean;
466
+ /** Request timeout in milliseconds */
467
+ timeout?: number;
468
+ }
469
+ /**
470
+ * Single feature flag test scenario definition
471
+ *
472
+ * @example
473
+ * ```typescript
474
+ * const scenario: FeatureFlagScenario = {
475
+ * name: 'Premium user sees new feature',
476
+ * description: 'Premium users should see the new checkout flow',
477
+ * flags: [newCheckoutFlag],
478
+ * context: { userId: 'premium-user-1', tier: 'premium' },
479
+ * expectedResults: {
480
+ * 'new-checkout': true,
481
+ * 'old-checkout': false
482
+ * },
483
+ * setup: async () => {
484
+ * await seedTestData();
485
+ * },
486
+ * teardown: async () => {
487
+ * await cleanupTestData();
488
+ * }
489
+ * };
490
+ * ```
491
+ */
492
+ export interface FeatureFlagScenario<FeatureFlagKey extends string> {
493
+ /** Scenario name */
494
+ name: string;
495
+ /** Optional scenario description */
496
+ description?: string;
497
+ /** Feature flags for this scenario */
498
+ flags: FeatureFlag<FeatureFlagKey>[];
499
+ /** Evaluation context */
500
+ context?: FeatureFlagContext;
501
+ /** Expected flag evaluation results */
502
+ expectedResults: Record<string, FeatureFlagValue>;
503
+ /** Setup function run before scenario */
504
+ setup?: () => void | Promise<void>;
505
+ /** Teardown function run after scenario */
506
+ teardown?: () => void | Promise<void>;
507
+ }
508
+ /**
509
+ * Test suite for managing and running multiple feature flag scenarios
510
+ *
511
+ * @example
512
+ * ```typescript
513
+ * const testSuite: FeatureFlagTestSuite = createFeatureFlagTestSuite();
514
+ *
515
+ * // Add scenarios
516
+ * testSuite.addScenario(premiumUserScenario);
517
+ * testSuite.addScenario(freeUserScenario);
518
+ *
519
+ * // Run specific scenario
520
+ * await testSuite.run('Premium user sees new feature');
521
+ *
522
+ * // Run all scenarios
523
+ * await testSuite.runAll();
524
+ *
525
+ * // Clean up
526
+ * testSuite.clear();
527
+ * ```
528
+ */
529
+ export interface FeatureFlagTestSuite<FeatureFlagKey extends string> {
530
+ /** All scenarios in the suite */
531
+ scenarios: FeatureFlagScenario<FeatureFlagKey>[];
532
+ /** Run a specific scenario by name */
533
+ run: (scenarioName?: string) => Promise<void>;
534
+ /** Run all scenarios in sequence */
535
+ runAll: () => Promise<void>;
536
+ /** Add a new scenario */
537
+ addScenario: (scenario: FeatureFlagScenario<FeatureFlagKey>) => void;
538
+ /** Remove a scenario by name */
539
+ removeScenario: (name: string) => void;
540
+ /** Clear all scenarios */
541
+ clear: () => void;
542
+ }
543
+ /**
544
+ * Custom assertion methods for feature flag testing
545
+ *
546
+ * @example
547
+ * ```typescript
548
+ * // Custom matchers extend expect
549
+ * expect(featureFlag).toBeEnabled();
550
+ * expect(featureFlag).toHaveValue(true);
551
+ * expect(featureFlag).toHaveRolloutPercentage(25);
552
+ * expect(featureFlag).toBeEvaluatedAs(true, userContext);
553
+ * ```
554
+ */
555
+ export interface FeatureFlagAssertion {
556
+ /** Assert flag is enabled */
557
+ toBeEnabled: () => void;
558
+ /** Assert flag is disabled */
559
+ toBeDisabled: () => void;
560
+ /** Assert flag has specific value */
561
+ toHaveValue: (value: FeatureFlagValue) => void;
562
+ /** Assert flag has specific rollout percentage */
563
+ toHaveRolloutPercentage: (percentage: number) => void;
564
+ /** Assert flag has specific conditions */
565
+ toHaveConditions: (conditions: FeatureFlagCondition[]) => void;
566
+ /** Assert flag matches a condition */
567
+ toMatchCondition: (condition: FeatureFlagCondition) => void;
568
+ /** Assert flag evaluates to specific value in context */
569
+ toBeEvaluatedAs: (value: FeatureFlagValue, context?: FeatureFlagContext) => void;
570
+ /** Assert flag is targeted to specific context */
571
+ toBeTargetedTo: (context: FeatureFlagContext) => void;
572
+ /** Assert flag is rolled out to percentage */
573
+ toBeRolledOutTo: (percentage: number) => void;
574
+ }
575
+ /**
576
+ * Helper utilities for feature flag testing operations
577
+ *
578
+ * @example
579
+ * ```typescript
580
+ * const helpers: FeatureFlagHelpers = createFeatureFlagHelpers();
581
+ *
582
+ * // Create mocks
583
+ * const mockProvider = helpers.createProvider({ cache: true });
584
+ * const mockRepository = helpers.createRepository();
585
+ *
586
+ * // Setup scenario
587
+ * await helpers.setupScenario(testScenario);
588
+ *
589
+ * // Evaluate flags
590
+ * const evaluation = helpers.evaluateFlag(flag, context);
591
+ * const isEnabled = helpers.evaluateCondition(condition, context);
592
+ *
593
+ * // Generate test data
594
+ * const testContext = helpers.generateContext({ userId: 'test' });
595
+ * const testFlags = helpers.generateFlags(10);
596
+ * ```
597
+ */
598
+ export interface FeatureFlagHelpersMock<FeatureFlagKey extends string> {
599
+ /** Create mock provider */
600
+ createProvider: (options?: FeatureFlagTestOptions<FeatureFlagKey>) => MockFeatureFlagProvider;
601
+ /** Create mock repository */
602
+ createRepository: () => MockFeatureFlagRepository;
603
+ /** Create mock service */
604
+ createService: () => MockFeatureFlagService;
605
+ /** Create mock engine */
606
+ createEngine: () => MockFeatureFlagEngine;
607
+ /** Create mock cache */
608
+ createCache: () => MockFeatureFlagCache;
609
+ /** Setup test scenario */
610
+ setupScenario: (scenario: FeatureFlagScenario<FeatureFlagKey>) => Promise<void>;
611
+ /** Evaluate flag manually */
612
+ evaluateFlag: (flag: FeatureFlag<FeatureFlagKey>, context?: FeatureFlagContext) => FeatureFlagEvaluation<FeatureFlagKey>;
613
+ /** Evaluate condition manually */
614
+ evaluateCondition: (condition: FeatureFlagCondition, context: FeatureFlagContext) => boolean;
615
+ /** Calculate rollout eligibility */
616
+ calculateRollout: (percentage: number, context: FeatureFlagContext) => boolean;
617
+ /** Generate test context */
618
+ generateContext: (overrides?: Partial<FeatureFlagContext>) => FeatureFlagContext;
619
+ /** Generate test flags */
620
+ generateFlags: (count: number, overrides?: Partial<FeatureFlag<FeatureFlagKey>>) => FeatureFlag<FeatureFlagKey>[];
621
+ }
622
+ /**
623
+ * Configuration for feature flag testing environment
624
+ *
625
+ * @example
626
+ * ```typescript
627
+ * const config: FeatureFlagTestConfig = {
628
+ * defaultProvider: 'memory',
629
+ * defaultTimeout: 5000,
630
+ * enableCache: false,
631
+ * cacheTimeout: 300000,
632
+ * enableLogging: true,
633
+ * logLevel: 'warn',
634
+ * mockOptions: {
635
+ * autoResolve: true,
636
+ * defaultEnabled: false,
637
+ * defaultValue: false,
638
+ * rolloutStrategy: 'deterministic'
639
+ * }
640
+ * };
641
+ *
642
+ * setupFeatureFlagTesting(config);
643
+ * ```
644
+ */
645
+ export interface FeatureFlagTestConfig {
646
+ /** Default provider type */
647
+ defaultProvider: 'memory' | 'file' | 'database' | 'api' | 'redis';
648
+ /** Default request timeout */
649
+ defaultTimeout: number;
650
+ /** Enable caching */
651
+ enableCache: boolean;
652
+ /** Cache timeout in milliseconds */
653
+ cacheTimeout: number;
654
+ /** Enable logging */
655
+ enableLogging: boolean;
656
+ /** Log level */
657
+ logLevel: 'debug' | 'info' | 'warn' | 'error';
658
+ /** Mock behavior options */
659
+ mockOptions: {
660
+ /** Auto-resolve promises */
661
+ autoResolve: boolean;
662
+ /** Default enabled state */
663
+ defaultEnabled: boolean;
664
+ /** Default flag value */
665
+ defaultValue: FeatureFlagValue;
666
+ /** Rollout calculation strategy */
667
+ rolloutStrategy: 'random' | 'deterministic';
668
+ };
669
+ }
670
+ /**
671
+ * Feature flag event for tracking flag operations and changes
672
+ *
673
+ * @example
674
+ * ```typescript
675
+ * const event: FeatureFlagEvent = {
676
+ * type: 'evaluation',
677
+ * flagKey: 'new-checkout',
678
+ * context: { userId: 'user-123' },
679
+ * value: true,
680
+ * timestamp: new Date(),
681
+ * metadata: { source: 'api', version: '1.0' }
682
+ * };
683
+ *
684
+ * // Emit event
685
+ * eventEmitter.emit(event);
686
+ * ```
687
+ */
688
+ export interface FeatureFlagEvent {
689
+ /** Type of flag operation */
690
+ type: 'evaluation' | 'update' | 'create' | 'delete' | 'refresh';
691
+ /** Flag identifier */
692
+ flagKey: string;
693
+ /** Evaluation context (for evaluations) */
694
+ context?: FeatureFlagContext;
695
+ /** Flag value (for evaluations/updates) */
696
+ value?: FeatureFlagValue;
697
+ /** Event timestamp */
698
+ timestamp: Date;
699
+ /** Additional event metadata */
700
+ metadata?: Record<string, unknown>;
701
+ }
702
+ /**
703
+ * Handler function for feature flag events
704
+ *
705
+ * @example
706
+ * ```typescript
707
+ * const handler: FeatureFlagEventHandler = async (event) => {
708
+ * console.log(`Flag ${event.flagKey} was ${event.type}`);
709
+ *
710
+ * if (event.type === 'evaluation') {
711
+ * await logFlagUsage(event.flagKey, event.context, event.value);
712
+ * }
713
+ * };
714
+ *
715
+ * eventEmitter.on('evaluation', handler);
716
+ * ```
717
+ */
718
+ export interface FeatureFlagEventHandler {
719
+ (event: FeatureFlagEvent): void | Promise<void>;
720
+ }
721
+ /**
722
+ * Event emitter for feature flag events with subscription management
723
+ *
724
+ * @example
725
+ * ```typescript
726
+ * const emitter: FeatureFlagEventEmitter = createFeatureFlagEventEmitter();
727
+ *
728
+ * // Subscribe to events
729
+ * const unsubscribe = emitter.on('evaluation', (event) => {
730
+ * console.log(`Flag ${event.flagKey} evaluated to ${event.value}`);
731
+ * });
732
+ *
733
+ * // One-time subscription
734
+ * emitter.once('update', (event) => {
735
+ * console.log('Flag updated:', event.flagKey);
736
+ * });
737
+ *
738
+ * // Emit events
739
+ * emitter.emit({
740
+ * type: 'evaluation',
741
+ * flagKey: 'my-flag',
742
+ * value: true,
743
+ * timestamp: new Date()
744
+ * });
745
+ *
746
+ * // Clean up
747
+ * unsubscribe();
748
+ * emitter.removeAllListeners();
749
+ * ```
750
+ */
751
+ export interface FeatureFlagEventEmitter {
752
+ /** Subscribe to events */
753
+ on: (type: FeatureFlagEvent['type'], handler: FeatureFlagEventHandler) => () => void;
754
+ /** Subscribe to single event */
755
+ once: (type: FeatureFlagEvent['type'], handler: FeatureFlagEventHandler) => () => void;
756
+ /** Emit an event */
757
+ emit: (event: FeatureFlagEvent) => void;
758
+ /** Unsubscribe from events */
759
+ off: (type: FeatureFlagEvent['type'], handler: FeatureFlagEventHandler) => void;
760
+ /** Remove all listeners */
761
+ removeAllListeners: (type?: FeatureFlagEvent['type']) => void;
762
+ }
763
+ /**
764
+ * Custom assertions for React hook testing with feature flags
765
+ *
766
+ * @example
767
+ * ```typescript
768
+ * const { result } = renderHook(() => useFeatureFlag('my-flag'), {
769
+ * wrapper: FeatureFlagProvider
770
+ * });
771
+ *
772
+ * // Custom hook assertions
773
+ * expect(result).toBeEnabled('my-flag');
774
+ * expect(result).toBeDisabled('old-flag');
775
+ * expect(result).toHaveValue('theme-flag', 'dark');
776
+ * ```
777
+ */
778
+ export interface FeatureFlagHookAssertion<FeatureFlagKey extends string> {
779
+ /** Assert hook shows flag as enabled */
780
+ toBeEnabled: (flagKey: FeatureFlagKey) => void;
781
+ /** Assert hook shows flag as disabled */
782
+ toBeDisabled: (flagKey: FeatureFlagKey) => void;
783
+ /** Assert hook shows flag with specific value */
784
+ toHaveValue: (flagKey: FeatureFlagKey, value: FeatureFlagValue) => void;
785
+ }
786
+ /**
787
+ * Stub definition for temporarily overriding feature flags in tests
788
+ *
789
+ * @example
790
+ * ```typescript
791
+ * const stub: FeatureFlagStub = {
792
+ * key: 'premium-feature',
793
+ * value: true,
794
+ * enabled: true,
795
+ * conditions: [{ field: 'tier', operator: 'equals', value: 'premium' }],
796
+ * rolloutPercentage: 100,
797
+ * temporary: true,
798
+ * priority: 10
799
+ * };
800
+ *
801
+ * stubManager.add(stub, { duration: 5000 });
802
+ * ```
803
+ */
804
+ export interface FeatureFlagStub {
805
+ /** Flag key to stub */
806
+ key: string;
807
+ /** Value to return */
808
+ value: FeatureFlagValue;
809
+ /** Whether flag is enabled */
810
+ enabled: boolean;
811
+ /** Conditions for evaluation */
812
+ conditions?: FeatureFlagCondition[];
813
+ /** Rollout percentage override */
814
+ rolloutPercentage?: number;
815
+ /** Auto-remove after test */
816
+ temporary?: boolean;
817
+ /** Stub priority (higher wins) */
818
+ priority?: number;
819
+ }
820
+ /**
821
+ * Options for configuring feature flag stubs
822
+ *
823
+ * @example
824
+ * ```typescript
825
+ * const options: FeatureFlagStubOptions = {
826
+ * duration: 10000, // Auto-remove after 10 seconds
827
+ * priority: 5,
828
+ * overrideExisting: true,
829
+ * applyToAllTests: false,
830
+ * scoped: true // Only apply to current test
831
+ * };
832
+ *
833
+ * stubManager.add(myStub, options);
834
+ * ```
835
+ */
836
+ export interface FeatureFlagStubOptions {
837
+ /** Auto-remove duration in milliseconds */
838
+ duration?: number;
839
+ /** Stub priority for conflicts */
840
+ priority?: number;
841
+ /** Override existing stubs */
842
+ overrideExisting?: boolean;
843
+ /** Apply to all tests in suite */
844
+ applyToAllTests?: boolean;
845
+ /** Scope to current test only */
846
+ scoped?: boolean;
847
+ }
848
+ /**
849
+ * Manager for feature flag stubs with full lifecycle management
850
+ *
851
+ * @example
852
+ * ```typescript
853
+ * const manager: FeatureFlagStubManager = createStubManager();
854
+ *
855
+ * // Add stub
856
+ * manager.add({
857
+ * key: 'test-feature',
858
+ * value: true,
859
+ * enabled: true
860
+ * });
861
+ *
862
+ * // Quick modifications
863
+ * manager.enable('disabled-feature');
864
+ * manager.setValue('config-flag', { theme: 'dark' });
865
+ * manager.setRollout('gradual-feature', 25);
866
+ *
867
+ * // Condition management
868
+ * manager.addCondition('targeted-feature', {
869
+ * field: 'userId',
870
+ * operator: 'in',
871
+ * value: ['user1', 'user2']
872
+ * });
873
+ *
874
+ * // Cleanup
875
+ * manager.clear();
876
+ * ```
877
+ */
878
+ export interface FeatureFlagStubManager {
879
+ /** Add a new stub */
880
+ add: (stub: FeatureFlagStub, options?: FeatureFlagStubOptions) => void;
881
+ /** Remove stub by key */
882
+ remove: (key: string) => void;
883
+ /** Update existing stub */
884
+ update: (key: string, updates: Partial<FeatureFlagStub>) => void;
885
+ /** Clear all stubs */
886
+ clear: () => void;
887
+ /** List all stubs */
888
+ list: () => FeatureFlagStub[];
889
+ /** Get stub by key */
890
+ get: (key: string) => FeatureFlagStub | undefined;
891
+ /** Check if stub exists */
892
+ exists: (key: string) => boolean;
893
+ /** Enable flag stub */
894
+ enable: (key: string) => void;
895
+ /** Disable flag stub */
896
+ disable: (key: string) => void;
897
+ /** Set flag value */
898
+ setValue: (key: string, value: FeatureFlagValue) => void;
899
+ /** Set rollout percentage */
900
+ setRollout: (key: string, percentage: number) => void;
901
+ /** Add condition to flag */
902
+ addCondition: (key: string, condition: FeatureFlagCondition) => void;
903
+ /** Remove condition by index */
904
+ removeCondition: (key: string, index: number) => void;
905
+ }
906
+ /**
907
+ * Feature flag update operation with timing control
908
+ *
909
+ * @example
910
+ * ```typescript
911
+ * const update: FeatureFlagUpdate = {
912
+ * key: 'gradual-rollout',
913
+ * value: true,
914
+ * delay: 2000 // Apply after 2 seconds
915
+ * };
916
+ *
917
+ * // Schedule update
918
+ * await scheduleFeatureFlagUpdate(update);
919
+ * ```
920
+ */
921
+ export interface FeatureFlagUpdate<FeatureFlagKey extends string> {
922
+ /** Flag key to update */
923
+ key: FeatureFlagKey;
924
+ /** New flag value */
925
+ value: FeatureFlagValue;
926
+ /** Delay before applying update (ms) */
927
+ delay: number;
928
+ }
929
+ /**
930
+ * Result of feature flag operation
931
+ *
932
+ * @example
933
+ * ```typescript
934
+ * const result: FeatureFlagResult = {
935
+ * success: true,
936
+ * value: { theme: 'dark', language: 'en' }
937
+ * };
938
+ *
939
+ * if (result.success) {
940
+ * console.log('Flag value:', result.value);
941
+ * }
942
+ * ```
943
+ */
944
+ export interface FeatureFlagResult {
945
+ /** Whether operation succeeded */
946
+ success?: boolean;
947
+ /** Operation result value */
948
+ value?: unknown;
949
+ }
950
+ /**
951
+ * Result wrapper for feature flag hook values
952
+ *
953
+ * @typeParam T - Type of the hook result value
954
+ *
955
+ * @example
956
+ * ```typescript
957
+ * const hookResult: FeatureFlagHookResult<boolean> = {
958
+ * current: true
959
+ * };
960
+ *
961
+ * // Usage in hook
962
+ * const { result } = renderHook(() => useFeatureFlag('my-flag'));
963
+ * expect(result.current).toBe(true);
964
+ * ```
965
+ */
966
+ export interface FeatureFlagHookResult<T> {
967
+ /** Current hook value */
968
+ current: T;
969
+ }
970
+ /**
971
+ * Props for feature flag test wrapper component
972
+ *
973
+ * @example
974
+ * ```typescript
975
+ * const WrapperComponent: React.FC<FeatureFlagWrapperProps> = ({ children }) => (
976
+ * <FeatureFlagProvider provider={mockProvider}>
977
+ * {children}
978
+ * </FeatureFlagProvider>
979
+ * );
980
+ *
981
+ * render(<MyComponent />, { wrapper: WrapperComponent });
982
+ * ```
983
+ */
984
+ export interface FeatureFlagWrapperProps {
985
+ /** Child components to wrap */
986
+ children: React.ReactNode;
987
+ }
988
+ /**
989
+ * Feature flag operation descriptor for batch operations
990
+ *
991
+ * @example
992
+ * ```typescript
993
+ * const operations: FeatureFlagOperation[] = [
994
+ * { type: 'set', key: 'feature-a', value: true },
995
+ * { type: 'set', key: 'feature-b', value: 'variant-1' },
996
+ * { type: 'remove', key: 'old-feature' },
997
+ * { type: 'get', key: 'current-feature' }
998
+ * ];
999
+ *
1000
+ * const results = await batchFeatureFlagOperations(operations);
1001
+ * ```
1002
+ */
1003
+ export interface FeatureFlagOperation<FeatureFlagKey extends string> {
1004
+ /** Operation type */
1005
+ type: 'set' | 'remove' | 'get';
1006
+ /** Flag key */
1007
+ key: FeatureFlagKey;
1008
+ /** Value for set operations */
1009
+ value?: FeatureFlagValue;
1010
+ }
1011
+ /**
1012
+ * Performance metrics for feature flag operations
1013
+ *
1014
+ * @example
1015
+ * ```typescript
1016
+ * const metrics: FeatureFlagPerformanceMetrics = {
1017
+ * avg: 15.5, // Average response time in ms
1018
+ * min: 8.2, // Fastest response
1019
+ * max: 45.1, // Slowest response
1020
+ * total: 1000 // Total operations measured
1021
+ * };
1022
+ *
1023
+ * console.log(`Average evaluation time: ${metrics.avg}ms`);
1024
+ * ```
1025
+ */
1026
+ export interface FeatureFlagPerformanceMetrics {
1027
+ /** Average operation time (ms) */
1028
+ avg: number;
1029
+ /** Minimum operation time (ms) */
1030
+ min: number;
1031
+ /** Maximum operation time (ms) */
1032
+ max: number;
1033
+ /** Total operations measured */
1034
+ total: number;
1035
+ }
1036
+ export interface FeatureFlagLoadTestResult {
1037
+ duration: number;
1038
+ errors: Error[];
1039
+ }
1040
+ export interface ControllableProvider<FeatureFlagKey extends string> {
1041
+ provider: IFeatureFlagProvider<FeatureFlagKey>;
1042
+ control: {
1043
+ resolveMethod: (method: string) => void;
1044
+ rejectMethod: (method: string, error: Error) => void;
1045
+ resolveAll: () => void;
1046
+ rejectAll: (error: Error) => void;
1047
+ reset: () => void;
1048
+ };
1049
+ }
1050
+ export interface SubscriptionFeatureFlagTracker<FeatureFlagKey extends string> {
1051
+ track: (provider: IFeatureFlagProvider<FeatureFlagKey>, id?: string) => {
1052
+ id: string;
1053
+ callback: Vitest.Mock;
1054
+ unsubscribe: () => void;
1055
+ };
1056
+ unsubscribe: (id: string) => void;
1057
+ unsubscribeAll: () => void;
1058
+ getCallCount: (id: string) => number;
1059
+ getLastCall: (id: string) => unknown;
1060
+ reset: () => void;
1061
+ }
1062
+ export interface EvaluationAssertions {
1063
+ hasValue: (expected: unknown) => void;
1064
+ hasReason: (expected: string) => void;
1065
+ hasSource: (expected: string) => void;
1066
+ hasRuleId: (expected: string) => void;
1067
+ wasEvaluatedRecently: (maxAgeMs?: number) => void;
1068
+ }
1069
+ export interface TestFeatureFlagProviderProps<FeatureFlagKey extends string> {
1070
+ provider: IFeatureFlagProvider<FeatureFlagKey>;
1071
+ children: React.ReactNode;
1072
+ context?: React.Context<FeatureFlagContextValue<FeatureFlagKey> | null>;
1073
+ }
1074
+ export interface CreateProviderForTestOptions<FeatureFlagKey extends string> {
1075
+ provider?: IFeatureFlagProvider<FeatureFlagKey>;
1076
+ config?: Partial<FeatureFlagConfig<FeatureFlagKey>>;
1077
+ flags?: Record<string, FeatureFlagValue>;
1078
+ features?: Record<FeatureFlagKey, FeatureFlagValue>;
1079
+ ProviderClass?: new (config: FeatureFlagConfig<FeatureFlagKey>, features: Record<FeatureFlagKey, FeatureFlagValue>) => IFeatureFlagProvider<FeatureFlagKey>;
1080
+ }
1081
+ export interface SetupFeatureFlagTestOptions<FeatureFlagKey extends string> {
1082
+ provider?: IFeatureFlagProvider<FeatureFlagKey>;
1083
+ config?: Partial<FeatureFlagConfig<FeatureFlagKey>>;
1084
+ flags?: Record<string, FeatureFlagValue>;
1085
+ setupBeforeEach?: boolean;
1086
+ autoInit: boolean;
1087
+ context?: React.Context<FeatureFlagContextValue<FeatureFlagKey> | null>;
1088
+ ProviderClass?: new (config: FeatureFlagConfig<FeatureFlagKey>, features: Record<FeatureFlagKey, FeatureFlagValue>) => IFeatureFlagProvider<FeatureFlagKey>;
1089
+ features?: Record<FeatureFlagKey, FeatureFlagValue>;
1090
+ }
1091
+ export interface PercentageRolloutScenario<FeatureFlagKey extends string> {
1092
+ rule: FeatureFlagRule<FeatureFlagKey>;
1093
+ users: string[];
1094
+ expectedEnabled: number;
1095
+ evaluate: (userId: string) => boolean;
1096
+ }
1097
+ export interface TimeBasedRolloutScenario<FeatureFlagKey extends string> {
1098
+ rule: FeatureFlagRule<FeatureFlagKey>;
1099
+ isActive: (date?: Date) => boolean;
1100
+ }
1101
+ export interface TargetedUsersScenario<FeatureFlagKey extends string> {
1102
+ rule: FeatureFlagRule<FeatureFlagKey>;
1103
+ isTargeted: (userId: string) => boolean;
1104
+ }
1105
+ export interface ABTestScenario<FeatureFlagKey extends string> {
1106
+ rules: FeatureFlagRule<FeatureFlagKey>[];
1107
+ variants: Record<string, FeatureFlagValue>;
1108
+ distribution: Record<string, number>;
1109
+ assignVariant: (userId: string) => string;
1110
+ }
1111
+ export interface ComplexRulesScenario<FeatureFlagKey extends string> {
1112
+ rules: FeatureFlagRule<FeatureFlagKey>[];
1113
+ evaluate: (context: FeatureFlagContext) => FeatureFlagEvaluation<FeatureFlagKey>;
1114
+ }
1115
+ export interface MockFeatureFlagProviderWithState<FeatureFlagKey extends string> extends IFeatureFlagProvider<FeatureFlagKey> {
1116
+ _mockState: {
1117
+ flags: Map<FeatureFlagKey, FeatureFlag<FeatureFlagKey>>;
1118
+ overrides: Map<FeatureFlagKey, FeatureFlagValue>;
1119
+ subscribers: Set<(flags: FeatureFlag<FeatureFlagKey>[]) => void>;
1120
+ };
1121
+ }
1122
+ export interface TestFeatureFlagContextValue<FeatureFlagKey extends string> {
1123
+ provider: IFeatureFlagProvider<FeatureFlagKey>;
1124
+ isInitialized: boolean;
1125
+ isLoading: boolean;
1126
+ error: Error | null;
1127
+ lastUpdated: Date;
1128
+ refresh: () => Promise<void>;
1129
+ }
1130
+ export interface WaitForFlagValueOptions {
1131
+ context?: FeatureFlagContext;
1132
+ timeout?: number;
1133
+ }