Unified · Split
| @@ -327,6 +327,14 @@ for (const origin of ["integration", "workspace"] as const) { · 326 unmodified lines | ||
| 327 | 327 | }); |
| 328 | 328 | yield* Effect.addFinalizer(() => |
| 329 | 329 | Effect.gen(function* () { |
| 330 | + const connections = yield* client.connections.list({ query: { integration: slug } }); | |
| 331 | + for (const connection of connections) { | |
| 332 | + yield* client.connections | |
| 333 | + .remove({ | |
| 334 | + params: { owner: connection.owner, integration: slug, name: connection.name }, | |
| 335 | + }) | |
| 336 | + .pipe(Effect.ignore); | |
| 337 | + } | |
| 330 | 338 | yield* client.mcp.removeServer({ params: { slug } }).pipe(Effect.ignore); |
| 331 | 339 | yield* client.oauth |
| 332 | 340 | .removeClient({ params: { slug: app }, payload: { owner: "org" } }) |
| @@ -355,17 +363,13 @@ for (const origin of ["integration", "workspace"] as const) { · 22 unmodified lines | ||
| 355 | 363 | ...(origin === "integration" ? { originIntegration: slug } : {}), |
| 356 | 364 | }, |
| 357 | 365 | }); |
| 358 | − const savedClients = yield* client.oauth.listClients({}); | |
| 359 | − expect(savedClients.find((saved) => saved.slug === app)?.origin).toEqual( | |
| 360 | − origin === "integration" | |
| 361 | − ? { kind: "manual", integration: slug } | |
| 362 | − : { kind: "manual", integration: null }, | |
| 363 | − ); | |
| 364 | 366 | yield* Effect.promise(() => emulator.ledger.clear()); |
| 365 | 367 | yield* browser.session(identity, async ({ page, step }) => { |
| 366 | 368 | await step("Open an integration that already has a saved OAuth app", async () => { |
| 367 | 369 | await visit(page, `/integrations/${slug}?addAccount=1`); |
| 368 | 370 | await page.getByRole("tab", { name: "OAuth", exact: true }).waitFor(); |
| 371 | + }); | |
| 372 | + await step("Connect once using the saved app", async () => { | |
| 369 | 373 | const opened = page.waitForEvent("popup"); |
| 370 | 374 | await page.getByRole("button", { name: /^Connect(?: with OAuth)?$/ }).click(); |
| 371 | 375 | const popup = await opened; |
| @@ -374,14 +378,28 @@ for (const origin of ["integration", "workspace"] as const) { · 2 unmodified lines | ||
| 374 | 378 | new URL(popup.url()).searchParams.get("client_id"), |
| 375 | 379 | "the existing app is reused without another registration step", |
| 376 | 380 | ).toBe(registered.client_id); |
| 377 | − await popup.close(); | |
| 381 | + }); | |
| 382 | + await step("Approve provider sign-in and save the connection", async () => { | |
| 383 | + const popup = page | |
| 384 | + .context() | |
| 385 | + .pages() | |
| 386 | + .find((candidate) => candidate !== page); | |
| 387 | + if (!popup) throw new Error("Provider sign-in window was not open"); | |
| 388 | + await popup.getByRole("button", { name: /admin/ }).click(); | |
| 378 | 389 | await page |
| 379 | − .getByRole("dialog") | |
| 380 | − .getByRole("button", { name: "Close", exact: true }) | |
| 381 | − .last() | |
| 382 | − .click(); | |
| 390 | + .getByRole("heading", { name: /Add connection/ }) | |
| 391 | + .waitFor({ state: "hidden", timeout: 30_000 }); | |
| 383 | 392 | }); |
| 384 | 393 | }); |
| 394 | + const connections = yield* client.connections.list({ query: { integration: slug } }); | |
| 395 | + expect(connections, "provider consent saves the connection").toHaveLength(1); | |
| 396 | + expect(connections[0]?.owner, "a shared app keeps the connection personal").toBe("user"); | |
| 397 | + const savedClients = yield* client.oauth.listClients({}); | |
| 398 | + expect(savedClients.find((saved) => saved.slug === app)?.origin).toEqual( | |
| 399 | + origin === "integration" | |
| 400 | + ? { kind: "manual", integration: slug } | |
| 401 | + : { kind: "manual", integration: null }, | |
| 402 | + ); | |
| 385 | 403 | const ledger = yield* Effect.promise(() => emulator.ledger.list()); |
| 386 | 404 | expect( |
| 387 | 405 | ledger.filter((entry) => entry.method === "POST" && entry.path === "/register"), |