Adapt the server integration test to the new standalone OAuth endpoints that store secrets without creating a source. Add workspace execution environment tests for GraphQL tool loading and invocation. Update auth service and control-plane runtime tests for the refactored APIs.
Showing the changes to apps (1 of 5 files). Show all
Unified · Split
| @@ -802,7 +802,7 @@ describe("local-executor-server", () => { · 801 unmodified lines | |||
| 802 | }), | 802 | }), |
| 803 | ); | 803 | ); |
| 804 | 804 | ||
| 805 | it.scoped("starts MCP OAuth from the sources API and completes the popup callback flow", () => | 805 | it.scoped("starts source OAuth without creating a source and stores secrets on callback", () => |
| 806 | Effect.gen(function* () { | 806 | Effect.gen(function* () { |
| 807 | const oauthServer = yield* Effect.acquireRelease( | 807 | const oauthServer = yield* Effect.acquireRelease( |
| 808 | Effect.promise(() => startOAuthProtectedMcpServer()), | 808 | Effect.promise(() => startOAuthProtectedMcpServer()), |
| @@ -820,16 +820,15 @@ describe("local-executor-server", () => { · 11 unmodified lines | |||
| 820 | const installation = yield* bootstrapClient.local.installation({}); | 820 | const installation = yield* bootstrapClient.local.installation({}); |
| 821 | 821 | ||
| 822 | const startResponse = yield* Effect.promise(() => | 822 | const startResponse = yield* Effect.promise(() => |
| 823 | fetch(`${server.baseUrl}/v1/workspaces/${encodeURIComponent(installation.workspaceId)}/sources/mcp/oauth/start`, { | 823 | fetch(`${server.baseUrl}/v1/workspaces/${encodeURIComponent(installation.workspaceId)}/oauth/source-auth/start`, { |
| 824 | method: "POST", | 824 | method: "POST", |
| 825 | headers: { | 825 | headers: { |
| 826 | "content-type": "application/json", | 826 | "content-type": "application/json", |
| 827 | "x-executor-account-id": installation.accountId, | 827 | "x-executor-account-id": installation.accountId, |
| 828 | }, | 828 | }, |
| 829 | body: JSON.stringify({ | 829 | body: JSON.stringify({ |
| 830 | provider: "mcp", | ||
| 830 | endpoint: oauthServer.endpoint, | 831 | endpoint: oauthServer.endpoint, |
| 831 | name: "Axiom", | ||
| 832 | namespace: "axiom", | ||
| 833 | transport: "auto", | 832 | transport: "auto", |
| 834 | }), | 833 | }), |
| 835 | }), | 834 | }), |
| @@ -837,29 +836,26 @@ describe("local-executor-server", () => { · 1 unmodified line | |||
| 837 | 836 | ||
| 838 | assertTrue(startResponse.ok); | 837 | assertTrue(startResponse.ok); |
| 839 | const started: { | 838 | const started: { |
| 840 | kind: "connected" | "oauth_required"; | 839 | sessionId: string; |
| 841 | source: { id: string; status: string; auth: { kind: string } }; | 840 | authorizationUrl: string; |
| 842 | authorizationUrl?: string; | ||
| 843 | } = yield* Effect.promise(() => startResponse.json() as Promise<{ | 841 | } = yield* Effect.promise(() => startResponse.json() as Promise<{ |
| 844 | kind: "connected" | "oauth_required"; | 842 | sessionId: string; |
| 845 | source: { id: string; status: string; auth: { kind: string } }; | 843 | authorizationUrl: string; |
| 846 | authorizationUrl?: string; | ||
| 847 | }>); | 844 | }>); |
| 848 | 845 | ||
| 849 | expect(started.kind).toBe("oauth_required"); | 846 | expect(started.sessionId).toBeTruthy(); |
| 850 | expect(started.source.status).toBe("auth_required"); | ||
| 851 | expect(started.authorizationUrl).toBeDefined(); | 847 | expect(started.authorizationUrl).toBeDefined(); |
| 852 | 848 | ||
| 853 | const callbackResponse = yield* Effect.promise(() => | 849 | const callbackResponse = yield* Effect.promise(() => |
| 854 | fetch(started.authorizationUrl!, { | 850 | fetch(started.authorizationUrl, { |
| 855 | redirect: "follow", | 851 | redirect: "follow", |
| 856 | }), | 852 | }), |
| 857 | ); | 853 | ); |
| 858 | 854 | ||
| 859 | assertTrue(callbackResponse.ok); | 855 | assertTrue(callbackResponse.ok); |
| 860 | const callbackHtml = yield* Effect.promise(() => callbackResponse.text()); | 856 | const callbackHtml = yield* Effect.promise(() => callbackResponse.text()); |
| 861 | expect(callbackHtml).toContain("Source connected:"); | 857 | expect(callbackHtml).toContain("OAuth connected"); |
| 862 | expect(callbackHtml).toContain("executor-v3:source-oauth-result"); | 858 | expect(callbackHtml).toContain("executor-v3:oauth-result"); |
| 863 | 859 | ||
| 864 | const client = yield* createControlPlaneClient({ | 860 | const client = yield* createControlPlaneClient({ |
| 865 | baseUrl: server.baseUrl, | 861 | baseUrl: server.baseUrl, |
| @@ -870,12 +866,12 @@ describe("local-executor-server", () => { · 4 unmodified lines | |||
| 870 | workspaceId: installation.workspaceId, | 866 | workspaceId: installation.workspaceId, |
| 871 | }, | 867 | }, |
| 872 | }); | 868 | }); |
| 873 | const source = sources.find((candidate) => candidate.id === started.source.id); | ||
| 874 | 869 | ||
| 875 | assertTrue(Boolean(source)); | 870 | expect(sources).toHaveLength(0); |
| 876 | 871 | ||
| 877 | expect(source?.status).toBe("connected"); | 872 | const secrets = yield* bootstrapClient.local.listSecrets({}); |
| 878 | expect(source?.auth.kind).toBe("oauth2"); | 873 | expect(secrets.some((secret) => secret.purpose === "oauth_access_token")).toBe(true); |
| 874 | expect(secrets.some((secret) => secret.purpose === "oauth_refresh_token")).toBe(true); | ||
| 879 | }), | 875 | }), |
| 880 | ); | 876 | ); |
| 881 | 877 | ||