import { assert, describe, it } from "@effect/vitest"; import * as NodeServices from "@effect/platform-node/NodeServices"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as ElectronApp from "../electron/ElectronApp.ts"; import * as ElectronWindow from "../electron/ElectronWindow.ts"; import * as IpcChannels from "../ipc/channels.ts"; import * as DesktopCloudAuth from "./DesktopCloudAuth.ts"; import * as DesktopEnvironment from "./DesktopEnvironment.ts"; interface CloudAuthHarness { readonly app: ElectronApp.ElectronAppShape; readonly window: ElectronWindow.ElectronWindowShape; readonly listeners: Map void)[]>; readonly protocolRegistrations: { readonly protocol: string; readonly path?: string; readonly args?: readonly string[]; }[]; readonly sends: { readonly channel: string; readonly args: readonly unknown[] }[]; readonly reveals: unknown[]; readonly layer: Layer.Layer< | DesktopCloudAuth.DesktopCloudAuth | DesktopEnvironment.DesktopEnvironment | ElectronApp.ElectronApp | ElectronWindow.ElectronWindow >; } function makeHarness(input: { readonly isDevelopment: boolean }): CloudAuthHarness { const listeners = new Map void)[]>(); const protocolRegistrations: CloudAuthHarness["protocolRegistrations"] = []; const sends: CloudAuthHarness["sends"] = []; const reveals: unknown[] = []; const mainWindow = { id: "main-window" }; const app = ElectronApp.ElectronApp.of({ metadata: Effect.succeed({ appVersion: "0.0.0-test", appPath: "/tmp/t3-code-test", isPackaged: !input.isDevelopment, resourcesPath: "/tmp/t3-code-test/resources", runningUnderArm64Translation: false, }), name: Effect.succeed("T3 Code"), whenReady: Effect.void, quit: Effect.void, exit: () => Effect.void, relaunch: () => Effect.void, setPath: () => Effect.void, setName: () => Effect.void, setAboutPanelOptions: () => Effect.void, setAppUserModelId: () => Effect.void, requestSingleInstanceLock: Effect.succeed(true), isDefaultProtocolClient: () => Effect.succeed(false), setAsDefaultProtocolClient: (protocol, path, args) => Effect.sync(() => { protocolRegistrations.push({ protocol, ...(path === undefined ? {} : { path }), ...(args === undefined ? {} : { args }), }); return true; }), setDesktopName: () => Effect.void, setDockIcon: () => Effect.void, appendCommandLineSwitch: () => Effect.void, on: (eventName, listener) => Effect.sync(() => { const erasedListener = listener as (...args: readonly unknown[]) => void; listeners.set(eventName, [...(listeners.get(eventName) ?? []), erasedListener]); }), }); const window = ElectronWindow.ElectronWindow.of({ create: () => Effect.die("not used"), main: Effect.succeed(Option.some(mainWindow as never)), currentMainOrFirst: Effect.succeed(Option.some(mainWindow as never)), focusedMainOrFirst: Effect.succeed(Option.some(mainWindow as never)), setMain: () => Effect.void, clearMain: () => Effect.void, reveal: (target) => Effect.sync(() => { reveals.push(target); }), sendAll: (channel, ...args) => Effect.sync(() => { sends.push({ channel, args }); }), destroyAll: Effect.void, syncAllAppearance: () => Effect.void, }); const environment = DesktopEnvironment.DesktopEnvironment.of({ isDevelopment: input.isDevelopment, } as DesktopEnvironment.DesktopEnvironmentShape); const environmentLayer = Layer.succeed(DesktopEnvironment.DesktopEnvironment, environment); return { app, window, listeners, protocolRegistrations, sends, reveals, layer: Layer.mergeAll( DesktopCloudAuth.layer.pipe( Layer.provideMerge(environmentLayer), Layer.provide(NodeServices.layer), ), Layer.succeed(ElectronApp.ElectronApp, app), Layer.succeed(ElectronWindow.ElectronWindow, window), ), }; } function emitAppEvent( harness: CloudAuthHarness, eventName: string, ...args: readonly unknown[] ): void { for (const listener of harness.listeners.get(eventName) ?? []) { listener(...args); } } const flushCloudAuthDispatch = Effect.promise(() => Promise.resolve()); describe("DesktopCloudAuth", () => { it("uses separate callback schemes for packaged and development builds", () => { assert.equal( DesktopCloudAuth.resolveCloudAuthCallbackScheme({ isDevelopment: false }), "t3code", ); assert.equal( DesktopCloudAuth.resolveCloudAuthCallbackScheme({ isDevelopment: true }), "t3code-dev", ); }); it("builds a native callback URL with request state", () => { assert.equal( DesktopCloudAuth.buildCloudAuthCallbackUrl({ scheme: "t3code", state: "state-1", }), "t3code://auth/callback?t3_state=state-1", ); }); it("accepts only the expected scheme, host, path, and state", () => { assert.isNotNull( DesktopCloudAuth.parseCloudAuthCallbackUrl({ rawUrl: "t3code://auth/callback?rotating_token_nonce=nonce&t3_state=state-1", scheme: "t3code", state: "state-1", }), ); assert.isNull( DesktopCloudAuth.parseCloudAuthCallbackUrl({ rawUrl: "t3code://auth/callback?rotating_token_nonce=nonce&t3_state=wrong", scheme: "t3code", state: "state-1", }), ); assert.isNull( DesktopCloudAuth.parseCloudAuthCallbackUrl({ rawUrl: "https://example.com/callback?rotating_token_nonce=nonce&t3_state=state-1", scheme: "t3code", state: "state-1", }), ); }); it("builds a native development callback URL with request state", () => { assert.equal( DesktopCloudAuth.buildCloudAuthCallbackUrl({ scheme: "t3code-dev", state: "state-1", }), "t3code-dev://auth/callback?t3_state=state-1", ); }); it.effect("registers the development protocol client and dispatches matching callbacks", () => { const harness = makeHarness({ isDevelopment: true }); return Effect.gen(function* () { const cloudAuth = yield* DesktopCloudAuth.DesktopCloudAuth; yield* cloudAuth.configure; const redirectUrl = yield* cloudAuth.createRequest; const callbackUrl = new URL(redirectUrl); callbackUrl.searchParams.set("rotating_token_nonce", "nonce-1"); let prevented = false; emitAppEvent( harness, "open-url", { preventDefault: () => (prevented = true) }, callbackUrl.toString(), ); yield* flushCloudAuthDispatch; assert.isTrue(prevented); assert.deepEqual( harness.protocolRegistrations.map((registration) => registration.protocol), ["t3code-dev"], ); assert.isString(harness.protocolRegistrations[0]?.path); assert.isArray(harness.protocolRegistrations[0]?.args); assert.deepEqual(harness.sends, [ { channel: IpcChannels.CLOUD_AUTH_CALLBACK_CHANNEL, args: [callbackUrl.toString()], }, ]); assert.lengthOf(harness.reveals, 1); }).pipe(Effect.provide(harness.layer), Effect.scoped); }); it.effect("rejects mismatched callback state and only consumes the pending request once", () => { const harness = makeHarness({ isDevelopment: false }); return Effect.gen(function* () { const cloudAuth = yield* DesktopCloudAuth.DesktopCloudAuth; yield* cloudAuth.configure; const redirectUrl = yield* cloudAuth.createRequest; const validCallback = new URL(redirectUrl); validCallback.searchParams.set("rotating_token_nonce", "nonce-1"); const invalidCallback = new URL(validCallback); invalidCallback.searchParams.set(DesktopCloudAuth.CLOUD_AUTH_CALLBACK_STATE_PARAM, "wrong"); emitAppEvent( harness, "open-url", { preventDefault: () => undefined }, invalidCallback.toString(), ); yield* flushCloudAuthDispatch; assert.deepEqual(harness.sends, []); emitAppEvent( harness, "open-url", { preventDefault: () => undefined }, validCallback.toString(), ); yield* flushCloudAuthDispatch; emitAppEvent( harness, "open-url", { preventDefault: () => undefined }, validCallback.toString(), ); yield* flushCloudAuthDispatch; assert.deepEqual( harness.protocolRegistrations.map((registration) => registration.protocol), ["t3code"], ); assert.deepEqual(harness.sends, [ { channel: IpcChannels.CLOUD_AUTH_CALLBACK_CHANNEL, args: [validCallback.toString()], }, ]); }).pipe(Effect.provide(harness.layer), Effect.scoped); }); it.effect( "routes second-instance callbacks and reveals the window for non-callback launches", () => { const harness = makeHarness({ isDevelopment: true }); return Effect.gen(function* () { const cloudAuth = yield* DesktopCloudAuth.DesktopCloudAuth; yield* cloudAuth.configure; const redirectUrl = yield* cloudAuth.createRequest; const callbackUrl = new URL(redirectUrl); callbackUrl.searchParams.set("rotating_token_nonce", "nonce-1"); emitAppEvent(harness, "second-instance", {}, ["electron", callbackUrl.toString()]); yield* flushCloudAuthDispatch; const revealCountAfterCallback = harness.reveals.length; emitAppEvent(harness, "second-instance", {}, ["electron", "--opened-from-dock"]); yield* flushCloudAuthDispatch; assert.deepEqual(harness.sends, [ { channel: IpcChannels.CLOUD_AUTH_CALLBACK_CHANNEL, args: [callbackUrl.toString()], }, ]); assert.equal(revealCountAfterCallback, 1); assert.equal(harness.reveals.length, 2); }).pipe(Effect.provide(harness.layer), Effect.scoped); }, ); });