import { describe, it, expect } from 'vitest' import { createAuth, createFakeUserRepo } from '../src/index.js' import { createFakeHasher, createFakeSigner, createFakeOauth, createFakeEmail } from './fakes.js' function build(oauth) { const userRepo = createFakeUserRepo() const auth = createAuth({ userRepo, hasher: createFakeHasher(), tokenSigner: createFakeSigner(), oauth, email: createFakeEmail(), }) return { userRepo, auth } } describe('oauthLogin', () => { it('first login auto-creates user (is_new_user true)', async () => { const oauth = createFakeOauth({ 'google:CODE1': { provider_user_id: 'g-1', email: 'g@x.com', email_verified: true }, }) const { auth, userRepo } = build(oauth) const res = await auth.oauthLogin({ provider: 'google', code: 'CODE1', redirect_uri: 'https://app/cb' }) expect(res.is_new_user).toBe(true) expect(res.user.email).toBe('g@x.com') expect(res.access_token).toBeTruthy() const stored = await userRepo.findByEmail('g@x.com') expect(stored.oauth_providers).toContainEqual({ provider: 'google', provider_user_id: 'g-1' }) }) it('existing email merges into same user (is_new_user false)', async () => { const oauth = createFakeOauth({ 'google:CODE1': { provider_user_id: 'g-1', email: 'merge@x.com', email_verified: true }, }) const { auth, userRepo } = build(oauth) // pre-existing password user with same email await userRepo.create({ email: 'merge@x.com', password_hash: 'h$pw' }) const res = await auth.oauthLogin({ provider: 'google', code: 'CODE1' }) expect(res.is_new_user).toBe(false) const stored = await userRepo.findByEmail('merge@x.com') expect(stored.oauth_providers).toContainEqual({ provider: 'google', provider_user_id: 'g-1' }) }) it('verify failure -> OAUTH_VERIFY_FAILED', async () => { const oauth = createFakeOauth({}, { throwOn: 'BAD' }) const { auth } = build(oauth) await expect(auth.oauthLogin({ provider: 'apple', code: 'BAD' })) .rejects.toMatchObject({ code: 'OAUTH_VERIFY_FAILED' }) }) it('unsupported provider rejected', async () => { const { auth } = build(createFakeOauth()) await expect(auth.oauthLogin({ provider: 'wechat', code: 'x' })) .rejects.toMatchObject({ code: 'UNSUPPORTED_PROVIDER' }) }) })