(authorizationUrl: string)
| 62 | /** Drive the test AS's consent by hand (authorize → login → code), without |
| 63 | * visiting the app's callback: `oauth.complete` takes the code directly. */ |
| 64 | const completeAuthorization = (authorizationUrl: string) => |
| 65 | Effect.promise(async () => { |
| 66 | const authorize = await fetch(authorizationUrl, { redirect: "manual" }); |
| 67 | const loginUrl = authorize.headers.get("location"); |
| 68 | if (!loginUrl) throw new Error(`authorize did not redirect: ${authorize.status}`); |
| 69 | const login = await fetch(loginUrl, { |
| 70 | method: "POST", |
| 71 | headers: { authorization: `Basic ${Buffer.from("alice:password").toString("base64")}` }, |
| 72 | redirect: "manual", |
| 73 | }); |
| 74 | const callbackUrl = login.headers.get("location"); |
| 75 | if (!callbackUrl) throw new Error(`login did not redirect: ${login.status}`); |
| 76 | const code = new URL(callbackUrl).searchParams.get("code"); |
| 77 | if (!code) throw new Error("callback carried no authorization code"); |
| 78 | return code; |
| 79 | }); |
| 80 | |
| 81 | /** Simulate the non-durable secret store being lost on sandbox recreate: drop |
| 82 | * every entry under this run's keychain service. On macOS `security` deletes |
no test coverage detected