Public: anyone can read this; the crew can change it.
Fast test/apps-token.test.ts: chop and rewrite under the budget (1 s a test, 10 s a file) #12065
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/1255-fast-test-apps-token-test-ts-chop-and-re → main 2 commits fork
1 file
changed +28
−15
test/apps-token.test.ts +28 −15
| @@ -185,6 +185,7 @@ describe("app tokens: live, end to end", () => { | ||
| 185 | 185 | let bob: User; |
| 186 | 186 | let repo: Repo; |
| 187 | 187 | let record: AppRecord; |
| 188 | let skew = 0; | |
| 188 | 189 | const DOMAIN = "apps.test"; |
| 189 | 190 | const HOST = `live.${DOMAIN}`; |
| 190 | 191 | |
| @@ -202,7 +203,7 @@ describe("app tokens: live, end to end", () => { | ||
| 202 | 203 | (r) => where(r) && (r.state === "ok" || r.state === "failed"), |
| 203 | 204 | ); |
| 204 | 205 | if (run) return run; |
| 205 | await Bun.sleep(100); | |
| 206 | await Bun.sleep(10); // real-timer: polls a deploy worker running in the background | |
| 206 | 207 | } |
| 207 | 208 | throw new Error("run did not settle in time"); |
| 208 | 209 | } |
| @@ -231,7 +232,8 @@ describe("app tokens: live, end to end", () => { | ||
| 231 | 232 | scheme: "http", |
| 232 | 233 | publicPort: servers.port, |
| 233 | 234 | forgeUrl: servers.url, |
| 234 | sweepEveryMs: 200, | |
| 235 | sweepEveryMs: 20, | |
| 236 | clock: () => Date.now() + skew, | |
| 235 | 237 | }); |
| 236 | 238 | await runtime.start(); |
| 237 | 239 | alice = await user(app, "alice"); |
| @@ -298,16 +300,15 @@ describe("app tokens: live, end to end", () => { | ||
| 298 | 300 | const [hers, his] = await Promise.all([listen(aliceRo), listen(bobRo)]); |
| 299 | 301 | expect(hers.status).toBe(200); |
| 300 | 302 | expect(hers.headers.get("content-type")).toContain("text/event-stream"); |
| 301 | const opened = openIssue(app, alice, secret.value, { | |
| 302 | title: "the private plan", | |
| 303 | }); | |
| 304 | expect(opened.ok).toBe(true); | |
| 303 | // The private issue first, then a public one both may read: events | |
| 304 | // arrive in order, so by the time bob hears the public one he would | |
| 305 | // have heard the private one. No waiting for silence. | |
| 306 | expect(openIssue(app, alice, secret.value, { title: "the private plan" }).ok).toBe(true); | |
| 307 | expect(openIssue(app, alice, repo, { title: "the public plan" }).ok).toBe(true); | |
| 305 | 308 | const heard = await readUntil(hers, (t) => t.includes("alice/secret")); |
| 306 | 309 | expect(heard).toContain("event: forge"); |
| 307 | // Bob cannot read alice/secret: his stream stays quiet about it. | |
| 308 | await expect( | |
| 309 | readUntil(his, (t) => t.includes("alice/secret"), 1_000), | |
| 310 | ).rejects.toThrow("did not say it"); | |
| 310 | const bobHeard = await readUntil(his, (t) => t.includes("alice/live")); | |
| 311 | expect(bobHeard).not.toContain("alice/secret"); | |
| 311 | 312 | }); |
| 312 | 313 | |
| 313 | 314 | test("acceptance: the sample page lists `now`, offers `say`, and goes live on /events", async () => { |
| @@ -348,17 +349,29 @@ describe("app tokens: live, end to end", () => { | ||
| 348 | 349 | }); |
| 349 | 350 | expect(stream.status).toBe(200); |
| 350 | 351 | const said = readUntil(stream, (t) => t.includes("event: changed")); |
| 351 | await Bun.sleep(300); // let the relay open its upstream | |
| 352 | openIssue(app, alice, repo, { title: "Another thing" }); | |
| 353 | expect(await said).toContain("data: {}"); | |
| 352 | // The relay opens its upstream a moment after it answers: say | |
| 353 | // something until it hears. | |
| 354 | const poke = setInterval( | |
| 355 | () => openIssue(app, alice, repo, { title: "Another thing" }), | |
| 356 | 15, | |
| 357 | ); | |
| 358 | try { | |
| 359 | expect(await said).toContain("data: {}"); | |
| 360 | } finally { | |
| 361 | clearInterval(poke); | |
| 362 | } | |
| 354 | 363 | // And the fragment the page refetches lists the same runs. |
| 355 | 364 | expect(await (await viaHost("/now")).text()).toContain("bob"); |
| 356 | 365 | }, 30_000); |
| 357 | 366 | |
| 358 | 367 | test("the sweep renews a running environment's token", async () => { |
| 359 | 368 | const before = appTokens("production")[0]!; |
| 360 | await Bun.sleep(1_100); | |
| 361 | const after = appTokens("production")[0]!; | |
| 369 | skew += 60_000; // the sweep's clock moves a minute; no waiting for it | |
| 370 | let after = appTokens("production")[0]!; | |
| 371 | for (let i = 0; i < 500 && after.expiresAt === before.expiresAt; i++) { | |
| 372 | await Bun.sleep(5); // real-timer: the sweep runs on its own 20 ms interval; its clock is already faked | |
| 373 | after = appTokens("production")[0]!; | |
| 374 | } | |
| 362 | 375 | expect(after.id).toBe(before.id); |
| 363 | 376 | expect(Date.parse(after.expiresAt!)).toBeGreaterThan( |
| 364 | 377 | Date.parse(before.expiresAt!), |
new above
offline