@replanejs/test-suite 0.8.20 → 0.9.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["resolve!: (value: T) => void","reject!: (reason?: unknown) => void","condition: () => boolean | Promise<boolean>","options: WaitForOptions","value: T | undefined","v: T","values: T[]","listeners: Array<() => void>","value: T","count: number","predicate: (value: T) => boolean","ms: number","request: {\n edgeApiBaseUrl: string;\n sdkKey: string;\n}","value: T","admin: ReplaneAdmin","workspaceId: string","projectId: string","environmentId: string","sdkKey: string","options: TestSuiteOptions","clientOptions?: {\n context?: ReplaneContext;\n defaults?: Partial<T>;\n required?: (keyof T)[] | Partial<T>;\n }","name: string","value: ConfigValue","configOptions?: {\n description?: string;\n overrides?: Override[];\n }","ctx: TestContext","activeClients: ReplaneClient<Record<string, unknown>>[]","client: ReplaneClient<T>"],"sources":["../src/utils.ts","../src/test-suite.ts"],"sourcesContent":["/**\n * Test utilities for waiting with early resolution\n */\n\nexport interface Deferred<T> {\n promise: Promise<T>;\n resolve: (value: T) => void;\n reject: (reason?: unknown) => void;\n}\n\n/**\n * Creates a deferred promise that can be resolved/rejected externally\n */\nexport function createDeferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void;\n let reject!: (reason?: unknown) => void;\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { promise, resolve, reject };\n}\n\n/**\n * Options for waitFor utility\n */\nexport interface WaitForOptions {\n /** Timeout in milliseconds (default: 5000) */\n timeout?: number;\n /** Custom error message on timeout */\n timeoutMessage?: string;\n}\n\n/**\n * Waits for a condition to be met or times out.\n * Returns immediately when condition is satisfied.\n *\n * @example\n * ```ts\n * let value: string | null = null;\n * client.subscribe(\"config\", (v) => { value = v; });\n *\n * await waitFor(() => value !== null, { timeout: 2000 });\n * expect(value).toBe(\"expected\");\n * ```\n */\nexport async function waitFor(\n condition: () => boolean | Promise<boolean>,\n options: WaitForOptions = {}\n): Promise<void> {\n const { timeout = 5000, timeoutMessage = \"waitFor timed out\" } = options;\n\n const startTime = Date.now();\n\n while (true) {\n const result = await condition();\n if (result) return;\n\n if (Date.now() - startTime >= timeout) {\n throw new Error(timeoutMessage);\n }\n\n // Yield to event loop, check again soon\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n}\n\n/**\n * A signal that can be awaited and triggered.\n * Useful for waiting for async events in tests.\n *\n * @example\n * ```ts\n * const signal = createSignal<string>();\n *\n * client.subscribe(\"config\", (value) => {\n * signal.trigger(value);\n * });\n *\n * const value = await signal.wait({ timeout: 2000 });\n * expect(value).toBe(\"expected\");\n * ```\n */\nexport interface Signal<T> {\n /** Wait for the signal to be triggered */\n wait(options?: WaitForOptions): Promise<T>;\n /** Trigger the signal with a value */\n trigger(value: T): void;\n /** Check if signal has been triggered */\n isTriggered(): boolean;\n /** Reset the signal to untriggered state */\n reset(): void;\n /** Get the triggered value (undefined if not triggered) */\n getValue(): T | undefined;\n}\n\nexport function createSignal<T = void>(): Signal<T> {\n let deferred = createDeferred<T>();\n let triggered = false;\n let value: T | undefined;\n\n return {\n wait(options: WaitForOptions = {}) {\n const { timeout = 5000, timeoutMessage = \"Signal wait timed out\" } = options;\n\n return Promise.race([\n deferred.promise,\n new Promise<T>((_, reject) => setTimeout(() => reject(new Error(timeoutMessage)), timeout)),\n ]);\n },\n\n trigger(v: T) {\n if (!triggered) {\n triggered = true;\n value = v;\n deferred.resolve(v);\n }\n },\n\n isTriggered() {\n return triggered;\n },\n\n reset() {\n triggered = false;\n value = undefined;\n deferred = createDeferred<T>();\n },\n\n getValue() {\n return value;\n },\n };\n}\n\n/**\n * A collector that accumulates values and can wait for a specific count.\n * Useful for collecting multiple updates in tests.\n *\n * @example\n * ```ts\n * const collector = createCollector<string>();\n *\n * client.subscribe(\"config\", (value) => {\n * collector.push(value);\n * });\n *\n * // Wait for 3 updates\n * const values = await collector.waitForCount(3, { timeout: 5000 });\n * expect(values).toEqual([\"v1\", \"v2\", \"v3\"]);\n * ```\n */\nexport interface Collector<T> {\n /** Push a value to the collector */\n push(value: T): void;\n /** Get all collected values */\n getValues(): T[];\n /** Get the count of collected values */\n count(): number;\n /** Wait for at least N values to be collected */\n waitForCount(count: number, options?: WaitForOptions): Promise<T[]>;\n /** Wait for a value matching the predicate */\n waitFor(predicate: (value: T) => boolean, options?: WaitForOptions): Promise<T>;\n /** Clear all collected values */\n clear(): void;\n}\n\nexport function createCollector<T>(): Collector<T> {\n const values: T[] = [];\n const listeners: Array<() => void> = [];\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n return {\n push(value: T) {\n values.push(value);\n notify();\n },\n\n getValues() {\n return [...values];\n },\n\n count() {\n return values.length;\n },\n\n async waitForCount(count: number, options: WaitForOptions = {}) {\n const { timeout = 5000, timeoutMessage = `Collector timed out waiting for ${count} values` } =\n options;\n\n if (values.length >= count) {\n return [...values];\n }\n\n return new Promise<T[]>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n const idx = listeners.indexOf(listener);\n if (idx !== -1) listeners.splice(idx, 1);\n reject(new Error(timeoutMessage));\n }, timeout);\n\n const listener = () => {\n if (values.length >= count) {\n clearTimeout(timeoutId);\n const idx = listeners.indexOf(listener);\n if (idx !== -1) listeners.splice(idx, 1);\n resolve([...values]);\n }\n };\n\n listeners.push(listener);\n });\n },\n\n async waitFor(predicate: (value: T) => boolean, options: WaitForOptions = {}) {\n const { timeout = 5000, timeoutMessage = \"Collector timed out waiting for matching value\" } =\n options;\n\n // Check existing values first\n for (const v of values) {\n if (predicate(v)) return v;\n }\n\n return new Promise<T>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n const idx = listeners.indexOf(listener);\n if (idx !== -1) listeners.splice(idx, 1);\n reject(new Error(timeoutMessage));\n }, timeout);\n\n const listener = () => {\n // Check the latest value\n const latest = values[values.length - 1];\n if (latest !== undefined && predicate(latest)) {\n clearTimeout(timeoutId);\n const idx = listeners.indexOf(listener);\n if (idx !== -1) listeners.splice(idx, 1);\n resolve(latest);\n }\n };\n\n listeners.push(listener);\n });\n },\n\n clear() {\n values.length = 0;\n },\n };\n}\n\n/**\n * Delay for a specified time (use sparingly in tests)\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Generate a unique test identifier\n */\nexport function uniqueId(prefix = \"test\"): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * Sync the edge replica with the database.\n * Requires TESTING_MODE=true on the server.\n *\n * This is useful in tests to ensure the edge replica has\n * received all config changes before making assertions.\n *\n * @param request - The request object containing the edge API base URL and admin API key\n * @param request.edgeApiBaseUrl - The base URL of the edge API (e.g., \"http://localhost:8080\")\n * @param request.adminApiKey - The admin API key\n */\nexport async function syncReplica(request: {\n edgeApiBaseUrl: string;\n sdkKey: string;\n}): Promise<void> {\n const { edgeApiBaseUrl, sdkKey } = request;\n\n const response = await fetch(`${edgeApiBaseUrl}/api/sdk/v1/testing/sync`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${sdkKey}`,\n },\n });\n\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Failed to sync replica: ${response.status} ${body}`);\n }\n}\n","/**\n * Replane E2E Test Suite\n *\n * Comprehensive test suite for testing @replanejs/sdk with real @replanejs/admin API\n *\n * NOTE: This test suite is designed for multi-server setups where admin API and edge API\n * may be on different servers. Config changes are not immediate and require waiting for\n * replication to complete.\n */\n\nimport { describe, it, beforeAll, afterAll, afterEach, expect } from \"vitest\";\nimport { ReplaneAdmin, type ConfigValue, type Override } from \"@replanejs/admin\";\nimport { createReplaneClient, ReplaneError, ReplaneErrorCode } from \"@replanejs/sdk\";\nimport type { ReplaneClient, ReplaneContext } from \"@replanejs/sdk\";\nimport type { TestSuiteOptions, TestContext } from \"./types\";\nimport { createSignal, createCollector, delay, uniqueId, syncReplica } from \"./utils\";\n\n/**\n * Helper to create a literal value for conditions.\n */\nfunction literal<T>(value: T) {\n return { type: \"literal\" as const, value };\n}\n\nconst silentLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/**\n * Creates a test context with helper methods\n */\nfunction createTestContext(\n admin: ReplaneAdmin,\n workspaceId: string,\n projectId: string,\n environmentId: string,\n sdkKey: string,\n options: TestSuiteOptions\n): TestContext {\n const defaultTimeout = options.defaultTimeout ?? 10000;\n\n function sync(): Promise<void> {\n return syncReplica({ edgeApiBaseUrl: options.edgeApiBaseUrl, sdkKey });\n }\n\n return {\n admin,\n workspaceId,\n projectId,\n environmentId,\n sdkKey,\n edgeApiBaseUrl: options.edgeApiBaseUrl,\n adminApiBaseUrl: options.adminApiBaseUrl,\n defaultTimeout,\n\n sync,\n\n async createClient<T extends object = Record<string, unknown>>(clientOptions?: {\n context?: ReplaneContext;\n defaults?: Partial<T>;\n required?: (keyof T)[] | Partial<T>;\n }): Promise<ReplaneClient<T>> {\n await sync();\n\n return createReplaneClient<T>({\n sdkKey,\n baseUrl: options.edgeApiBaseUrl,\n logger: options.debug ? console : silentLogger,\n initializationTimeoutMs: defaultTimeout,\n context: clientOptions?.context,\n defaults: clientOptions?.defaults as T | undefined,\n required: clientOptions?.required as (keyof T)[] | undefined,\n });\n },\n\n async createConfig(\n name: string,\n value: ConfigValue,\n configOptions?: {\n description?: string;\n overrides?: Override[];\n }\n ): Promise<void> {\n await admin.configs.create({\n projectId,\n name,\n description: configOptions?.description ?? \"\",\n editors: [],\n maintainers: [],\n base: {\n value,\n schema: null,\n overrides: configOptions?.overrides ?? [],\n },\n variants: [],\n });\n await sync();\n },\n\n async updateConfig(\n name: string,\n value: ConfigValue,\n configOptions?: {\n description?: string;\n overrides?: Override[];\n }\n ): Promise<void> {\n await admin.configs.update({\n projectId,\n configName: name,\n description: configOptions?.description ?? \"\",\n editors: [],\n base: {\n value,\n schema: null,\n overrides: configOptions?.overrides ?? [],\n },\n variants: [],\n });\n await sync();\n },\n\n async deleteConfig(name: string): Promise<void> {\n await admin.configs.delete({ projectId, configName: name });\n await sync();\n },\n };\n}\n\n/**\n * Main test suite function\n *\n * @example\n * ```ts\n * import { testSuite } from \"@replanejs/test-suite\";\n *\n * testSuite({\n * superadminKey: process.env.SUPERADMIN_KEY!,\n * adminApiBaseUrl: \"http://localhost:8080\",\n * edgeApiBaseUrl: \"http://localhost:8080\",\n * });\n * ```\n */\nexport function testSuite(options: TestSuiteOptions): void {\n const { superadminKey, adminApiBaseUrl, edgeApiBaseUrl } = options;\n const defaultTimeout = options.defaultTimeout ?? 10000;\n\n describe(\"Replane E2E Test Suite\", () => {\n let admin: ReplaneAdmin;\n let workspaceId: string;\n let projectId: string;\n let environmentId: string;\n let sdkKey: string;\n let ctx: TestContext;\n\n // Track clients for cleanup\n const activeClients: ReplaneClient<Record<string, unknown>>[] = [];\n\n beforeAll(async () => {\n // Create admin client with superadmin key\n admin = new ReplaneAdmin({\n apiKey: superadminKey,\n baseUrl: adminApiBaseUrl,\n });\n\n // Create a unique workspace for this test run\n const workspaceName = uniqueId(\"e2e-workspace\");\n const workspaceRes = await admin.workspaces.create({ name: workspaceName });\n workspaceId = workspaceRes.id;\n\n // Create a project in the workspace\n const projectName = uniqueId(\"e2e-project\");\n const projectRes = await admin.projects.create({\n workspaceId,\n name: projectName,\n description: \"E2E test project\",\n });\n projectId = projectRes.id;\n\n // Get environments (use production)\n const envRes = await admin.environments.list({ projectId });\n const prodEnv =\n envRes.environments.find((e) => e.name === \"Production\") ?? envRes.environments[0];\n if (!prodEnv) {\n throw new Error(\"No environments found\");\n }\n environmentId = prodEnv.id;\n\n // Create SDK key\n const sdkKeyRes = await admin.sdkKeys.create({\n projectId,\n name: uniqueId(\"e2e-sdk-key\"),\n environmentId,\n });\n sdkKey = sdkKeyRes.key;\n\n await syncReplica({ edgeApiBaseUrl, sdkKey });\n\n // Create test context\n ctx = createTestContext(admin, workspaceId, projectId, environmentId, sdkKey, options);\n });\n\n afterAll(async () => {\n // Close all active clients\n for (const client of activeClients) {\n try {\n client.close();\n } catch {\n // Ignore errors during cleanup\n }\n }\n activeClients.length = 0;\n\n // Clean up: delete workspace (cascades to project, configs, keys)\n if (workspaceId) {\n await admin.workspaces.delete({ workspaceId });\n }\n });\n\n // Helper to track clients for cleanup\n const trackClient = <T extends object>(client: ReplaneClient<T>): ReplaneClient<T> => {\n activeClients.push(client as ReplaneClient<Record<string, unknown>>);\n return client;\n };\n\n afterEach(async () => {\n const configs = await admin.configs.list({ projectId });\n for (const config of configs.configs) {\n await admin.configs.delete({ projectId, configName: config.name });\n }\n await syncReplica({ edgeApiBaseUrl, sdkKey });\n });\n\n // ==================== CONNECTION TESTS ====================\n\n describe(\"SDK Connection\", () => {\n it(\"should connect and receive initial configs\", async () => {\n // Create config via admin API\n await ctx.createConfig(\"test-config\", \"initial-value\");\n\n // Create client - sync ensures configs are available\n const client = trackClient(\n await ctx.createClient<{ \"test-config\": string }>({\n required: [\"test-config\"],\n })\n );\n\n const value = client.get(\"test-config\");\n expect(value).toBe(\"initial-value\");\n\n client.close();\n });\n\n it(\"should handle empty project (no configs)\", async () => {\n // Create a new project with no configs\n const emptyProjectRes = await admin.projects.create({\n workspaceId,\n name: uniqueId(\"empty-project\"),\n description: \"Empty project for testing\",\n });\n const emptyEnvRes = await admin.environments.list({ projectId: emptyProjectRes.id });\n const emptyEnv = emptyEnvRes.environments[0];\n const emptySdkKeyRes = await admin.sdkKeys.create({\n projectId: emptyProjectRes.id,\n name: uniqueId(\"empty-sdk-key\"),\n environmentId: emptyEnv.id,\n });\n\n // Wait for SDK key to sync\n await syncReplica({ edgeApiBaseUrl, sdkKey });\n\n const client = trackClient(\n await createReplaneClient({\n sdkKey: emptySdkKeyRes.key,\n baseUrl: edgeApiBaseUrl,\n logger: silentLogger,\n initializationTimeoutMs: defaultTimeout,\n })\n );\n\n // Should not throw, but get() with no default should throw\n expect(() => client.get(\"nonexistent\")).toThrow();\n\n client.close();\n\n // Cleanup\n await admin.projects.delete({ projectId: emptyProjectRes.id });\n });\n\n it(\"should use default values when config not found\", async () => {\n const client = trackClient(\n await ctx.createClient({\n defaults: { \"missing-config\": \"default-value\" },\n })\n );\n\n const value = client.get(\"missing-config\");\n expect(value).toBe(\"default-value\");\n\n client.close();\n });\n\n it(\"should throw when required config is missing\", { timeout: 15000 }, async () => {\n await expect(\n ctx.createClient({\n required: [\"definitely-missing-config\"],\n })\n ).rejects.toThrow();\n });\n });\n\n // ==================== GET CONFIG TESTS ====================\n\n describe(\"Get Config\", () => {\n it(\"should get string config\", async () => {\n await ctx.createConfig(\"string-config\", \"hello\");\n\n const client = trackClient(\n await ctx.createClient<{ \"string-config\": string }>({ required: [\"string-config\"] })\n );\n\n expect(client.get(\"string-config\")).toBe(\"hello\");\n client.close();\n });\n\n it(\"should get number config\", async () => {\n await ctx.createConfig(\"number-config\", 42);\n\n const client = trackClient(\n await ctx.createClient<{ \"number-config\": number }>({ required: [\"number-config\"] })\n );\n\n expect(client.get(\"number-config\")).toBe(42);\n client.close();\n });\n\n it(\"should get boolean config\", async () => {\n await ctx.createConfig(\"boolean-config\", true);\n\n const client = trackClient(\n await ctx.createClient<{ \"boolean-config\": boolean }>({ required: [\"boolean-config\"] })\n );\n\n expect(client.get(\"boolean-config\")).toBe(true);\n client.close();\n });\n\n it(\"should get object config\", async () => {\n const objValue = { nested: { value: \"deep\" } };\n await ctx.createConfig(\"object-config\", objValue);\n\n const client = trackClient(\n await ctx.createClient<{ \"object-config\": typeof objValue }>({\n required: [\"object-config\"],\n })\n );\n\n expect(client.get(\"object-config\")).toEqual(objValue);\n client.close();\n });\n\n it(\"should get array config\", async () => {\n const arrValue = [1, 2, 3];\n await ctx.createConfig(\"array-config\", arrValue);\n\n const client = trackClient(\n await ctx.createClient<{ \"array-config\": number[] }>({ required: [\"array-config\"] })\n );\n\n expect(client.get(\"array-config\")).toEqual(arrValue);\n client.close();\n });\n\n it(\"should get null config\", async () => {\n await ctx.createConfig(\"null-config\", null);\n\n const client = trackClient(\n await ctx.createClient<{ \"null-config\": null }>({ required: [\"null-config\"] })\n );\n\n expect(client.get(\"null-config\")).toBe(null);\n client.close();\n });\n\n it(\"should return default value when config not found\", async () => {\n const client = trackClient(await ctx.createClient());\n const value = client.get(\"nonexistent\", { default: \"fallback\" });\n expect(value).toBe(\"fallback\");\n client.close();\n });\n\n it(\"should throw ReplaneError when config not found and no default\", async () => {\n const client = trackClient(await ctx.createClient());\n try {\n client.get(\"nonexistent\");\n expect.fail(\"Should have thrown\");\n } catch (error) {\n expect(error).toBeInstanceOf(ReplaneError);\n expect((error as ReplaneError).code).toBe(ReplaneErrorCode.NotFound);\n }\n client.close();\n });\n });\n\n // ==================== REAL-TIME UPDATES TESTS ====================\n\n describe(\"Real-time Updates\", () => {\n it(\"should receive config updates via subscription\", async () => {\n await ctx.createConfig(\"live-config\", \"initial\");\n\n const client = trackClient(\n await ctx.createClient<{ \"live-config\": string }>({ required: [\"live-config\"] })\n );\n\n expect(client.get(\"live-config\")).toBe(\"initial\");\n\n // Set up signal for next update\n const updateSignal = createSignal<string>();\n client.subscribe(\"live-config\", (config) => {\n if (config.value !== \"initial\") {\n updateSignal.trigger(config.value as string);\n }\n });\n\n // Update config\n await ctx.updateConfig(\"live-config\", \"updated\");\n\n // Wait for update (with timeout)\n const newValue = await updateSignal.wait({ timeout: defaultTimeout });\n expect(newValue).toBe(\"updated\");\n\n // Verify get() returns new value\n expect(client.get(\"live-config\")).toBe(\"updated\");\n\n client.close();\n });\n\n it(\"should receive multiple updates in order\", async () => {\n await ctx.createConfig(\"multi-update-config\", 0);\n\n const client = trackClient(\n await ctx.createClient<{ \"multi-update-config\": number }>({\n required: [\"multi-update-config\"],\n })\n );\n\n expect(client.get(\"multi-update-config\")).toBe(0);\n\n const collector = createCollector<number>();\n client.subscribe(\"multi-update-config\", (config) => {\n const val = config.value as number;\n if (val > 0) {\n collector.push(val);\n }\n });\n\n // Send multiple updates with small delays to ensure ordering\n await ctx.updateConfig(\"multi-update-config\", 1);\n await delay(100);\n await ctx.updateConfig(\"multi-update-config\", 2);\n await delay(100);\n await ctx.updateConfig(\"multi-update-config\", 3);\n\n // Wait for all updates\n const values = await collector.waitForCount(3, { timeout: defaultTimeout });\n expect(values).toEqual([1, 2, 3]);\n\n client.close();\n });\n\n it(\"should handle rapid updates\", async () => {\n await ctx.createConfig(\"rapid-config\", 0);\n\n const client = trackClient(\n await ctx.createClient<{ \"rapid-config\": number }>({ required: [\"rapid-config\"] })\n );\n\n expect(client.get(\"rapid-config\")).toBe(0);\n\n const collector = createCollector<number>();\n client.subscribe(\"rapid-config\", (config) => {\n collector.push(config.value as number);\n });\n\n // Send rapid updates\n const updateCount = 10;\n for (let i = 1; i <= updateCount; i++) {\n await ctx.updateConfig(\"rapid-config\", i);\n }\n\n // Wait for final value (may not get all intermediate values due to batching)\n await collector.waitFor((v) => v === updateCount, { timeout: defaultTimeout });\n\n // Final value should be correct\n expect(client.get(\"rapid-config\")).toBe(updateCount);\n\n client.close();\n });\n\n it(\"should call global subscription for any config change\", async () => {\n await ctx.createConfig(\"config-a\", \"a\");\n await ctx.createConfig(\"config-b\", \"b\");\n\n const client = trackClient(\n await ctx.createClient<{ \"config-a\": string; \"config-b\": string }>({\n required: [\"config-a\", \"config-b\"],\n })\n );\n\n expect(client.get(\"config-a\")).toBe(\"a\");\n expect(client.get(\"config-b\")).toBe(\"b\");\n\n const collector = createCollector<{ name: unknown; value: unknown }>();\n client.subscribe((config) => {\n // Only collect updates (not initial values)\n if (config.value === \"a-updated\" || config.value === \"b-updated\") {\n collector.push({ name: config.name, value: config.value });\n }\n });\n\n // Update both configs\n await ctx.updateConfig(\"config-a\", \"a-updated\");\n await ctx.updateConfig(\"config-b\", \"b-updated\");\n\n // Wait for both updates\n await collector.waitForCount(2, { timeout: defaultTimeout });\n\n const values = collector.getValues();\n const aUpdate = values.find((v) => v.name === \"config-a\");\n const bUpdate = values.find((v) => v.name === \"config-b\");\n\n expect(aUpdate?.value).toBe(\"a-updated\");\n expect(bUpdate?.value).toBe(\"b-updated\");\n\n client.close();\n });\n\n it(\"should allow unsubscribing\", async () => {\n await ctx.createConfig(\"unsub-config\", \"initial\");\n\n const client = trackClient(\n await ctx.createClient<{ \"unsub-config\": string }>({ required: [\"unsub-config\"] })\n );\n\n expect(client.get(\"unsub-config\")).toBe(\"initial\");\n\n const collector = createCollector<string>();\n const unsubscribe = client.subscribe(\"unsub-config\", (config) => {\n if (config.value !== \"initial\") {\n collector.push(config.value as string);\n }\n });\n\n // First update should be received\n await ctx.updateConfig(\"unsub-config\", \"update-1\");\n await collector.waitForCount(1, { timeout: defaultTimeout });\n\n // Unsubscribe\n unsubscribe();\n\n // Second update should NOT be received\n await ctx.updateConfig(\"unsub-config\", \"update-2\");\n await delay(2000); // Give time for potential update to propagate\n\n // Should only have 1 update\n expect(collector.count()).toBe(1);\n\n client.close();\n });\n });\n\n // ==================== OVERRIDE TESTS ====================\n\n describe(\"Override Evaluation\", () => {\n it(\"should evaluate equals condition\", async () => {\n await ctx.createConfig(\"env-config\", \"default\", {\n overrides: [\n {\n name: \"prod-override\",\n conditions: [{ operator: \"equals\", property: \"env\", value: literal(\"production\") }],\n value: \"production-value\",\n },\n ],\n });\n\n // Without context - should get default\n const client1 = trackClient(\n await ctx.createClient<{ \"env-config\": string }>({ required: [\"env-config\"] })\n );\n expect(client1.get(\"env-config\")).toBe(\"default\");\n client1.close();\n\n // With matching context\n const client2 = trackClient(\n await ctx.createClient<{ \"env-config\": string }>({\n context: { env: \"production\" },\n required: [\"env-config\"],\n })\n );\n expect(client2.get(\"env-config\")).toBe(\"production-value\");\n client2.close();\n\n // With non-matching context\n const client3 = trackClient(\n await ctx.createClient<{ \"env-config\": string }>({\n context: { env: \"staging\" },\n required: [\"env-config\"],\n })\n );\n expect(client3.get(\"env-config\")).toBe(\"default\");\n client3.close();\n });\n\n it(\"should evaluate in condition\", async () => {\n await ctx.createConfig(\"region-config\", \"default\", {\n overrides: [\n {\n name: \"western-override\",\n conditions: [{ operator: \"in\", property: \"region\", value: literal([\"us\", \"eu\"]) }],\n value: \"western\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"region-config\": string }>({\n context: { region: \"us\" },\n required: [\"region-config\"],\n })\n );\n expect(client1.get(\"region-config\")).toBe(\"western\");\n client1.close();\n\n const client2 = trackClient(\n await ctx.createClient<{ \"region-config\": string }>({\n context: { region: \"eu\" },\n required: [\"region-config\"],\n })\n );\n expect(client2.get(\"region-config\")).toBe(\"western\");\n client2.close();\n\n const client3 = trackClient(\n await ctx.createClient<{ \"region-config\": string }>({\n context: { region: \"asia\" },\n required: [\"region-config\"],\n })\n );\n expect(client3.get(\"region-config\")).toBe(\"default\");\n client3.close();\n });\n\n it(\"should evaluate not_in condition\", async () => {\n await ctx.createConfig(\"allow-config\", \"allowed\", {\n overrides: [\n {\n name: \"not-blocked-override\",\n conditions: [\n {\n operator: \"not_in\",\n property: \"country\",\n value: literal([\"blocked1\", \"blocked2\"]),\n },\n ],\n value: \"not-blocked\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"allow-config\": string }>({\n context: { country: \"blocked1\" },\n required: [\"allow-config\"],\n })\n );\n expect(client1.get(\"allow-config\")).toBe(\"allowed\");\n client1.close();\n\n const client2 = trackClient(\n await ctx.createClient<{ \"allow-config\": string }>({\n context: { country: \"normal\" },\n required: [\"allow-config\"],\n })\n );\n expect(client2.get(\"allow-config\")).toBe(\"not-blocked\");\n client2.close();\n });\n\n it(\"should evaluate numeric comparison conditions\", async () => {\n await ctx.createConfig(\"tier-config\", \"free\", {\n overrides: [\n {\n name: \"premium-override\",\n conditions: [\n { operator: \"greater_than_or_equal\", property: \"level\", value: literal(10) },\n ],\n value: \"premium\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"tier-config\": string }>({\n context: { level: 5 },\n required: [\"tier-config\"],\n })\n );\n expect(client1.get(\"tier-config\")).toBe(\"free\");\n client1.close();\n\n const client2 = trackClient(\n await ctx.createClient<{ \"tier-config\": string }>({\n context: { level: 10 },\n required: [\"tier-config\"],\n })\n );\n expect(client2.get(\"tier-config\")).toBe(\"premium\");\n client2.close();\n\n const client3 = trackClient(\n await ctx.createClient<{ \"tier-config\": string }>({\n context: { level: 15 },\n required: [\"tier-config\"],\n })\n );\n expect(client3.get(\"tier-config\")).toBe(\"premium\");\n client3.close();\n });\n\n it(\"should evaluate and condition\", async () => {\n await ctx.createConfig(\"combo-config\", \"default\", {\n overrides: [\n {\n name: \"combo-override\",\n conditions: [\n {\n operator: \"and\",\n conditions: [\n { operator: \"equals\", property: \"plan\", value: literal(\"enterprise\") },\n { operator: \"equals\", property: \"verified\", value: literal(true) },\n ],\n },\n ],\n value: \"enterprise-verified\",\n },\n ],\n });\n\n // Both conditions must match\n const client1 = trackClient(\n await ctx.createClient<{ \"combo-config\": string }>({\n context: { plan: \"enterprise\", verified: true },\n required: [\"combo-config\"],\n })\n );\n expect(client1.get(\"combo-config\")).toBe(\"enterprise-verified\");\n client1.close();\n\n // Only one matches\n const client2 = trackClient(\n await ctx.createClient<{ \"combo-config\": string }>({\n context: { plan: \"enterprise\", verified: false },\n required: [\"combo-config\"],\n })\n );\n expect(client2.get(\"combo-config\")).toBe(\"default\");\n client2.close();\n });\n\n it(\"should evaluate or condition\", async () => {\n await ctx.createConfig(\"either-config\", \"default\", {\n overrides: [\n {\n name: \"privileged-override\",\n conditions: [\n {\n operator: \"or\",\n conditions: [\n { operator: \"equals\", property: \"role\", value: literal(\"admin\") },\n { operator: \"equals\", property: \"role\", value: literal(\"superadmin\") },\n ],\n },\n ],\n value: \"privileged\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"either-config\": string }>({\n context: { role: \"admin\" },\n required: [\"either-config\"],\n })\n );\n expect(client1.get(\"either-config\")).toBe(\"privileged\");\n client1.close();\n\n const client2 = trackClient(\n await ctx.createClient<{ \"either-config\": string }>({\n context: { role: \"superadmin\" },\n required: [\"either-config\"],\n })\n );\n expect(client2.get(\"either-config\")).toBe(\"privileged\");\n client2.close();\n\n const client3 = trackClient(\n await ctx.createClient<{ \"either-config\": string }>({\n context: { role: \"user\" },\n required: [\"either-config\"],\n })\n );\n expect(client3.get(\"either-config\")).toBe(\"default\");\n client3.close();\n });\n\n it(\"should allow per-request context override\", async () => {\n await ctx.createConfig(\"dynamic-config\", \"default\", {\n overrides: [\n {\n name: \"feature-override\",\n conditions: [{ operator: \"equals\", property: \"feature\", value: literal(\"enabled\") }],\n value: \"feature-on\",\n },\n ],\n });\n\n const client = trackClient(\n await ctx.createClient<{ \"dynamic-config\": string }>({ required: [\"dynamic-config\"] })\n );\n\n // Without context\n expect(client.get(\"dynamic-config\")).toBe(\"default\");\n\n // With per-request context\n expect(client.get(\"dynamic-config\", { context: { feature: \"enabled\" } })).toBe(\n \"feature-on\"\n );\n\n // Original still returns default\n expect(client.get(\"dynamic-config\")).toBe(\"default\");\n\n client.close();\n });\n\n it(\"should apply first matching override\", async () => {\n await ctx.createConfig(\"priority-config\", \"default\", {\n overrides: [\n {\n name: \"gold-override\",\n conditions: [{ operator: \"equals\", property: \"tier\", value: literal(\"gold\") }],\n value: \"gold-value\",\n },\n {\n name: \"silver-override\",\n conditions: [{ operator: \"equals\", property: \"tier\", value: literal(\"silver\") }],\n value: \"silver-value\",\n },\n {\n name: \"score-override\",\n conditions: [{ operator: \"greater_than\", property: \"score\", value: literal(0) }],\n value: \"has-score\",\n },\n ],\n });\n\n // First override matches\n const client = trackClient(\n await ctx.createClient<{ \"priority-config\": string }>({\n context: { tier: \"gold\", score: 100 },\n required: [\"priority-config\"],\n })\n );\n expect(client.get(\"priority-config\")).toBe(\"gold-value\");\n client.close();\n });\n });\n\n // ==================== SNAPSHOT TESTS ====================\n\n describe(\"Snapshot\", () => {\n it(\"should create snapshot with current configs\", async () => {\n await ctx.createConfig(\"snap-config-1\", \"value-1\");\n await ctx.createConfig(\"snap-config-2\", \"value-2\");\n\n const client = trackClient(\n await ctx.createClient<{ \"snap-config-1\": string; \"snap-config-2\": string }>({\n required: [\"snap-config-1\", \"snap-config-2\"],\n })\n );\n\n const snapshot = client.getSnapshot();\n\n expect(snapshot.configs).toMatchInlineSnapshot(`\n [\n {\n \"name\": \"snap-config-1\",\n \"overrides\": [],\n \"value\": \"value-1\",\n },\n {\n \"name\": \"snap-config-2\",\n \"overrides\": [],\n \"value\": \"value-2\",\n },\n ]\n `);\n expect(snapshot.configs.map((c) => c.name).sort()).toEqual([\n \"snap-config-1\",\n \"snap-config-2\",\n ]);\n\n client.close();\n });\n\n it(\"should include context in snapshot\", async () => {\n await ctx.createConfig(\"ctx-config\", \"value\");\n\n const client = trackClient(\n await ctx.createClient<{ \"ctx-config\": string }>({\n context: { userId: \"123\" },\n required: [\"ctx-config\"],\n })\n );\n\n const snapshot = client.getSnapshot();\n expect(snapshot.context).toEqual({ userId: \"123\" });\n\n client.close();\n });\n });\n\n // ==================== ERROR HANDLING TESTS ====================\n\n describe(\"Error Handling\", () => {\n it(\"should throw on invalid SDK key\", async () => {\n await expect(\n createReplaneClient({\n sdkKey: \"invalid-key\",\n baseUrl: edgeApiBaseUrl,\n logger: silentLogger,\n initializationTimeoutMs: 2000,\n })\n ).rejects.toThrow();\n });\n\n it(\"should handle closed client gracefully\", async () => {\n await ctx.createConfig(\"close-test\", \"value\");\n\n const client = trackClient(\n await ctx.createClient<{ \"close-test\": string }>({ required: [\"close-test\"] })\n );\n\n expect(client.get(\"close-test\")).toBe(\"value\");\n\n client.close();\n\n // After close, client should still return cached value (doesn't throw)\n // This verifies the client handles close gracefully\n const cachedValue = client.get(\"close-test\");\n expect(cachedValue).toBe(\"value\");\n });\n\n it(\"should timeout on unreachable server\", async () => {\n await expect(\n createReplaneClient({\n sdkKey: \"rp_test\",\n baseUrl: \"http://localhost:59999\", // Non-existent port\n logger: silentLogger,\n initializationTimeoutMs: 1000,\n })\n ).rejects.toThrow();\n });\n });\n\n // ==================== CONFIG LIFECYCLE TESTS ====================\n\n describe(\"Config Lifecycle\", () => {\n it(\"should handle config creation after client connects\", async () => {\n // Create client first with no configs\n const client = trackClient(\n await ctx.createClient({ defaults: { \"late-config\": \"waiting\" } })\n );\n\n // Set up signal to wait for the config\n const configSignal = createSignal<string>();\n client.subscribe(\"late-config\", (config) => {\n configSignal.trigger(config.value as string);\n });\n\n // Create config after connection\n await ctx.createConfig(\"late-config\", \"late-value\");\n\n // Wait for the config to appear via subscription\n const value = await configSignal.wait({ timeout: defaultTimeout });\n expect(value).toBe(\"late-value\");\n\n expect(client.get(\"late-config\")).toBe(\"late-value\");\n\n client.close();\n });\n\n it(\"should ignore config deletion on client\", async () => {\n await ctx.createConfig(\"delete-me\", \"exists\");\n\n const client = trackClient(\n await ctx.createClient<{ \"delete-me\": string }>({ required: [\"delete-me\"] })\n );\n\n expect(client.get(\"delete-me\")).toBe(\"exists\");\n\n // Delete config\n await ctx.deleteConfig(\"delete-me\");\n\n await delay(1000);\n\n expect(client.get(\"delete-me\")).toBe(\"exists\");\n\n client.close();\n });\n });\n\n // ==================== CONCURRENT CLIENTS TESTS ====================\n\n describe(\"Concurrent Clients\", () => {\n it(\"should handle multiple clients with same SDK key\", async () => {\n await ctx.createConfig(\"shared-config\", \"initial\");\n\n const client1 = trackClient(\n await ctx.createClient<{ \"shared-config\": string }>({ required: [\"shared-config\"] })\n );\n const client2 = trackClient(\n await ctx.createClient<{ \"shared-config\": string }>({ required: [\"shared-config\"] })\n );\n\n expect(client1.get(\"shared-config\")).toBe(\"initial\");\n expect(client2.get(\"shared-config\")).toBe(\"initial\");\n\n // Both should receive updates\n const signal1 = createSignal<string>();\n const signal2 = createSignal<string>();\n\n client1.subscribe(\"shared-config\", (c) => {\n if (c.value === \"updated\") signal1.trigger(c.value as string);\n });\n client2.subscribe(\"shared-config\", (c) => {\n if (c.value === \"updated\") signal2.trigger(c.value as string);\n });\n\n await ctx.updateConfig(\"shared-config\", \"updated\");\n\n const [v1, v2] = await Promise.all([\n signal1.wait({ timeout: defaultTimeout }),\n signal2.wait({ timeout: defaultTimeout }),\n ]);\n\n expect(v1).toBe(\"updated\");\n expect(v2).toBe(\"updated\");\n\n client1.close();\n client2.close();\n });\n\n it(\"should isolate context between clients\", async () => {\n await ctx.createConfig(\"context-config\", \"default\", {\n overrides: [\n {\n name: \"prod-override\",\n conditions: [{ operator: \"equals\", property: \"env\", value: literal(\"prod\") }],\n value: \"prod-value\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"context-config\": string }>({\n context: { env: \"prod\" },\n required: [\"context-config\"],\n })\n );\n const client2 = trackClient(\n await ctx.createClient<{ \"context-config\": string }>({\n context: { env: \"dev\" },\n required: [\"context-config\"],\n })\n );\n\n expect(client1.get(\"context-config\")).toBe(\"prod-value\");\n expect(client2.get(\"context-config\")).toBe(\"default\");\n\n client1.close();\n client2.close();\n });\n });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["resolve!: (value: T) => void","reject!: (reason?: unknown) => void","condition: () => boolean | Promise<boolean>","options: WaitForOptions","value: T | undefined","v: T","values: T[]","listeners: Array<() => void>","value: T","count: number","predicate: (value: T) => boolean","ms: number","request: {\n edgeApiBaseUrl: string;\n sdkKey: string;\n}","value: T","admin: ReplaneAdmin","workspaceId: string","projectId: string","environmentId: string","sdkKey: string","options: TestSuiteOptions","clientOptions?: {\n context?: ReplaneContext;\n defaults?: Partial<T>;\n }","name: string","value: ConfigValue","configOptions?: {\n description?: string;\n overrides?: Override[];\n }","ctx: TestContext","activeClients: Replane<Record<string, unknown>>[]","client: Replane<T>"],"sources":["../src/utils.ts","../src/test-suite.ts"],"sourcesContent":["/**\n * Test utilities for waiting with early resolution\n */\n\nexport interface Deferred<T> {\n promise: Promise<T>;\n resolve: (value: T) => void;\n reject: (reason?: unknown) => void;\n}\n\n/**\n * Creates a deferred promise that can be resolved/rejected externally\n */\nexport function createDeferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void;\n let reject!: (reason?: unknown) => void;\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { promise, resolve, reject };\n}\n\n/**\n * Options for waitFor utility\n */\nexport interface WaitForOptions {\n /** Timeout in milliseconds (default: 5000) */\n timeout?: number;\n /** Custom error message on timeout */\n timeoutMessage?: string;\n}\n\n/**\n * Waits for a condition to be met or times out.\n * Returns immediately when condition is satisfied.\n *\n * @example\n * ```ts\n * let value: string | null = null;\n * client.subscribe(\"config\", (v) => { value = v; });\n *\n * await waitFor(() => value !== null, { timeout: 2000 });\n * expect(value).toBe(\"expected\");\n * ```\n */\nexport async function waitFor(\n condition: () => boolean | Promise<boolean>,\n options: WaitForOptions = {}\n): Promise<void> {\n const { timeout = 5000, timeoutMessage = \"waitFor timed out\" } = options;\n\n const startTime = Date.now();\n\n while (true) {\n const result = await condition();\n if (result) return;\n\n if (Date.now() - startTime >= timeout) {\n throw new Error(timeoutMessage);\n }\n\n // Yield to event loop, check again soon\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n}\n\n/**\n * A signal that can be awaited and triggered.\n * Useful for waiting for async events in tests.\n *\n * @example\n * ```ts\n * const signal = createSignal<string>();\n *\n * client.subscribe(\"config\", (value) => {\n * signal.trigger(value);\n * });\n *\n * const value = await signal.wait({ timeout: 2000 });\n * expect(value).toBe(\"expected\");\n * ```\n */\nexport interface Signal<T> {\n /** Wait for the signal to be triggered */\n wait(options?: WaitForOptions): Promise<T>;\n /** Trigger the signal with a value */\n trigger(value: T): void;\n /** Check if signal has been triggered */\n isTriggered(): boolean;\n /** Reset the signal to untriggered state */\n reset(): void;\n /** Get the triggered value (undefined if not triggered) */\n getValue(): T | undefined;\n}\n\nexport function createSignal<T = void>(): Signal<T> {\n let deferred = createDeferred<T>();\n let triggered = false;\n let value: T | undefined;\n\n return {\n wait(options: WaitForOptions = {}) {\n const { timeout = 5000, timeoutMessage = \"Signal wait timed out\" } = options;\n\n return Promise.race([\n deferred.promise,\n new Promise<T>((_, reject) => setTimeout(() => reject(new Error(timeoutMessage)), timeout)),\n ]);\n },\n\n trigger(v: T) {\n if (!triggered) {\n triggered = true;\n value = v;\n deferred.resolve(v);\n }\n },\n\n isTriggered() {\n return triggered;\n },\n\n reset() {\n triggered = false;\n value = undefined;\n deferred = createDeferred<T>();\n },\n\n getValue() {\n return value;\n },\n };\n}\n\n/**\n * A collector that accumulates values and can wait for a specific count.\n * Useful for collecting multiple updates in tests.\n *\n * @example\n * ```ts\n * const collector = createCollector<string>();\n *\n * client.subscribe(\"config\", (value) => {\n * collector.push(value);\n * });\n *\n * // Wait for 3 updates\n * const values = await collector.waitForCount(3, { timeout: 5000 });\n * expect(values).toEqual([\"v1\", \"v2\", \"v3\"]);\n * ```\n */\nexport interface Collector<T> {\n /** Push a value to the collector */\n push(value: T): void;\n /** Get all collected values */\n getValues(): T[];\n /** Get the count of collected values */\n count(): number;\n /** Wait for at least N values to be collected */\n waitForCount(count: number, options?: WaitForOptions): Promise<T[]>;\n /** Wait for a value matching the predicate */\n waitFor(predicate: (value: T) => boolean, options?: WaitForOptions): Promise<T>;\n /** Clear all collected values */\n clear(): void;\n}\n\nexport function createCollector<T>(): Collector<T> {\n const values: T[] = [];\n const listeners: Array<() => void> = [];\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n return {\n push(value: T) {\n values.push(value);\n notify();\n },\n\n getValues() {\n return [...values];\n },\n\n count() {\n return values.length;\n },\n\n async waitForCount(count: number, options: WaitForOptions = {}) {\n const { timeout = 5000, timeoutMessage = `Collector timed out waiting for ${count} values` } =\n options;\n\n if (values.length >= count) {\n return [...values];\n }\n\n return new Promise<T[]>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n const idx = listeners.indexOf(listener);\n if (idx !== -1) listeners.splice(idx, 1);\n reject(new Error(timeoutMessage));\n }, timeout);\n\n const listener = () => {\n if (values.length >= count) {\n clearTimeout(timeoutId);\n const idx = listeners.indexOf(listener);\n if (idx !== -1) listeners.splice(idx, 1);\n resolve([...values]);\n }\n };\n\n listeners.push(listener);\n });\n },\n\n async waitFor(predicate: (value: T) => boolean, options: WaitForOptions = {}) {\n const { timeout = 5000, timeoutMessage = \"Collector timed out waiting for matching value\" } =\n options;\n\n // Check existing values first\n for (const v of values) {\n if (predicate(v)) return v;\n }\n\n return new Promise<T>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n const idx = listeners.indexOf(listener);\n if (idx !== -1) listeners.splice(idx, 1);\n reject(new Error(timeoutMessage));\n }, timeout);\n\n const listener = () => {\n // Check the latest value\n const latest = values[values.length - 1];\n if (latest !== undefined && predicate(latest)) {\n clearTimeout(timeoutId);\n const idx = listeners.indexOf(listener);\n if (idx !== -1) listeners.splice(idx, 1);\n resolve(latest);\n }\n };\n\n listeners.push(listener);\n });\n },\n\n clear() {\n values.length = 0;\n },\n };\n}\n\n/**\n * Delay for a specified time (use sparingly in tests)\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Generate a unique test identifier\n */\nexport function uniqueId(prefix = \"test\"): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * Sync the edge replica with the database.\n * Requires TESTING_MODE=true on the server.\n *\n * This is useful in tests to ensure the edge replica has\n * received all config changes before making assertions.\n *\n * @param request - The request object containing the edge API base URL and admin API key\n * @param request.edgeApiBaseUrl - The base URL of the edge API (e.g., \"http://localhost:8080\")\n * @param request.adminApiKey - The admin API key\n */\nexport async function syncReplica(request: {\n edgeApiBaseUrl: string;\n sdkKey: string;\n}): Promise<void> {\n const { edgeApiBaseUrl, sdkKey } = request;\n\n const response = await fetch(`${edgeApiBaseUrl}/api/sdk/v1/testing/sync`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${sdkKey}`,\n },\n });\n\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Failed to sync replica: ${response.status} ${body}`);\n }\n}\n","/**\n * Replane E2E Test Suite\n *\n * Comprehensive test suite for testing @replanejs/sdk with real @replanejs/admin API\n *\n * NOTE: This test suite is designed for multi-server setups where admin API and edge API\n * may be on different servers. Config changes are not immediate and require waiting for\n * replication to complete.\n */\n\nimport { describe, it, beforeAll, afterAll, afterEach, expect } from \"vitest\";\nimport { ReplaneAdmin, type ConfigValue, type Override } from \"@replanejs/admin\";\nimport { Replane, ReplaneError, ReplaneErrorCode } from \"@replanejs/sdk\";\nimport type { ReplaneContext } from \"@replanejs/sdk\";\nimport type { TestSuiteOptions, TestContext } from \"./types\";\nimport { createSignal, createCollector, delay, uniqueId, syncReplica } from \"./utils\";\n\n/**\n * Helper to create a literal value for conditions.\n */\nfunction literal<T>(value: T) {\n return { type: \"literal\" as const, value };\n}\n\nconst silentLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/**\n * Creates a test context with helper methods\n */\nfunction createTestContext(\n admin: ReplaneAdmin,\n workspaceId: string,\n projectId: string,\n environmentId: string,\n sdkKey: string,\n options: TestSuiteOptions\n): TestContext {\n const defaultTimeout = options.defaultTimeout ?? 10000;\n\n function sync(): Promise<void> {\n return syncReplica({ edgeApiBaseUrl: options.edgeApiBaseUrl, sdkKey });\n }\n\n return {\n admin,\n workspaceId,\n projectId,\n environmentId,\n sdkKey,\n edgeApiBaseUrl: options.edgeApiBaseUrl,\n adminApiBaseUrl: options.adminApiBaseUrl,\n defaultTimeout,\n\n sync,\n\n async createClient<T extends object = Record<string, unknown>>(clientOptions?: {\n context?: ReplaneContext;\n defaults?: Partial<T>;\n }): Promise<Replane<T>> {\n await sync();\n\n const client = new Replane<T>({\n logger: options.debug ? console : silentLogger,\n context: clientOptions?.context,\n defaults: clientOptions?.defaults as T | undefined,\n });\n\n await client.connect({\n sdkKey,\n baseUrl: options.edgeApiBaseUrl,\n connectTimeoutMs: defaultTimeout,\n });\n\n return client;\n },\n\n async createConfig(\n name: string,\n value: ConfigValue,\n configOptions?: {\n description?: string;\n overrides?: Override[];\n }\n ): Promise<void> {\n await admin.configs.create({\n projectId,\n name,\n description: configOptions?.description ?? \"\",\n editors: [],\n base: {\n value,\n schema: null,\n overrides: configOptions?.overrides ?? [],\n },\n variants: [],\n });\n await sync();\n },\n\n async updateConfig(\n name: string,\n value: ConfigValue,\n configOptions?: {\n description?: string;\n overrides?: Override[];\n }\n ): Promise<void> {\n await admin.configs.update({\n projectId,\n configName: name,\n description: configOptions?.description ?? \"\",\n editors: [],\n base: {\n value,\n schema: null,\n overrides: configOptions?.overrides ?? [],\n },\n variants: [],\n });\n await sync();\n },\n\n async deleteConfig(name: string): Promise<void> {\n await admin.configs.delete({ projectId, configName: name });\n await sync();\n },\n };\n}\n\n/**\n * Main test suite function\n *\n * @example\n * ```ts\n * import { testSuite } from \"@replanejs/test-suite\";\n *\n * testSuite({\n * superadminKey: process.env.SUPERADMIN_KEY!,\n * adminApiBaseUrl: \"http://localhost:8080\",\n * edgeApiBaseUrl: \"http://localhost:8080\",\n * });\n * ```\n */\nexport function testSuite(options: TestSuiteOptions): void {\n const { superadminKey, adminApiBaseUrl, edgeApiBaseUrl } = options;\n const defaultTimeout = options.defaultTimeout ?? 10000;\n\n describe(\"Replane E2E Test Suite\", () => {\n let admin: ReplaneAdmin;\n let workspaceId: string;\n let projectId: string;\n let environmentId: string;\n let sdkKey: string;\n let ctx: TestContext;\n\n // Track clients for cleanup\n const activeClients: Replane<Record<string, unknown>>[] = [];\n\n beforeAll(async () => {\n // Create admin client with superadmin key\n admin = new ReplaneAdmin({\n apiKey: superadminKey,\n baseUrl: adminApiBaseUrl,\n });\n\n // Create a unique workspace for this test run\n const workspaceName = uniqueId(\"e2e-workspace\");\n const workspaceRes = await admin.workspaces.create({ name: workspaceName });\n workspaceId = workspaceRes.id;\n\n // Create a project in the workspace\n const projectName = uniqueId(\"e2e-project\");\n const projectRes = await admin.projects.create({\n workspaceId,\n name: projectName,\n description: \"E2E test project\",\n });\n projectId = projectRes.id;\n\n // Get environments (use production)\n const envRes = await admin.environments.list({ projectId });\n const prodEnv =\n envRes.environments.find((e) => e.name === \"Production\") ?? envRes.environments[0];\n if (!prodEnv) {\n throw new Error(\"No environments found\");\n }\n environmentId = prodEnv.id;\n\n // Create SDK key\n const sdkKeyRes = await admin.sdkKeys.create({\n projectId,\n name: uniqueId(\"e2e-sdk-key\"),\n environmentId,\n });\n sdkKey = sdkKeyRes.key;\n\n await syncReplica({ edgeApiBaseUrl, sdkKey });\n\n // Create test context\n ctx = createTestContext(admin, workspaceId, projectId, environmentId, sdkKey, options);\n });\n\n afterAll(async () => {\n // Disconnect all active clients\n for (const client of activeClients) {\n try {\n client.disconnect();\n } catch {\n // Ignore errors during cleanup\n }\n }\n activeClients.length = 0;\n\n // Clean up: delete workspace (cascades to project, configs, keys)\n if (workspaceId) {\n await admin.workspaces.delete({ workspaceId });\n }\n });\n\n // Helper to track clients for cleanup\n const trackClient = <T extends object>(client: Replane<T>): Replane<T> => {\n activeClients.push(client as Replane<Record<string, unknown>>);\n return client;\n };\n\n afterEach(async () => {\n const configs = await admin.configs.list({ projectId });\n for (const config of configs.configs) {\n await admin.configs.delete({ projectId, configName: config.name });\n }\n await syncReplica({ edgeApiBaseUrl, sdkKey });\n });\n\n // ==================== CONNECTION TESTS ====================\n\n describe(\"SDK Connection\", () => {\n it(\"should connect and receive initial configs\", async () => {\n // Create config via admin API\n await ctx.createConfig(\"test-config\", \"initial-value\");\n\n // Create client - sync ensures configs are available\n const client = trackClient(\n await ctx.createClient<{ \"test-config\": string }>({})\n );\n\n const value = client.get(\"test-config\");\n expect(value).toBe(\"initial-value\");\n\n client.disconnect();\n });\n\n it(\"should handle empty project (no configs)\", async () => {\n // Create a new project with no configs\n const emptyProjectRes = await admin.projects.create({\n workspaceId,\n name: uniqueId(\"empty-project\"),\n description: \"Empty project for testing\",\n });\n const emptyEnvRes = await admin.environments.list({ projectId: emptyProjectRes.id });\n const emptyEnv = emptyEnvRes.environments[0];\n const emptySdkKeyRes = await admin.sdkKeys.create({\n projectId: emptyProjectRes.id,\n name: uniqueId(\"empty-sdk-key\"),\n environmentId: emptyEnv.id,\n });\n\n // Wait for SDK key to sync\n await syncReplica({ edgeApiBaseUrl, sdkKey });\n\n const emptyClient = new Replane({\n logger: silentLogger,\n });\n await emptyClient.connect({\n sdkKey: emptySdkKeyRes.key,\n baseUrl: edgeApiBaseUrl,\n connectTimeoutMs: defaultTimeout,\n });\n const client = trackClient(emptyClient);\n\n // Should not throw, but get() with no default should throw\n expect(() => client.get(\"nonexistent\")).toThrow();\n\n client.disconnect();\n\n // Cleanup\n await admin.projects.delete({ projectId: emptyProjectRes.id });\n });\n\n it(\"should use default values when config not found\", async () => {\n const client = trackClient(\n await ctx.createClient({\n defaults: { \"missing-config\": \"default-value\" },\n })\n );\n\n const value = client.get(\"missing-config\");\n expect(value).toBe(\"default-value\");\n\n client.disconnect();\n });\n\n });\n\n // ==================== GET CONFIG TESTS ====================\n\n describe(\"Get Config\", () => {\n it(\"should get string config\", async () => {\n await ctx.createConfig(\"string-config\", \"hello\");\n\n const client = trackClient(\n await ctx.createClient<{ \"string-config\": string }>({})\n );\n\n expect(client.get(\"string-config\")).toBe(\"hello\");\n client.disconnect();\n });\n\n it(\"should get number config\", async () => {\n await ctx.createConfig(\"number-config\", 42);\n\n const client = trackClient(\n await ctx.createClient<{ \"number-config\": number }>({})\n );\n\n expect(client.get(\"number-config\")).toBe(42);\n client.disconnect();\n });\n\n it(\"should get boolean config\", async () => {\n await ctx.createConfig(\"boolean-config\", true);\n\n const client = trackClient(\n await ctx.createClient<{ \"boolean-config\": boolean }>({})\n );\n\n expect(client.get(\"boolean-config\")).toBe(true);\n client.disconnect();\n });\n\n it(\"should get object config\", async () => {\n const objValue = { nested: { value: \"deep\" } };\n await ctx.createConfig(\"object-config\", objValue);\n\n const client = trackClient(\n await ctx.createClient<{ \"object-config\": typeof objValue }>({\n })\n );\n\n expect(client.get(\"object-config\")).toEqual(objValue);\n client.disconnect();\n });\n\n it(\"should get array config\", async () => {\n const arrValue = [1, 2, 3];\n await ctx.createConfig(\"array-config\", arrValue);\n\n const client = trackClient(\n await ctx.createClient<{ \"array-config\": number[] }>({})\n );\n\n expect(client.get(\"array-config\")).toEqual(arrValue);\n client.disconnect();\n });\n\n it(\"should get null config\", async () => {\n await ctx.createConfig(\"null-config\", null);\n\n const client = trackClient(\n await ctx.createClient<{ \"null-config\": null }>({})\n );\n\n expect(client.get(\"null-config\")).toBe(null);\n client.disconnect();\n });\n\n it(\"should return default value when config not found\", async () => {\n const client = trackClient(await ctx.createClient());\n const value = client.get(\"nonexistent\", { default: \"fallback\" });\n expect(value).toBe(\"fallback\");\n client.disconnect();\n });\n\n it(\"should throw ReplaneError when config not found and no default\", async () => {\n const client = trackClient(await ctx.createClient());\n try {\n client.get(\"nonexistent\");\n expect.fail(\"Should have thrown\");\n } catch (error) {\n expect(error).toBeInstanceOf(ReplaneError);\n expect((error as ReplaneError).code).toBe(ReplaneErrorCode.NotFound);\n }\n client.disconnect();\n });\n });\n\n // ==================== REAL-TIME UPDATES TESTS ====================\n\n describe(\"Real-time Updates\", () => {\n it(\"should receive config updates via subscription\", async () => {\n await ctx.createConfig(\"live-config\", \"initial\");\n\n const client = trackClient(\n await ctx.createClient<{ \"live-config\": string }>({})\n );\n\n expect(client.get(\"live-config\")).toBe(\"initial\");\n\n // Set up signal for next update\n const updateSignal = createSignal<string>();\n client.subscribe(\"live-config\", (config) => {\n if (config.value !== \"initial\") {\n updateSignal.trigger(config.value as string);\n }\n });\n\n // Update config\n await ctx.updateConfig(\"live-config\", \"updated\");\n\n // Wait for update (with timeout)\n const newValue = await updateSignal.wait({ timeout: defaultTimeout });\n expect(newValue).toBe(\"updated\");\n\n // Verify get() returns new value\n expect(client.get(\"live-config\")).toBe(\"updated\");\n\n client.disconnect();\n });\n\n it(\"should receive multiple updates in order\", async () => {\n await ctx.createConfig(\"multi-update-config\", 0);\n\n const client = trackClient(\n await ctx.createClient<{ \"multi-update-config\": number }>({\n })\n );\n\n expect(client.get(\"multi-update-config\")).toBe(0);\n\n const collector = createCollector<number>();\n client.subscribe(\"multi-update-config\", (config) => {\n const val = config.value as number;\n if (val > 0) {\n collector.push(val);\n }\n });\n\n // Send multiple updates with small delays to ensure ordering\n await ctx.updateConfig(\"multi-update-config\", 1);\n await delay(100);\n await ctx.updateConfig(\"multi-update-config\", 2);\n await delay(100);\n await ctx.updateConfig(\"multi-update-config\", 3);\n\n // Wait for all updates\n const values = await collector.waitForCount(3, { timeout: defaultTimeout });\n expect(values).toEqual([1, 2, 3]);\n\n client.disconnect();\n });\n\n it(\"should handle rapid updates\", async () => {\n await ctx.createConfig(\"rapid-config\", 0);\n\n const client = trackClient(\n await ctx.createClient<{ \"rapid-config\": number }>({})\n );\n\n expect(client.get(\"rapid-config\")).toBe(0);\n\n const collector = createCollector<number>();\n client.subscribe(\"rapid-config\", (config) => {\n collector.push(config.value as number);\n });\n\n // Send rapid updates\n const updateCount = 10;\n for (let i = 1; i <= updateCount; i++) {\n await ctx.updateConfig(\"rapid-config\", i);\n }\n\n // Wait for final value (may not get all intermediate values due to batching)\n await collector.waitFor((v) => v === updateCount, { timeout: defaultTimeout });\n\n // Final value should be correct\n expect(client.get(\"rapid-config\")).toBe(updateCount);\n\n client.disconnect();\n });\n\n it(\"should call global subscription for any config change\", async () => {\n await ctx.createConfig(\"config-a\", \"a\");\n await ctx.createConfig(\"config-b\", \"b\");\n\n const client = trackClient(\n await ctx.createClient<{ \"config-a\": string; \"config-b\": string }>({\n })\n );\n\n expect(client.get(\"config-a\")).toBe(\"a\");\n expect(client.get(\"config-b\")).toBe(\"b\");\n\n const collector = createCollector<{ name: unknown; value: unknown }>();\n client.subscribe((config) => {\n // Only collect updates (not initial values)\n if (config.value === \"a-updated\" || config.value === \"b-updated\") {\n collector.push({ name: config.name, value: config.value });\n }\n });\n\n // Update both configs\n await ctx.updateConfig(\"config-a\", \"a-updated\");\n await ctx.updateConfig(\"config-b\", \"b-updated\");\n\n // Wait for both updates\n await collector.waitForCount(2, { timeout: defaultTimeout });\n\n const values = collector.getValues();\n const aUpdate = values.find((v) => v.name === \"config-a\");\n const bUpdate = values.find((v) => v.name === \"config-b\");\n\n expect(aUpdate?.value).toBe(\"a-updated\");\n expect(bUpdate?.value).toBe(\"b-updated\");\n\n client.disconnect();\n });\n\n it(\"should allow unsubscribing\", async () => {\n await ctx.createConfig(\"unsub-config\", \"initial\");\n\n const client = trackClient(\n await ctx.createClient<{ \"unsub-config\": string }>({})\n );\n\n expect(client.get(\"unsub-config\")).toBe(\"initial\");\n\n const collector = createCollector<string>();\n const unsubscribe = client.subscribe(\"unsub-config\", (config) => {\n if (config.value !== \"initial\") {\n collector.push(config.value as string);\n }\n });\n\n // First update should be received\n await ctx.updateConfig(\"unsub-config\", \"update-1\");\n await collector.waitForCount(1, { timeout: defaultTimeout });\n\n // Unsubscribe\n unsubscribe();\n\n // Second update should NOT be received\n await ctx.updateConfig(\"unsub-config\", \"update-2\");\n await delay(2000); // Give time for potential update to propagate\n\n // Should only have 1 update\n expect(collector.count()).toBe(1);\n\n client.disconnect();\n });\n });\n\n // ==================== OVERRIDE TESTS ====================\n\n describe(\"Override Evaluation\", () => {\n it(\"should evaluate equals condition\", async () => {\n await ctx.createConfig(\"env-config\", \"default\", {\n overrides: [\n {\n name: \"prod-override\",\n conditions: [{ operator: \"equals\", property: \"env\", value: literal(\"production\") }],\n value: \"production-value\",\n },\n ],\n });\n\n // Without context - should get default\n const client1 = trackClient(\n await ctx.createClient<{ \"env-config\": string }>({})\n );\n expect(client1.get(\"env-config\")).toBe(\"default\");\n client1.disconnect();\n\n // With matching context\n const client2 = trackClient(\n await ctx.createClient<{ \"env-config\": string }>({\n context: { env: \"production\" },\n })\n );\n expect(client2.get(\"env-config\")).toBe(\"production-value\");\n client2.disconnect();\n\n // With non-matching context\n const client3 = trackClient(\n await ctx.createClient<{ \"env-config\": string }>({\n context: { env: \"staging\" },\n })\n );\n expect(client3.get(\"env-config\")).toBe(\"default\");\n client3.disconnect();\n });\n\n it(\"should evaluate in condition\", async () => {\n await ctx.createConfig(\"region-config\", \"default\", {\n overrides: [\n {\n name: \"western-override\",\n conditions: [{ operator: \"in\", property: \"region\", value: literal([\"us\", \"eu\"]) }],\n value: \"western\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"region-config\": string }>({\n context: { region: \"us\" },\n })\n );\n expect(client1.get(\"region-config\")).toBe(\"western\");\n client1.disconnect();\n\n const client2 = trackClient(\n await ctx.createClient<{ \"region-config\": string }>({\n context: { region: \"eu\" },\n })\n );\n expect(client2.get(\"region-config\")).toBe(\"western\");\n client2.disconnect();\n\n const client3 = trackClient(\n await ctx.createClient<{ \"region-config\": string }>({\n context: { region: \"asia\" },\n })\n );\n expect(client3.get(\"region-config\")).toBe(\"default\");\n client3.disconnect();\n });\n\n it(\"should evaluate not_in condition\", async () => {\n await ctx.createConfig(\"allow-config\", \"allowed\", {\n overrides: [\n {\n name: \"not-blocked-override\",\n conditions: [\n {\n operator: \"not_in\",\n property: \"country\",\n value: literal([\"blocked1\", \"blocked2\"]),\n },\n ],\n value: \"not-blocked\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"allow-config\": string }>({\n context: { country: \"blocked1\" },\n })\n );\n expect(client1.get(\"allow-config\")).toBe(\"allowed\");\n client1.disconnect();\n\n const client2 = trackClient(\n await ctx.createClient<{ \"allow-config\": string }>({\n context: { country: \"normal\" },\n })\n );\n expect(client2.get(\"allow-config\")).toBe(\"not-blocked\");\n client2.disconnect();\n });\n\n it(\"should evaluate numeric comparison conditions\", async () => {\n await ctx.createConfig(\"tier-config\", \"free\", {\n overrides: [\n {\n name: \"premium-override\",\n conditions: [\n { operator: \"greater_than_or_equal\", property: \"level\", value: literal(10) },\n ],\n value: \"premium\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"tier-config\": string }>({\n context: { level: 5 },\n })\n );\n expect(client1.get(\"tier-config\")).toBe(\"free\");\n client1.disconnect();\n\n const client2 = trackClient(\n await ctx.createClient<{ \"tier-config\": string }>({\n context: { level: 10 },\n })\n );\n expect(client2.get(\"tier-config\")).toBe(\"premium\");\n client2.disconnect();\n\n const client3 = trackClient(\n await ctx.createClient<{ \"tier-config\": string }>({\n context: { level: 15 },\n })\n );\n expect(client3.get(\"tier-config\")).toBe(\"premium\");\n client3.disconnect();\n });\n\n it(\"should evaluate and condition\", async () => {\n await ctx.createConfig(\"combo-config\", \"default\", {\n overrides: [\n {\n name: \"combo-override\",\n conditions: [\n {\n operator: \"and\",\n conditions: [\n { operator: \"equals\", property: \"plan\", value: literal(\"enterprise\") },\n { operator: \"equals\", property: \"verified\", value: literal(true) },\n ],\n },\n ],\n value: \"enterprise-verified\",\n },\n ],\n });\n\n // Both conditions must match\n const client1 = trackClient(\n await ctx.createClient<{ \"combo-config\": string }>({\n context: { plan: \"enterprise\", verified: true },\n })\n );\n expect(client1.get(\"combo-config\")).toBe(\"enterprise-verified\");\n client1.disconnect();\n\n // Only one matches\n const client2 = trackClient(\n await ctx.createClient<{ \"combo-config\": string }>({\n context: { plan: \"enterprise\", verified: false },\n })\n );\n expect(client2.get(\"combo-config\")).toBe(\"default\");\n client2.disconnect();\n });\n\n it(\"should evaluate or condition\", async () => {\n await ctx.createConfig(\"either-config\", \"default\", {\n overrides: [\n {\n name: \"privileged-override\",\n conditions: [\n {\n operator: \"or\",\n conditions: [\n { operator: \"equals\", property: \"role\", value: literal(\"admin\") },\n { operator: \"equals\", property: \"role\", value: literal(\"superadmin\") },\n ],\n },\n ],\n value: \"privileged\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"either-config\": string }>({\n context: { role: \"admin\" },\n })\n );\n expect(client1.get(\"either-config\")).toBe(\"privileged\");\n client1.disconnect();\n\n const client2 = trackClient(\n await ctx.createClient<{ \"either-config\": string }>({\n context: { role: \"superadmin\" },\n })\n );\n expect(client2.get(\"either-config\")).toBe(\"privileged\");\n client2.disconnect();\n\n const client3 = trackClient(\n await ctx.createClient<{ \"either-config\": string }>({\n context: { role: \"user\" },\n })\n );\n expect(client3.get(\"either-config\")).toBe(\"default\");\n client3.disconnect();\n });\n\n it(\"should allow per-request context override\", async () => {\n await ctx.createConfig(\"dynamic-config\", \"default\", {\n overrides: [\n {\n name: \"feature-override\",\n conditions: [{ operator: \"equals\", property: \"feature\", value: literal(\"enabled\") }],\n value: \"feature-on\",\n },\n ],\n });\n\n const client = trackClient(\n await ctx.createClient<{ \"dynamic-config\": string }>({})\n );\n\n // Without context\n expect(client.get(\"dynamic-config\")).toBe(\"default\");\n\n // With per-request context\n expect(client.get(\"dynamic-config\", { context: { feature: \"enabled\" } })).toBe(\n \"feature-on\"\n );\n\n // Original still returns default\n expect(client.get(\"dynamic-config\")).toBe(\"default\");\n\n client.disconnect();\n });\n\n it(\"should apply first matching override\", async () => {\n await ctx.createConfig(\"priority-config\", \"default\", {\n overrides: [\n {\n name: \"gold-override\",\n conditions: [{ operator: \"equals\", property: \"tier\", value: literal(\"gold\") }],\n value: \"gold-value\",\n },\n {\n name: \"silver-override\",\n conditions: [{ operator: \"equals\", property: \"tier\", value: literal(\"silver\") }],\n value: \"silver-value\",\n },\n {\n name: \"score-override\",\n conditions: [{ operator: \"greater_than\", property: \"score\", value: literal(0) }],\n value: \"has-score\",\n },\n ],\n });\n\n // First override matches\n const client = trackClient(\n await ctx.createClient<{ \"priority-config\": string }>({\n context: { tier: \"gold\", score: 100 },\n })\n );\n expect(client.get(\"priority-config\")).toBe(\"gold-value\");\n client.disconnect();\n });\n });\n\n // ==================== SNAPSHOT TESTS ====================\n\n describe(\"Snapshot\", () => {\n it(\"should create snapshot with current configs\", async () => {\n await ctx.createConfig(\"snap-config-1\", \"value-1\");\n await ctx.createConfig(\"snap-config-2\", \"value-2\");\n\n const client = trackClient(\n await ctx.createClient<{ \"snap-config-1\": string; \"snap-config-2\": string }>({})\n );\n\n const snapshot = client.getSnapshot();\n\n expect(snapshot.configs).toMatchInlineSnapshot(`\n [\n {\n \"name\": \"snap-config-1\",\n \"overrides\": [],\n \"value\": \"value-1\",\n },\n {\n \"name\": \"snap-config-2\",\n \"overrides\": [],\n \"value\": \"value-2\",\n },\n ]\n `);\n expect(snapshot.configs.map((c) => c.name).sort()).toEqual([\n \"snap-config-1\",\n \"snap-config-2\",\n ]);\n\n client.disconnect();\n });\n\n });\n\n // ==================== ERROR HANDLING TESTS ====================\n\n describe(\"Error Handling\", () => {\n it(\"should throw on invalid SDK key\", async () => {\n const invalidClient = new Replane({\n logger: silentLogger,\n });\n await expect(\n invalidClient.connect({\n sdkKey: \"invalid-key\",\n baseUrl: edgeApiBaseUrl,\n connectTimeoutMs: 2000,\n })\n ).rejects.toThrow();\n });\n\n it(\"should handle disconnected client gracefully\", async () => {\n await ctx.createConfig(\"close-test\", \"value\");\n\n const client = trackClient(\n await ctx.createClient<{ \"close-test\": string }>({\n defaults: { \"close-test\": \"default\" },\n })\n );\n\n expect(client.get(\"close-test\")).toBe(\"value\");\n\n client.disconnect();\n\n // After disconnect, client should still return cached value (doesn't throw)\n // This verifies the client handles disconnect gracefully\n const cachedValue = client.get(\"close-test\");\n expect(cachedValue).toBe(\"value\");\n });\n\n it(\"should timeout on unreachable server\", async () => {\n const unreachableClient = new Replane({\n logger: silentLogger,\n });\n await expect(\n unreachableClient.connect({\n sdkKey: \"rp_test\",\n baseUrl: \"http://localhost:59999\", // Non-existent port\n connectTimeoutMs: 1000,\n })\n ).rejects.toThrow();\n });\n });\n\n // ==================== CONFIG LIFECYCLE TESTS ====================\n\n describe(\"Config Lifecycle\", () => {\n it(\"should handle config creation after client connects\", async () => {\n // Create client first with no configs\n const client = trackClient(\n await ctx.createClient({ defaults: { \"late-config\": \"waiting\" } })\n );\n\n // Set up signal to wait for the config\n const configSignal = createSignal<string>();\n client.subscribe(\"late-config\", (config) => {\n configSignal.trigger(config.value as string);\n });\n\n // Create config after connection\n await ctx.createConfig(\"late-config\", \"late-value\");\n\n // Wait for the config to appear via subscription\n const value = await configSignal.wait({ timeout: defaultTimeout });\n expect(value).toBe(\"late-value\");\n\n expect(client.get(\"late-config\")).toBe(\"late-value\");\n\n client.disconnect();\n });\n\n it(\"should ignore config deletion on client\", async () => {\n await ctx.createConfig(\"delete-me\", \"exists\");\n\n const client = trackClient(\n await ctx.createClient<{ \"delete-me\": string }>({})\n );\n\n expect(client.get(\"delete-me\")).toBe(\"exists\");\n\n // Delete config\n await ctx.deleteConfig(\"delete-me\");\n\n await delay(1000);\n\n expect(client.get(\"delete-me\")).toBe(\"exists\");\n\n client.disconnect();\n });\n });\n\n // ==================== CONCURRENT CLIENTS TESTS ====================\n\n describe(\"Concurrent Clients\", () => {\n it(\"should handle multiple clients with same SDK key\", async () => {\n await ctx.createConfig(\"shared-config\", \"initial\");\n\n const client1 = trackClient(\n await ctx.createClient<{ \"shared-config\": string }>({})\n );\n const client2 = trackClient(\n await ctx.createClient<{ \"shared-config\": string }>({})\n );\n\n expect(client1.get(\"shared-config\")).toBe(\"initial\");\n expect(client2.get(\"shared-config\")).toBe(\"initial\");\n\n // Both should receive updates\n const signal1 = createSignal<string>();\n const signal2 = createSignal<string>();\n\n client1.subscribe(\"shared-config\", (c) => {\n if (c.value === \"updated\") signal1.trigger(c.value as string);\n });\n client2.subscribe(\"shared-config\", (c) => {\n if (c.value === \"updated\") signal2.trigger(c.value as string);\n });\n\n await ctx.updateConfig(\"shared-config\", \"updated\");\n\n const [v1, v2] = await Promise.all([\n signal1.wait({ timeout: defaultTimeout }),\n signal2.wait({ timeout: defaultTimeout }),\n ]);\n\n expect(v1).toBe(\"updated\");\n expect(v2).toBe(\"updated\");\n\n client1.disconnect();\n client2.disconnect();\n });\n\n it(\"should isolate context between clients\", async () => {\n await ctx.createConfig(\"context-config\", \"default\", {\n overrides: [\n {\n name: \"prod-override\",\n conditions: [{ operator: \"equals\", property: \"env\", value: literal(\"prod\") }],\n value: \"prod-value\",\n },\n ],\n });\n\n const client1 = trackClient(\n await ctx.createClient<{ \"context-config\": string }>({\n context: { env: \"prod\" },\n })\n );\n const client2 = trackClient(\n await ctx.createClient<{ \"context-config\": string }>({\n context: { env: \"dev\" },\n })\n );\n\n expect(client1.get(\"context-config\")).toBe(\"prod-value\");\n expect(client2.get(\"context-config\")).toBe(\"default\");\n\n client1.disconnect();\n client2.disconnect();\n });\n });\n });\n}\n"],"mappings":";;;;;;;;AAaA,SAAgB,iBAAiC;CAC/C,IAAIA;CACJ,IAAIC;CAEJ,MAAM,UAAU,IAAI,QAAW,CAAC,KAAK,QAAQ;AAC3C,YAAU;AACV,WAAS;CACV;AAED,QAAO;EAAE;EAAS;EAAS;CAAQ;AACpC;;;;;;;;;;;;;;AAyBD,eAAsB,QACpBC,WACAC,UAA0B,CAAE,GACb;CACf,MAAM,EAAE,UAAU,KAAM,iBAAiB,qBAAqB,GAAG;CAEjE,MAAM,YAAY,KAAK,KAAK;AAE5B,QAAO,MAAM;EACX,MAAM,SAAS,MAAM,WAAW;AAChC,MAAI,OAAQ;AAEZ,MAAI,KAAK,KAAK,GAAG,aAAa,QAC5B,OAAM,IAAI,MAAM;AAIlB,QAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG;CACvD;AACF;AA+BD,SAAgB,eAAoC;CAClD,IAAI,WAAW,gBAAmB;CAClC,IAAI,YAAY;CAChB,IAAIC;AAEJ,QAAO;EACL,KAAKD,UAA0B,CAAE,GAAE;GACjC,MAAM,EAAE,UAAU,KAAM,iBAAiB,yBAAyB,GAAG;AAErE,UAAO,QAAQ,KAAK,CAClB,SAAS,SACT,IAAI,QAAW,CAAC,GAAG,WAAW,WAAW,MAAM,OAAO,IAAI,MAAM,gBAAgB,EAAE,QAAQ,CAC3F,EAAC;EACH;EAED,QAAQE,GAAM;AACZ,QAAK,WAAW;AACd,gBAAY;AACZ,YAAQ;AACR,aAAS,QAAQ,EAAE;GACpB;EACF;EAED,cAAc;AACZ,UAAO;EACR;EAED,QAAQ;AACN,eAAY;AACZ;AACA,cAAW,gBAAmB;EAC/B;EAED,WAAW;AACT,UAAO;EACR;CACF;AACF;AAkCD,SAAgB,kBAAmC;CACjD,MAAMC,SAAc,CAAE;CACtB,MAAMC,YAA+B,CAAE;CAEvC,MAAM,SAAS,MAAM;AACnB,OAAK,MAAM,YAAY,UACrB,WAAU;CAEb;AAED,QAAO;EACL,KAAKC,OAAU;AACb,UAAO,KAAK,MAAM;AAClB,WAAQ;EACT;EAED,YAAY;AACV,UAAO,CAAC,GAAG,MAAO;EACnB;EAED,QAAQ;AACN,UAAO,OAAO;EACf;EAED,MAAM,aAAaC,OAAeN,UAA0B,CAAE,GAAE;GAC9D,MAAM,EAAE,UAAU,KAAM,kBAAkB,kCAAkC,MAAM,UAAU,GAC1F;AAEF,OAAI,OAAO,UAAU,MACnB,QAAO,CAAC,GAAG,MAAO;AAGpB,UAAO,IAAI,QAAa,CAAC,SAAS,WAAW;IAC3C,MAAM,YAAY,WAAW,MAAM;KACjC,MAAM,MAAM,UAAU,QAAQ,SAAS;AACvC,SAAI,QAAQ,GAAI,WAAU,OAAO,KAAK,EAAE;AACxC,YAAO,IAAI,MAAM,gBAAgB;IAClC,GAAE,QAAQ;IAEX,MAAM,WAAW,MAAM;AACrB,SAAI,OAAO,UAAU,OAAO;AAC1B,mBAAa,UAAU;MACvB,MAAM,MAAM,UAAU,QAAQ,SAAS;AACvC,UAAI,QAAQ,GAAI,WAAU,OAAO,KAAK,EAAE;AACxC,cAAQ,CAAC,GAAG,MAAO,EAAC;KACrB;IACF;AAED,cAAU,KAAK,SAAS;GACzB;EACF;EAED,MAAM,QAAQO,WAAkCP,UAA0B,CAAE,GAAE;GAC5E,MAAM,EAAE,UAAU,KAAM,iBAAiB,kDAAkD,GACzF;AAGF,QAAK,MAAM,KAAK,OACd,KAAI,UAAU,EAAE,CAAE,QAAO;AAG3B,UAAO,IAAI,QAAW,CAAC,SAAS,WAAW;IACzC,MAAM,YAAY,WAAW,MAAM;KACjC,MAAM,MAAM,UAAU,QAAQ,SAAS;AACvC,SAAI,QAAQ,GAAI,WAAU,OAAO,KAAK,EAAE;AACxC,YAAO,IAAI,MAAM,gBAAgB;IAClC,GAAE,QAAQ;IAEX,MAAM,WAAW,MAAM;KAErB,MAAM,SAAS,OAAO,OAAO,SAAS;AACtC,SAAI,qBAAwB,UAAU,OAAO,EAAE;AAC7C,mBAAa,UAAU;MACvB,MAAM,MAAM,UAAU,QAAQ,SAAS;AACvC,UAAI,QAAQ,GAAI,WAAU,OAAO,KAAK,EAAE;AACxC,cAAQ,OAAO;KAChB;IACF;AAED,cAAU,KAAK,SAAS;GACzB;EACF;EAED,QAAQ;AACN,UAAO,SAAS;EACjB;CACF;AACF;;;;AAKD,SAAgB,MAAMQ,IAA2B;AAC/C,QAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG;AACxD;;;;AAKD,SAAgB,SAAS,SAAS,QAAgB;AAChD,SAAQ,EAAE,OAAO,GAAG,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;AAC1E;;;;;;;;;;;;AAaD,eAAsB,YAAYC,SAGhB;CAChB,MAAM,EAAE,gBAAgB,QAAQ,GAAG;CAEnC,MAAM,WAAW,MAAM,OAAO,EAAE,eAAe,2BAA2B;EACxE,QAAQ;EACR,SAAS,EACP,gBAAgB,SAAS,OAAO,EACjC;CACF,EAAC;AAEF,MAAK,SAAS,IAAI;EAChB,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,QAAM,IAAI,OAAO,0BAA0B,SAAS,OAAO,GAAG,KAAK;CACpE;AACF;;;;;;;ACxRD,SAAS,QAAWC,OAAU;AAC5B,QAAO;EAAE,MAAM;EAAoB;CAAO;AAC3C;AAED,MAAM,eAAe;CACnB,OAAO,MAAM,CAAE;CACf,MAAM,MAAM,CAAE;CACd,MAAM,MAAM,CAAE;CACd,OAAO,MAAM,CAAE;AAChB;;;;AAKD,SAAS,kBACPC,OACAC,aACAC,WACAC,eACAC,QACAC,SACa;CACb,MAAM,iBAAiB,QAAQ,kBAAkB;CAEjD,SAAS,OAAsB;AAC7B,SAAO,YAAY;GAAE,gBAAgB,QAAQ;GAAgB;EAAQ,EAAC;CACvE;AAED,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,gBAAgB,QAAQ;EACxB,iBAAiB,QAAQ;EACzB;EAEA;EAEA,MAAM,aAAyDC,eAGvC;AACtB,SAAM,MAAM;GAEZ,MAAM,SAAS,IAAI,QAAW;IAC5B,QAAQ,QAAQ,QAAQ,UAAU;IAClC,SAAS,eAAe;IACxB,UAAU,eAAe;GAC1B;AAED,SAAM,OAAO,QAAQ;IACnB;IACA,SAAS,QAAQ;IACjB,kBAAkB;GACnB,EAAC;AAEF,UAAO;EACR;EAED,MAAM,aACJC,MACAC,OACAC,eAIe;AACf,SAAM,MAAM,QAAQ,OAAO;IACzB;IACA;IACA,aAAa,eAAe,eAAe;IAC3C,SAAS,CAAE;IACX,MAAM;KACJ;KACA,QAAQ;KACR,WAAW,eAAe,aAAa,CAAE;IAC1C;IACD,UAAU,CAAE;GACb,EAAC;AACF,SAAM,MAAM;EACb;EAED,MAAM,aACJF,MACAC,OACAC,eAIe;AACf,SAAM,MAAM,QAAQ,OAAO;IACzB;IACA,YAAY;IACZ,aAAa,eAAe,eAAe;IAC3C,SAAS,CAAE;IACX,MAAM;KACJ;KACA,QAAQ;KACR,WAAW,eAAe,aAAa,CAAE;IAC1C;IACD,UAAU,CAAE;GACb,EAAC;AACF,SAAM,MAAM;EACb;EAED,MAAM,aAAaF,MAA6B;AAC9C,SAAM,MAAM,QAAQ,OAAO;IAAE;IAAW,YAAY;GAAM,EAAC;AAC3D,SAAM,MAAM;EACb;CACF;AACF;;;;;;;;;;;;;;;AAgBD,SAAgB,UAAUF,SAAiC;CACzD,MAAM,EAAE,eAAe,iBAAiB,gBAAgB,GAAG;CAC3D,MAAM,iBAAiB,QAAQ,kBAAkB;AAEjD,UAAS,0BAA0B,MAAM;EACvC,IAAIL;EACJ,IAAIC;EACJ,IAAIC;EACJ,IAAIC;EACJ,IAAIC;EACJ,IAAIM;EAGJ,MAAMC,gBAAoD,CAAE;AAE5D,YAAU,YAAY;AAEpB,WAAQ,IAAI,aAAa;IACvB,QAAQ;IACR,SAAS;GACV;GAGD,MAAM,gBAAgB,SAAS,gBAAgB;GAC/C,MAAM,eAAe,MAAM,MAAM,WAAW,OAAO,EAAE,MAAM,cAAe,EAAC;AAC3E,iBAAc,aAAa;GAG3B,MAAM,cAAc,SAAS,cAAc;GAC3C,MAAM,aAAa,MAAM,MAAM,SAAS,OAAO;IAC7C;IACA,MAAM;IACN,aAAa;GACd,EAAC;AACF,eAAY,WAAW;GAGvB,MAAM,SAAS,MAAM,MAAM,aAAa,KAAK,EAAE,UAAW,EAAC;GAC3D,MAAM,UACJ,OAAO,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,aAAa,IAAI,OAAO,aAAa;AAClF,QAAK,QACH,OAAM,IAAI,MAAM;AAElB,mBAAgB,QAAQ;GAGxB,MAAM,YAAY,MAAM,MAAM,QAAQ,OAAO;IAC3C;IACA,MAAM,SAAS,cAAc;IAC7B;GACD,EAAC;AACF,YAAS,UAAU;AAEnB,SAAM,YAAY;IAAE;IAAgB;GAAQ,EAAC;AAG7C,SAAM,kBAAkB,OAAO,aAAa,WAAW,eAAe,QAAQ,QAAQ;EACvF,EAAC;AAEF,WAAS,YAAY;AAEnB,QAAK,MAAM,UAAU,cACnB,KAAI;AACF,WAAO,YAAY;GACpB,QAAO,CAEP;AAEH,iBAAc,SAAS;AAGvB,OAAI,YACF,OAAM,MAAM,WAAW,OAAO,EAAE,YAAa,EAAC;EAEjD,EAAC;EAGF,MAAM,cAAc,CAAmBC,WAAmC;AACxE,iBAAc,KAAK,OAA2C;AAC9D,UAAO;EACR;AAED,YAAU,YAAY;GACpB,MAAM,UAAU,MAAM,MAAM,QAAQ,KAAK,EAAE,UAAW,EAAC;AACvD,QAAK,MAAM,UAAU,QAAQ,QAC3B,OAAM,MAAM,QAAQ,OAAO;IAAE;IAAW,YAAY,OAAO;GAAM,EAAC;AAEpE,SAAM,YAAY;IAAE;IAAgB;GAAQ,EAAC;EAC9C,EAAC;AAIF,WAAS,kBAAkB,MAAM;AAC/B,MAAG,8CAA8C,YAAY;AAE3D,UAAM,IAAI,aAAa,eAAe,gBAAgB;IAGtD,MAAM,SAAS,YACb,MAAM,IAAI,aAAwC,CAAE,EAAC,CACtD;IAED,MAAM,QAAQ,OAAO,IAAI,cAAc;AACvC,WAAO,MAAM,CAAC,KAAK,gBAAgB;AAEnC,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,4CAA4C,YAAY;IAEzD,MAAM,kBAAkB,MAAM,MAAM,SAAS,OAAO;KAClD;KACA,MAAM,SAAS,gBAAgB;KAC/B,aAAa;IACd,EAAC;IACF,MAAM,cAAc,MAAM,MAAM,aAAa,KAAK,EAAE,WAAW,gBAAgB,GAAI,EAAC;IACpF,MAAM,WAAW,YAAY,aAAa;IAC1C,MAAM,iBAAiB,MAAM,MAAM,QAAQ,OAAO;KAChD,WAAW,gBAAgB;KAC3B,MAAM,SAAS,gBAAgB;KAC/B,eAAe,SAAS;IACzB,EAAC;AAGF,UAAM,YAAY;KAAE;KAAgB;IAAQ,EAAC;IAE7C,MAAM,cAAc,IAAI,QAAQ,EAC9B,QAAQ,aACT;AACD,UAAM,YAAY,QAAQ;KACxB,QAAQ,eAAe;KACvB,SAAS;KACT,kBAAkB;IACnB,EAAC;IACF,MAAM,SAAS,YAAY,YAAY;AAGvC,WAAO,MAAM,OAAO,IAAI,cAAc,CAAC,CAAC,SAAS;AAEjD,WAAO,YAAY;AAGnB,UAAM,MAAM,SAAS,OAAO,EAAE,WAAW,gBAAgB,GAAI,EAAC;GAC/D,EAAC;AAEF,MAAG,mDAAmD,YAAY;IAChE,MAAM,SAAS,YACb,MAAM,IAAI,aAAa,EACrB,UAAU,EAAE,kBAAkB,gBAAiB,EAChD,EAAC,CACH;IAED,MAAM,QAAQ,OAAO,IAAI,iBAAiB;AAC1C,WAAO,MAAM,CAAC,KAAK,gBAAgB;AAEnC,WAAO,YAAY;GACpB,EAAC;EAEH,EAAC;AAIF,WAAS,cAAc,MAAM;AAC3B,MAAG,4BAA4B,YAAY;AACzC,UAAM,IAAI,aAAa,iBAAiB,QAAQ;IAEhD,MAAM,SAAS,YACb,MAAM,IAAI,aAA0C,CAAE,EAAC,CACxD;AAED,WAAO,OAAO,IAAI,gBAAgB,CAAC,CAAC,KAAK,QAAQ;AACjD,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,4BAA4B,YAAY;AACzC,UAAM,IAAI,aAAa,iBAAiB,GAAG;IAE3C,MAAM,SAAS,YACb,MAAM,IAAI,aAA0C,CAAE,EAAC,CACxD;AAED,WAAO,OAAO,IAAI,gBAAgB,CAAC,CAAC,KAAK,GAAG;AAC5C,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,6BAA6B,YAAY;AAC1C,UAAM,IAAI,aAAa,kBAAkB,KAAK;IAE9C,MAAM,SAAS,YACb,MAAM,IAAI,aAA4C,CAAE,EAAC,CAC1D;AAED,WAAO,OAAO,IAAI,iBAAiB,CAAC,CAAC,KAAK,KAAK;AAC/C,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,4BAA4B,YAAY;IACzC,MAAM,WAAW,EAAE,QAAQ,EAAE,OAAO,OAAQ,EAAE;AAC9C,UAAM,IAAI,aAAa,iBAAiB,SAAS;IAEjD,MAAM,SAAS,YACb,MAAM,IAAI,aAAmD,CAChD,EAAC,CACf;AAED,WAAO,OAAO,IAAI,gBAAgB,CAAC,CAAC,QAAQ,SAAS;AACrD,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,2BAA2B,YAAY;IACxC,MAAM,WAAW;KAAC;KAAG;KAAG;IAAE;AAC1B,UAAM,IAAI,aAAa,gBAAgB,SAAS;IAEhD,MAAM,SAAS,YACb,MAAM,IAAI,aAA2C,CAAE,EAAC,CACzD;AAED,WAAO,OAAO,IAAI,eAAe,CAAC,CAAC,QAAQ,SAAS;AACpD,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,0BAA0B,YAAY;AACvC,UAAM,IAAI,aAAa,eAAe,KAAK;IAE3C,MAAM,SAAS,YACb,MAAM,IAAI,aAAsC,CAAE,EAAC,CACpD;AAED,WAAO,OAAO,IAAI,cAAc,CAAC,CAAC,KAAK,KAAK;AAC5C,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,qDAAqD,YAAY;IAClE,MAAM,SAAS,YAAY,MAAM,IAAI,cAAc,CAAC;IACpD,MAAM,QAAQ,OAAO,IAAI,eAAe,EAAE,SAAS,WAAY,EAAC;AAChE,WAAO,MAAM,CAAC,KAAK,WAAW;AAC9B,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,kEAAkE,YAAY;IAC/E,MAAM,SAAS,YAAY,MAAM,IAAI,cAAc,CAAC;AACpD,QAAI;AACF,YAAO,IAAI,cAAc;AACzB,YAAO,KAAK,qBAAqB;IAClC,SAAQ,OAAO;AACd,YAAO,MAAM,CAAC,eAAe,aAAa;AAC1C,YAAQ,MAAuB,KAAK,CAAC,KAAK,iBAAiB,SAAS;IACrE;AACD,WAAO,YAAY;GACpB,EAAC;EACH,EAAC;AAIF,WAAS,qBAAqB,MAAM;AAClC,MAAG,kDAAkD,YAAY;AAC/D,UAAM,IAAI,aAAa,eAAe,UAAU;IAEhD,MAAM,SAAS,YACb,MAAM,IAAI,aAAwC,CAAE,EAAC,CACtD;AAED,WAAO,OAAO,IAAI,cAAc,CAAC,CAAC,KAAK,UAAU;IAGjD,MAAM,eAAe,cAAsB;AAC3C,WAAO,UAAU,eAAe,CAAC,WAAW;AAC1C,SAAI,OAAO,UAAU,UACnB,cAAa,QAAQ,OAAO,MAAgB;IAE/C,EAAC;AAGF,UAAM,IAAI,aAAa,eAAe,UAAU;IAGhD,MAAM,WAAW,MAAM,aAAa,KAAK,EAAE,SAAS,eAAgB,EAAC;AACrE,WAAO,SAAS,CAAC,KAAK,UAAU;AAGhC,WAAO,OAAO,IAAI,cAAc,CAAC,CAAC,KAAK,UAAU;AAEjD,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,4CAA4C,YAAY;AACzD,UAAM,IAAI,aAAa,uBAAuB,EAAE;IAEhD,MAAM,SAAS,YACb,MAAM,IAAI,aAAgD,CAC7C,EAAC,CACf;AAED,WAAO,OAAO,IAAI,sBAAsB,CAAC,CAAC,KAAK,EAAE;IAEjD,MAAM,YAAY,iBAAyB;AAC3C,WAAO,UAAU,uBAAuB,CAAC,WAAW;KAClD,MAAM,MAAM,OAAO;AACnB,SAAI,MAAM,EACR,WAAU,KAAK,IAAI;IAEtB,EAAC;AAGF,UAAM,IAAI,aAAa,uBAAuB,EAAE;AAChD,UAAM,MAAM,IAAI;AAChB,UAAM,IAAI,aAAa,uBAAuB,EAAE;AAChD,UAAM,MAAM,IAAI;AAChB,UAAM,IAAI,aAAa,uBAAuB,EAAE;IAGhD,MAAM,SAAS,MAAM,UAAU,aAAa,GAAG,EAAE,SAAS,eAAgB,EAAC;AAC3E,WAAO,OAAO,CAAC,QAAQ;KAAC;KAAG;KAAG;IAAE,EAAC;AAEjC,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,+BAA+B,YAAY;AAC5C,UAAM,IAAI,aAAa,gBAAgB,EAAE;IAEzC,MAAM,SAAS,YACb,MAAM,IAAI,aAAyC,CAAE,EAAC,CACvD;AAED,WAAO,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,EAAE;IAE1C,MAAM,YAAY,iBAAyB;AAC3C,WAAO,UAAU,gBAAgB,CAAC,WAAW;AAC3C,eAAU,KAAK,OAAO,MAAgB;IACvC,EAAC;IAGF,MAAM,cAAc;AACpB,SAAK,IAAI,IAAI,GAAG,KAAK,aAAa,IAChC,OAAM,IAAI,aAAa,gBAAgB,EAAE;AAI3C,UAAM,UAAU,QAAQ,CAAC,MAAM,MAAM,aAAa,EAAE,SAAS,eAAgB,EAAC;AAG9E,WAAO,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,YAAY;AAEpD,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,yDAAyD,YAAY;AACtE,UAAM,IAAI,aAAa,YAAY,IAAI;AACvC,UAAM,IAAI,aAAa,YAAY,IAAI;IAEvC,MAAM,SAAS,YACb,MAAM,IAAI,aAAyD,CACtD,EAAC,CACf;AAED,WAAO,OAAO,IAAI,WAAW,CAAC,CAAC,KAAK,IAAI;AACxC,WAAO,OAAO,IAAI,WAAW,CAAC,CAAC,KAAK,IAAI;IAExC,MAAM,YAAY,iBAAoD;AACtE,WAAO,UAAU,CAAC,WAAW;AAE3B,SAAI,OAAO,UAAU,eAAe,OAAO,UAAU,YACnD,WAAU,KAAK;MAAE,MAAM,OAAO;MAAM,OAAO,OAAO;KAAO,EAAC;IAE7D,EAAC;AAGF,UAAM,IAAI,aAAa,YAAY,YAAY;AAC/C,UAAM,IAAI,aAAa,YAAY,YAAY;AAG/C,UAAM,UAAU,aAAa,GAAG,EAAE,SAAS,eAAgB,EAAC;IAE5D,MAAM,SAAS,UAAU,WAAW;IACpC,MAAM,UAAU,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,WAAW;IACzD,MAAM,UAAU,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,WAAW;AAEzD,WAAO,SAAS,MAAM,CAAC,KAAK,YAAY;AACxC,WAAO,SAAS,MAAM,CAAC,KAAK,YAAY;AAExC,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,8BAA8B,YAAY;AAC3C,UAAM,IAAI,aAAa,gBAAgB,UAAU;IAEjD,MAAM,SAAS,YACb,MAAM,IAAI,aAAyC,CAAE,EAAC,CACvD;AAED,WAAO,OAAO,IAAI,eAAe,CAAC,CAAC,KAAK,UAAU;IAElD,MAAM,YAAY,iBAAyB;IAC3C,MAAM,cAAc,OAAO,UAAU,gBAAgB,CAAC,WAAW;AAC/D,SAAI,OAAO,UAAU,UACnB,WAAU,KAAK,OAAO,MAAgB;IAEzC,EAAC;AAGF,UAAM,IAAI,aAAa,gBAAgB,WAAW;AAClD,UAAM,UAAU,aAAa,GAAG,EAAE,SAAS,eAAgB,EAAC;AAG5D,iBAAa;AAGb,UAAM,IAAI,aAAa,gBAAgB,WAAW;AAClD,UAAM,MAAM,IAAK;AAGjB,WAAO,UAAU,OAAO,CAAC,CAAC,KAAK,EAAE;AAEjC,WAAO,YAAY;GACpB,EAAC;EACH,EAAC;AAIF,WAAS,uBAAuB,MAAM;AACpC,MAAG,oCAAoC,YAAY;AACjD,UAAM,IAAI,aAAa,cAAc,WAAW,EAC9C,WAAW,CACT;KACE,MAAM;KACN,YAAY,CAAC;MAAE,UAAU;MAAU,UAAU;MAAO,OAAO,QAAQ,aAAa;KAAE,CAAC;KACnF,OAAO;IACR,CACF,EACF,EAAC;IAGF,MAAM,UAAU,YACd,MAAM,IAAI,aAAuC,CAAE,EAAC,CACrD;AACD,WAAO,QAAQ,IAAI,aAAa,CAAC,CAAC,KAAK,UAAU;AACjD,YAAQ,YAAY;IAGpB,MAAM,UAAU,YACd,MAAM,IAAI,aAAuC,EAC/C,SAAS,EAAE,KAAK,aAAc,EACnB,EAAC,CACf;AACD,WAAO,QAAQ,IAAI,aAAa,CAAC,CAAC,KAAK,mBAAmB;AAC1D,YAAQ,YAAY;IAGpB,MAAM,UAAU,YACd,MAAM,IAAI,aAAuC,EAC/C,SAAS,EAAE,KAAK,UAAW,EAChB,EAAC,CACf;AACD,WAAO,QAAQ,IAAI,aAAa,CAAC,CAAC,KAAK,UAAU;AACjD,YAAQ,YAAY;GACrB,EAAC;AAEF,MAAG,gCAAgC,YAAY;AAC7C,UAAM,IAAI,aAAa,iBAAiB,WAAW,EACjD,WAAW,CACT;KACE,MAAM;KACN,YAAY,CAAC;MAAE,UAAU;MAAM,UAAU;MAAU,OAAO,QAAQ,CAAC,MAAM,IAAK,EAAC;KAAE,CAAC;KAClF,OAAO;IACR,CACF,EACF,EAAC;IAEF,MAAM,UAAU,YACd,MAAM,IAAI,aAA0C,EAClD,SAAS,EAAE,QAAQ,KAAM,EACd,EAAC,CACf;AACD,WAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,KAAK,UAAU;AACpD,YAAQ,YAAY;IAEpB,MAAM,UAAU,YACd,MAAM,IAAI,aAA0C,EAClD,SAAS,EAAE,QAAQ,KAAM,EACd,EAAC,CACf;AACD,WAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,KAAK,UAAU;AACpD,YAAQ,YAAY;IAEpB,MAAM,UAAU,YACd,MAAM,IAAI,aAA0C,EAClD,SAAS,EAAE,QAAQ,OAAQ,EAChB,EAAC,CACf;AACD,WAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,KAAK,UAAU;AACpD,YAAQ,YAAY;GACrB,EAAC;AAEF,MAAG,oCAAoC,YAAY;AACjD,UAAM,IAAI,aAAa,gBAAgB,WAAW,EAChD,WAAW,CACT;KACE,MAAM;KACN,YAAY,CACV;MACE,UAAU;MACV,UAAU;MACV,OAAO,QAAQ,CAAC,YAAY,UAAW,EAAC;KACzC,CACF;KACD,OAAO;IACR,CACF,EACF,EAAC;IAEF,MAAM,UAAU,YACd,MAAM,IAAI,aAAyC,EACjD,SAAS,EAAE,SAAS,WAAY,EACjC,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,eAAe,CAAC,CAAC,KAAK,UAAU;AACnD,YAAQ,YAAY;IAEpB,MAAM,UAAU,YACd,MAAM,IAAI,aAAyC,EACjD,SAAS,EAAE,SAAS,SAAU,EAC/B,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,eAAe,CAAC,CAAC,KAAK,cAAc;AACvD,YAAQ,YAAY;GACrB,EAAC;AAEF,MAAG,iDAAiD,YAAY;AAC9D,UAAM,IAAI,aAAa,eAAe,QAAQ,EAC5C,WAAW,CACT;KACE,MAAM;KACN,YAAY,CACV;MAAE,UAAU;MAAyB,UAAU;MAAS,OAAO,QAAQ,GAAG;KAAE,CAC7E;KACD,OAAO;IACR,CACF,EACF,EAAC;IAEF,MAAM,UAAU,YACd,MAAM,IAAI,aAAwC,EAChD,SAAS,EAAE,OAAO,EAAG,EACtB,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,cAAc,CAAC,CAAC,KAAK,OAAO;AAC/C,YAAQ,YAAY;IAEpB,MAAM,UAAU,YACd,MAAM,IAAI,aAAwC,EAChD,SAAS,EAAE,OAAO,GAAI,EACvB,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,cAAc,CAAC,CAAC,KAAK,UAAU;AAClD,YAAQ,YAAY;IAEpB,MAAM,UAAU,YACd,MAAM,IAAI,aAAwC,EAChD,SAAS,EAAE,OAAO,GAAI,EACvB,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,cAAc,CAAC,CAAC,KAAK,UAAU;AAClD,YAAQ,YAAY;GACrB,EAAC;AAEF,MAAG,iCAAiC,YAAY;AAC9C,UAAM,IAAI,aAAa,gBAAgB,WAAW,EAChD,WAAW,CACT;KACE,MAAM;KACN,YAAY,CACV;MACE,UAAU;MACV,YAAY,CACV;OAAE,UAAU;OAAU,UAAU;OAAQ,OAAO,QAAQ,aAAa;MAAE,GACtE;OAAE,UAAU;OAAU,UAAU;OAAY,OAAO,QAAQ,KAAK;MAAE,CACnE;KACF,CACF;KACD,OAAO;IACR,CACF,EACF,EAAC;IAGF,MAAM,UAAU,YACd,MAAM,IAAI,aAAyC,EACjD,SAAS;KAAE,MAAM;KAAc,UAAU;IAAM,EAChD,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,eAAe,CAAC,CAAC,KAAK,sBAAsB;AAC/D,YAAQ,YAAY;IAGpB,MAAM,UAAU,YACd,MAAM,IAAI,aAAyC,EACjD,SAAS;KAAE,MAAM;KAAc,UAAU;IAAO,EACjD,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,eAAe,CAAC,CAAC,KAAK,UAAU;AACnD,YAAQ,YAAY;GACrB,EAAC;AAEF,MAAG,gCAAgC,YAAY;AAC7C,UAAM,IAAI,aAAa,iBAAiB,WAAW,EACjD,WAAW,CACT;KACE,MAAM;KACN,YAAY,CACV;MACE,UAAU;MACV,YAAY,CACV;OAAE,UAAU;OAAU,UAAU;OAAQ,OAAO,QAAQ,QAAQ;MAAE,GACjE;OAAE,UAAU;OAAU,UAAU;OAAQ,OAAO,QAAQ,aAAa;MAAE,CACvE;KACF,CACF;KACD,OAAO;IACR,CACF,EACF,EAAC;IAEF,MAAM,UAAU,YACd,MAAM,IAAI,aAA0C,EAClD,SAAS,EAAE,MAAM,QAAS,EAC3B,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,KAAK,aAAa;AACvD,YAAQ,YAAY;IAEpB,MAAM,UAAU,YACd,MAAM,IAAI,aAA0C,EAClD,SAAS,EAAE,MAAM,aAAc,EAChC,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,KAAK,aAAa;AACvD,YAAQ,YAAY;IAEpB,MAAM,UAAU,YACd,MAAM,IAAI,aAA0C,EAClD,SAAS,EAAE,MAAM,OAAQ,EAC1B,EAAC,CACH;AACD,WAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,KAAK,UAAU;AACpD,YAAQ,YAAY;GACrB,EAAC;AAEF,MAAG,6CAA6C,YAAY;AAC1D,UAAM,IAAI,aAAa,kBAAkB,WAAW,EAClD,WAAW,CACT;KACE,MAAM;KACN,YAAY,CAAC;MAAE,UAAU;MAAU,UAAU;MAAW,OAAO,QAAQ,UAAU;KAAE,CAAC;KACpF,OAAO;IACR,CACF,EACF,EAAC;IAEF,MAAM,SAAS,YACb,MAAM,IAAI,aAA2C,CAAE,EAAC,CACzD;AAGD,WAAO,OAAO,IAAI,iBAAiB,CAAC,CAAC,KAAK,UAAU;AAGpD,WAAO,OAAO,IAAI,kBAAkB,EAAE,SAAS,EAAE,SAAS,UAAW,EAAE,EAAC,CAAC,CAAC,KACxE,aACD;AAGD,WAAO,OAAO,IAAI,iBAAiB,CAAC,CAAC,KAAK,UAAU;AAEpD,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,wCAAwC,YAAY;AACrD,UAAM,IAAI,aAAa,mBAAmB,WAAW,EACnD,WAAW;KACT;MACE,MAAM;MACN,YAAY,CAAC;OAAE,UAAU;OAAU,UAAU;OAAQ,OAAO,QAAQ,OAAO;MAAE,CAAC;MAC9E,OAAO;KACR;KACD;MACE,MAAM;MACN,YAAY,CAAC;OAAE,UAAU;OAAU,UAAU;OAAQ,OAAO,QAAQ,SAAS;MAAE,CAAC;MAChF,OAAO;KACR;KACD;MACE,MAAM;MACN,YAAY,CAAC;OAAE,UAAU;OAAgB,UAAU;OAAS,OAAO,QAAQ,EAAE;MAAE,CAAC;MAChF,OAAO;KACR;IACF,EACF,EAAC;IAGF,MAAM,SAAS,YACb,MAAM,IAAI,aAA4C,EACpD,SAAS;KAAE,MAAM;KAAQ,OAAO;IAAK,EACtC,EAAC,CACH;AACD,WAAO,OAAO,IAAI,kBAAkB,CAAC,CAAC,KAAK,aAAa;AACxD,WAAO,YAAY;GACpB,EAAC;EACH,EAAC;AAIF,WAAS,YAAY,MAAM;AACzB,MAAG,+CAA+C,YAAY;AAC5D,UAAM,IAAI,aAAa,iBAAiB,UAAU;AAClD,UAAM,IAAI,aAAa,iBAAiB,UAAU;IAElD,MAAM,SAAS,YACb,MAAM,IAAI,aAAmE,CAAE,EAAC,CACjF;IAED,MAAM,WAAW,OAAO,aAAa;AAErC,WAAO,SAAS,QAAQ,CAAC,uBAAuB;;;;;;;;;;;;;UAa9C;AACF,WAAO,SAAS,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,CACzD,iBACA,eACD,EAAC;AAEF,WAAO,YAAY;GACpB,EAAC;EAEH,EAAC;AAIF,WAAS,kBAAkB,MAAM;AAC/B,MAAG,mCAAmC,YAAY;IAChD,MAAM,gBAAgB,IAAI,QAAQ,EAChC,QAAQ,aACT;AACD,UAAM,OACJ,cAAc,QAAQ;KACpB,QAAQ;KACR,SAAS;KACT,kBAAkB;IACnB,EAAC,CACH,CAAC,QAAQ,SAAS;GACpB,EAAC;AAEF,MAAG,gDAAgD,YAAY;AAC7D,UAAM,IAAI,aAAa,cAAc,QAAQ;IAE7C,MAAM,SAAS,YACb,MAAM,IAAI,aAAuC,EAC/C,UAAU,EAAE,cAAc,UAAW,EACtC,EAAC,CACH;AAED,WAAO,OAAO,IAAI,aAAa,CAAC,CAAC,KAAK,QAAQ;AAE9C,WAAO,YAAY;IAInB,MAAM,cAAc,OAAO,IAAI,aAAa;AAC5C,WAAO,YAAY,CAAC,KAAK,QAAQ;GAClC,EAAC;AAEF,MAAG,wCAAwC,YAAY;IACrD,MAAM,oBAAoB,IAAI,QAAQ,EACpC,QAAQ,aACT;AACD,UAAM,OACJ,kBAAkB,QAAQ;KACxB,QAAQ;KACR,SAAS;KACT,kBAAkB;IACnB,EAAC,CACH,CAAC,QAAQ,SAAS;GACpB,EAAC;EACH,EAAC;AAIF,WAAS,oBAAoB,MAAM;AACjC,MAAG,uDAAuD,YAAY;IAEpE,MAAM,SAAS,YACb,MAAM,IAAI,aAAa,EAAE,UAAU,EAAE,eAAe,UAAW,EAAE,EAAC,CACnE;IAGD,MAAM,eAAe,cAAsB;AAC3C,WAAO,UAAU,eAAe,CAAC,WAAW;AAC1C,kBAAa,QAAQ,OAAO,MAAgB;IAC7C,EAAC;AAGF,UAAM,IAAI,aAAa,eAAe,aAAa;IAGnD,MAAM,QAAQ,MAAM,aAAa,KAAK,EAAE,SAAS,eAAgB,EAAC;AAClE,WAAO,MAAM,CAAC,KAAK,aAAa;AAEhC,WAAO,OAAO,IAAI,cAAc,CAAC,CAAC,KAAK,aAAa;AAEpD,WAAO,YAAY;GACpB,EAAC;AAEF,MAAG,2CAA2C,YAAY;AACxD,UAAM,IAAI,aAAa,aAAa,SAAS;IAE7C,MAAM,SAAS,YACb,MAAM,IAAI,aAAsC,CAAE,EAAC,CACpD;AAED,WAAO,OAAO,IAAI,YAAY,CAAC,CAAC,KAAK,SAAS;AAG9C,UAAM,IAAI,aAAa,YAAY;AAEnC,UAAM,MAAM,IAAK;AAEjB,WAAO,OAAO,IAAI,YAAY,CAAC,CAAC,KAAK,SAAS;AAE9C,WAAO,YAAY;GACpB,EAAC;EACH,EAAC;AAIF,WAAS,sBAAsB,MAAM;AACnC,MAAG,oDAAoD,YAAY;AACjE,UAAM,IAAI,aAAa,iBAAiB,UAAU;IAElD,MAAM,UAAU,YACd,MAAM,IAAI,aAA0C,CAAE,EAAC,CACxD;IACD,MAAM,UAAU,YACd,MAAM,IAAI,aAA0C,CAAE,EAAC,CACxD;AAED,WAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,KAAK,UAAU;AACpD,WAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,KAAK,UAAU;IAGpD,MAAM,UAAU,cAAsB;IACtC,MAAM,UAAU,cAAsB;AAEtC,YAAQ,UAAU,iBAAiB,CAAC,MAAM;AACxC,SAAI,EAAE,UAAU,UAAW,SAAQ,QAAQ,EAAE,MAAgB;IAC9D,EAAC;AACF,YAAQ,UAAU,iBAAiB,CAAC,MAAM;AACxC,SAAI,EAAE,UAAU,UAAW,SAAQ,QAAQ,EAAE,MAAgB;IAC9D,EAAC;AAEF,UAAM,IAAI,aAAa,iBAAiB,UAAU;IAElD,MAAM,CAAC,IAAI,GAAG,GAAG,MAAM,QAAQ,IAAI,CACjC,QAAQ,KAAK,EAAE,SAAS,eAAgB,EAAC,EACzC,QAAQ,KAAK,EAAE,SAAS,eAAgB,EAAC,AAC1C,EAAC;AAEF,WAAO,GAAG,CAAC,KAAK,UAAU;AAC1B,WAAO,GAAG,CAAC,KAAK,UAAU;AAE1B,YAAQ,YAAY;AACpB,YAAQ,YAAY;GACrB,EAAC;AAEF,MAAG,0CAA0C,YAAY;AACvD,UAAM,IAAI,aAAa,kBAAkB,WAAW,EAClD,WAAW,CACT;KACE,MAAM;KACN,YAAY,CAAC;MAAE,UAAU;MAAU,UAAU;MAAO,OAAO,QAAQ,OAAO;KAAE,CAAC;KAC7E,OAAO;IACR,CACF,EACF,EAAC;IAEF,MAAM,UAAU,YACd,MAAM,IAAI,aAA2C,EACnD,SAAS,EAAE,KAAK,OAAQ,EACzB,EAAC,CACH;IACD,MAAM,UAAU,YACd,MAAM,IAAI,aAA2C,EACnD,SAAS,EAAE,KAAK,MAAO,EACxB,EAAC,CACH;AAED,WAAO,QAAQ,IAAI,iBAAiB,CAAC,CAAC,KAAK,aAAa;AACxD,WAAO,QAAQ,IAAI,iBAAiB,CAAC,CAAC,KAAK,UAAU;AAErD,YAAQ,YAAY;AACpB,YAAQ,YAAY;GACrB,EAAC;EACH,EAAC;CACH,EAAC;AACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replanejs/test-suite",
3
- "version": "0.8.20",
3
+ "version": "0.9.2",
4
4
  "description": "End-to-end test suite for Replane SDK and Admin API",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,8 +39,8 @@
39
39
  ],
40
40
  "sideEffects": false,
41
41
  "dependencies": {
42
- "@replanejs/admin": "^0.8.20",
43
- "@replanejs/sdk": "^0.8.20"
42
+ "@replanejs/admin": "^0.9.2",
43
+ "@replanejs/sdk": "^0.9.2"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "vitest": ">=2.0.0"