diff --git a/test/auth/login.test.ts b/test/auth/login.test.ts index e1bf4a6..177b5ed 100644 --- a/test/auth/login.test.ts +++ b/test/auth/login.test.ts @@ -200,11 +200,25 @@ const buildMockFetch = ( srpServer.checkM1(Buffer.from(body.srpM1, "base64")); const M2 = srpServer.computeM2(); + // IMPORTANT: the museum server's EmailAuthorizationResponse + // (server/ente/user.go) declares passkeySessionID, accountsUrl, + // twoFactorSessionID, and twoFactorSessionIDV2 WITHOUT the + // `omitempty` JSON tag. Go therefore always serializes them, + // sending "" (empty string, NOT null/absent) for any that do + // not apply. These mocks must reproduce that faithfully: a + // client that distinguishes fields with `??` instead of `||` + // passes against an omitting mock but breaks against the real + // server. + if (opts?.requireTOTP) { return new Response( JSON.stringify({ + id: 42, srpM2: M2.toString("base64"), + passkeySessionID: "", + accountsUrl: "", twoFactorSessionID: "totp-session-999", + twoFactorSessionIDV2: "", }), { status: 200, @@ -218,11 +232,14 @@ const buildMockFetch = ( // server sets passkeySessionID + twoFactorSessionIDV2 (not // twoFactorSessionID -- that's deliberate, so old clients // that only know the V1 field keep using the passkey flow). + // The V1 field is still present on the wire as "". return new Response( JSON.stringify({ + id: 42, srpM2: M2.toString("base64"), passkeySessionID: "passkey-session-123", accountsUrl: "https://accounts.ente.io", + twoFactorSessionID: "", twoFactorSessionIDV2: "totp-session-v2-456", }), { @@ -238,6 +255,10 @@ const buildMockFetch = ( id: 42, keyAttributes: fixture.keyAttributes, encryptedToken: fixture.encryptedToken, + passkeySessionID: "", + accountsUrl: "", + twoFactorSessionID: "", + twoFactorSessionIDV2: "", }), { status: 200,