72 lines
4.1 KiB
TypeScript
72 lines
4.1 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
initializeApp: vi.fn((_options: unknown, name = '[DEFAULT]') => ({ name })),
|
|
getApps: vi.fn((): Array<{ name: string }> => []),
|
|
getApp: vi.fn(),
|
|
connectAuth: vi.fn(),
|
|
connectFirestore: vi.fn(),
|
|
}));
|
|
vi.mock('firebase/app', () => mocks);
|
|
vi.mock('firebase/auth', () => ({ getAuth: vi.fn(() => ({})), GoogleAuthProvider: class {}, connectAuthEmulator: mocks.connectAuth }));
|
|
vi.mock('firebase/firestore', () => ({ getFirestore: vi.fn(() => ({})), connectFirestoreEmulator: mocks.connectFirestore }));
|
|
|
|
describe('isolated Firebase QA client', () => {
|
|
beforeEach(() => { vi.resetModules(); vi.clearAllMocks(); mocks.getApps.mockReturnValue([]); });
|
|
afterEach(() => vi.unstubAllEnvs());
|
|
it('initializes production project when explicitly configured', async () => {
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_EMULATORS', 'false');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_PROJECT_ID', 'motoapp-d22e0');
|
|
vi.stubEnv('FIREBASE_PROJECT_ID', 'motoapp-d22e0');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_API_KEY', 'test-production-api-key');
|
|
await import('../lib/firebase-client');
|
|
expect(mocks.initializeApp).toHaveBeenCalledWith(expect.objectContaining({ projectId: 'motoapp-d22e0' }));
|
|
expect(mocks.connectAuth).not.toHaveBeenCalled();
|
|
});
|
|
it('rejects unconfigured Firebase client when emulators are off', async () => {
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_EMULATORS', 'false');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_PROJECT_ID', '');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_API_KEY', '');
|
|
await expect(import('../lib/firebase-client')).rejects.toThrow('Missing required Firebase client configuration');
|
|
expect(mocks.initializeApp).not.toHaveBeenCalled();
|
|
});
|
|
it('rejects a production project before initializing Firebase', async () => {
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_EMULATORS', 'true');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_QA_PROJECT_ID', 'motoapp-d22e0');
|
|
await expect(import('../lib/firebase-client')).rejects.toThrow('demo- project');
|
|
expect(mocks.initializeApp).not.toHaveBeenCalled();
|
|
});
|
|
it('connects an isolated named demo app to both loopback emulators', async () => {
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_EMULATORS', 'true');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_QA_PROJECT_ID', 'demo-motorsignal-qa');
|
|
await import('../lib/firebase-client');
|
|
expect(mocks.initializeApp).toHaveBeenCalledWith(expect.objectContaining({ projectId: 'demo-motorsignal-qa' }), 'motorsignal-local-qa');
|
|
expect(mocks.connectAuth).toHaveBeenCalledWith(expect.anything(), 'http://127.0.0.1:9099');
|
|
expect(mocks.connectFirestore).toHaveBeenCalledWith(expect.anything(), '127.0.0.1', 8088);
|
|
});
|
|
it('supports dedicated QA emulator ports without changing production defaults', async () => {
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_EMULATORS', 'true');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_QA_PROJECT_ID', 'demo-motorsignal-web-qa');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_AUTH_EMULATOR_PORT', '9199');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_FIRESTORE_EMULATOR_PORT', '8188');
|
|
await import('../lib/firebase-client');
|
|
expect(mocks.connectAuth).toHaveBeenCalledWith(expect.anything(), 'http://127.0.0.1:9199');
|
|
expect(mocks.connectFirestore).toHaveBeenCalledWith(expect.anything(), '127.0.0.1', 8188);
|
|
});
|
|
it('rejects invalid dedicated QA emulator ports', async () => {
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_EMULATORS', 'true');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_QA_PROJECT_ID', 'demo-motorsignal-web-qa');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_AUTH_EMULATOR_PORT', '99999');
|
|
await expect(import('../lib/firebase-client')).rejects.toThrow('valid TCP ports');
|
|
expect(mocks.initializeApp).not.toHaveBeenCalled();
|
|
});
|
|
it('reuses an already connected QA app during module reload', async () => {
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_EMULATORS', 'true');
|
|
vi.stubEnv('NEXT_PUBLIC_FIREBASE_QA_PROJECT_ID', 'demo-motorsignal-qa');
|
|
mocks.getApps.mockReturnValue([{ name: 'motorsignal-local-qa' }]);
|
|
await import('../lib/firebase-client');
|
|
expect(mocks.initializeApp).not.toHaveBeenCalled();
|
|
expect(mocks.connectFirestore).not.toHaveBeenCalled();
|
|
});
|
|
});
|