|
| 1 | +import { http, HttpResponse } from "msw"; |
1 | 2 | import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; |
2 | 3 |
|
3 | 4 | import { ReflagClient } from "../src/client"; |
4 | 5 | import { FlagsClient } from "../src/flag/flags"; |
5 | 6 | import { HttpClient } from "../src/httpClient"; |
6 | 7 | import { flagsResult } from "./mocks/handlers"; |
| 8 | +import { server } from "./mocks/server"; |
7 | 9 |
|
8 | 10 | describe("ReflagClient", () => { |
9 | 11 | let client: ReflagClient; |
@@ -71,6 +73,84 @@ describe("ReflagClient", () => { |
71 | 73 | "No company Id provided in context, company will be ignored", |
72 | 74 | ); |
73 | 75 | }); |
| 76 | + |
| 77 | + it("starts flushing the user update before refetching flags without waiting for it", async () => { |
| 78 | + const requests: string[] = []; |
| 79 | + let bulkResolved = false; |
| 80 | + let resolveBulk: ((response: HttpResponse) => void) | undefined; |
| 81 | + const bulkResponse = new Promise<HttpResponse>((resolve) => { |
| 82 | + resolveBulk = (response) => { |
| 83 | + bulkResolved = true; |
| 84 | + resolve(response); |
| 85 | + }; |
| 86 | + }); |
| 87 | + |
| 88 | + server.use( |
| 89 | + http.post("https://front.reflag.com/bulk", async ({ request }) => { |
| 90 | + requests.push("bulk"); |
| 91 | + const data = await request.json(); |
| 92 | + const userEvent = Array.isArray(data) |
| 93 | + ? data.find((event) => event?.type === "user") |
| 94 | + : undefined; |
| 95 | + expect(userEvent?.attributes?.siteCentricOptIn).toBe("true"); |
| 96 | + |
| 97 | + return bulkResponse; |
| 98 | + }), |
| 99 | + http.get( |
| 100 | + "https://front.reflag.com/features/evaluated", |
| 101 | + ({ request }) => { |
| 102 | + requests.push("flags"); |
| 103 | + const url = new URL(request.url); |
| 104 | + expect(url.searchParams.get("context.user.siteCentricOptIn")).toBe( |
| 105 | + "true", |
| 106 | + ); |
| 107 | + |
| 108 | + return HttpResponse.json({ |
| 109 | + success: true, |
| 110 | + features: { |
| 111 | + SITE_CENTRIC: { |
| 112 | + key: "SITE_CENTRIC", |
| 113 | + isEnabled: true, |
| 114 | + targetingVersion: 1, |
| 115 | + }, |
| 116 | + }, |
| 117 | + }); |
| 118 | + }, |
| 119 | + ), |
| 120 | + ); |
| 121 | + |
| 122 | + client = new ReflagClient({ |
| 123 | + publishableKey: "test-key-user-update-before-flags", |
| 124 | + user: { id: "user1" }, |
| 125 | + bootstrappedFlags: { |
| 126 | + SITE_CENTRIC: { |
| 127 | + key: "SITE_CENTRIC", |
| 128 | + isEnabled: false, |
| 129 | + targetingVersion: 1, |
| 130 | + }, |
| 131 | + }, |
| 132 | + trackingQueue: { |
| 133 | + flushDelayMs: 2_000, |
| 134 | + }, |
| 135 | + }); |
| 136 | + await client.initialize(); |
| 137 | + |
| 138 | + const updatePromise = client.updateUser({ siteCentricOptIn: "true" }); |
| 139 | + |
| 140 | + try { |
| 141 | + await vi.waitFor(() => expect(requests).toEqual(["bulk", "flags"])); |
| 142 | + |
| 143 | + let updateResolved = false; |
| 144 | + void updatePromise.then(() => { |
| 145 | + updateResolved = true; |
| 146 | + }); |
| 147 | + await vi.waitFor(() => expect(updateResolved).toBe(true)); |
| 148 | + expect(bulkResolved).toBe(false); |
| 149 | + } finally { |
| 150 | + resolveBulk?.(HttpResponse.json({ success: true })); |
| 151 | + await updatePromise; |
| 152 | + } |
| 153 | + }); |
74 | 154 | }); |
75 | 155 |
|
76 | 156 | describe("updateCompany", () => { |
@@ -100,6 +180,50 @@ describe("ReflagClient", () => { |
100 | 180 | ); |
101 | 181 | expect(flagClientSetContext).toHaveBeenCalledWith(client["context"]); |
102 | 182 | }); |
| 183 | + |
| 184 | + it("starts flushing the company update before refetching flags", async () => { |
| 185 | + const requests: string[] = []; |
| 186 | + let resolveCompanyPlan: ((plan: unknown) => void) | undefined; |
| 187 | + const companyPlan = new Promise<unknown>((resolve) => { |
| 188 | + resolveCompanyPlan = resolve; |
| 189 | + }); |
| 190 | + |
| 191 | + server.use( |
| 192 | + http.post("https://front.reflag.com/bulk", async ({ request }) => { |
| 193 | + requests.push("bulk"); |
| 194 | + const data = await request.json(); |
| 195 | + const companyEvent = Array.isArray(data) |
| 196 | + ? data.find((event) => event?.type === "company") |
| 197 | + : undefined; |
| 198 | + resolveCompanyPlan?.(companyEvent?.attributes?.plan); |
| 199 | + |
| 200 | + return HttpResponse.json({ success: true }); |
| 201 | + }), |
| 202 | + http.get("https://front.reflag.com/features/evaluated", () => { |
| 203 | + requests.push("flags"); |
| 204 | + return HttpResponse.json({ |
| 205 | + success: true, |
| 206 | + features: {}, |
| 207 | + }); |
| 208 | + }), |
| 209 | + ); |
| 210 | + |
| 211 | + client = new ReflagClient({ |
| 212 | + publishableKey: "test-key-company-update-before-flags", |
| 213 | + user: { id: "user1" }, |
| 214 | + company: { id: "company1" }, |
| 215 | + bootstrappedFlags: {}, |
| 216 | + trackingQueue: { |
| 217 | + flushDelayMs: 2_000, |
| 218 | + }, |
| 219 | + }); |
| 220 | + await client.initialize(); |
| 221 | + |
| 222 | + await client.updateCompany({ plan: "enterprise" }); |
| 223 | + |
| 224 | + expect(requests).toEqual(["bulk", "flags"]); |
| 225 | + await expect(companyPlan).resolves.toBe("enterprise"); |
| 226 | + }); |
103 | 227 | }); |
104 | 228 |
|
105 | 229 | describe("getFlag", () => { |
|
0 commit comments