Files
gridpilot.gg/apps/website/lib/config/apiBaseUrl.test.ts
2026-01-17 22:55:03 +01:00

212 lines
7.0 KiB
TypeScript

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { getWebsiteApiBaseUrl } from './apiBaseUrl';
describe('getWebsiteApiBaseUrl', () => {
const originalEnv = process.env;
beforeEach(() => {
vi.resetModules();
process.env = { ...originalEnv };
// Clear window mock
if (typeof window !== 'undefined') {
delete (window as any).__NEXT_PUBLIC_API_BASE_URL__;
}
});
afterEach(() => {
process.env = originalEnv;
});
describe('with environment variables', () => {
it('should return configured NEXT_PUBLIC_API_BASE_URL in browser', () => {
// Mock browser environment
vi.stubGlobal('window', { location: {} } as any);
process.env.NEXT_PUBLIC_API_BASE_URL = 'https://api.example.com';
const result = getWebsiteApiBaseUrl();
expect(result).toBe('https://api.example.com');
});
it('should return configured API_BASE_URL in Node.js', () => {
// Ensure we're not in browser
vi.stubGlobal('window', undefined as any);
process.env.API_BASE_URL = 'https://api.example.com';
const result = getWebsiteApiBaseUrl();
expect(result).toBe('https://api.example.com');
});
it('should prefer API_BASE_URL over NEXT_PUBLIC_API_BASE_URL in Node.js', () => {
vi.stubGlobal('window', undefined as any);
process.env.API_BASE_URL = 'https://api-server.com';
process.env.NEXT_PUBLIC_API_BASE_URL = 'https://api-client.com';
const result = getWebsiteApiBaseUrl();
expect(result).toBe('https://api-server.com');
});
it('should fallback to NEXT_PUBLIC_API_BASE_URL if API_BASE_URL is not set', () => {
vi.stubGlobal('window', undefined as any);
delete process.env.API_BASE_URL;
process.env.NEXT_PUBLIC_API_BASE_URL = 'https://api-fallback.com';
const result = getWebsiteApiBaseUrl();
expect(result).toBe('https://api-fallback.com');
});
});
describe('normalization', () => {
it('should trim whitespace from URL', () => {
vi.stubGlobal('window', undefined as any);
process.env.API_BASE_URL = ' https://api.example.com ';
const result = getWebsiteApiBaseUrl();
expect(result).toBe('https://api.example.com');
});
it('should remove trailing slash', () => {
vi.stubGlobal('window', undefined as any);
process.env.API_BASE_URL = 'https://api.example.com/';
const result = getWebsiteApiBaseUrl();
expect(result).toBe('https://api.example.com');
});
it('should handle multiple trailing slashes', () => {
vi.stubGlobal('window', undefined as any);
process.env.API_BASE_URL = 'https://api.example.com///';
const result = getWebsiteApiBaseUrl();
// normalizeBaseUrl only removes one trailing slash
expect(result).toBe('https://api.example.com//');
});
it('should handle URL with path and trailing slash', () => {
vi.stubGlobal('window', undefined as any);
process.env.API_BASE_URL = 'https://api.example.com/v1/';
const result = getWebsiteApiBaseUrl();
expect(result).toBe('https://api.example.com/v1');
});
});
describe('fallback behavior', () => {
it('should fallback to localhost in development when no env vars set', () => {
vi.stubGlobal('window', undefined as any);
process.env.NODE_ENV = 'development';
delete process.env.API_BASE_URL;
delete process.env.NEXT_PUBLIC_API_BASE_URL;
delete process.env.CI;
delete process.env.DOCKER;
const result = getWebsiteApiBaseUrl();
expect(result).toBe('http://localhost:3001');
});
it('should fallback to api:3000 in production when no env vars set', () => {
vi.stubGlobal('window', undefined as any);
process.env.NODE_ENV = 'production';
delete process.env.API_BASE_URL;
delete process.env.NEXT_PUBLIC_API_BASE_URL;
delete process.env.CI;
delete process.env.DOCKER;
const result = getWebsiteApiBaseUrl();
expect(result).toBe('http://api:3000');
});
});
describe('test-like environment', () => {
it('should throw error in test environment when no URL configured', () => {
vi.stubGlobal('window', undefined as any);
process.env.NODE_ENV = 'test';
delete process.env.API_BASE_URL;
delete process.env.NEXT_PUBLIC_API_BASE_URL;
expect(() => getWebsiteApiBaseUrl()).toThrow(
'Missing API_BASE_URL. In Docker/CI/test we do not allow falling back to localhost.'
);
});
it('should throw error in CI environment when no URL configured', () => {
vi.stubGlobal('window', undefined as any);
process.env.CI = 'true';
delete process.env.API_BASE_URL;
delete process.env.NEXT_PUBLIC_API_BASE_URL;
expect(() => getWebsiteApiBaseUrl()).toThrow(
'Missing API_BASE_URL. In Docker/CI/test we do not allow falling back to localhost.'
);
});
it('should throw error in Docker environment when no URL configured', () => {
vi.stubGlobal('window', undefined as any);
process.env.DOCKER = 'true';
delete process.env.API_BASE_URL;
delete process.env.NEXT_PUBLIC_API_BASE_URL;
expect(() => getWebsiteApiBaseUrl()).toThrow(
'Missing API_BASE_URL. In Docker/CI/test we do not allow falling back to localhost.'
);
});
it('should throw browser-specific error in test environment when in browser', () => {
vi.stubGlobal('window', { location: {} } as any);
process.env.NODE_ENV = 'test';
delete process.env.API_BASE_URL;
delete process.env.NEXT_PUBLIC_API_BASE_URL;
expect(() => getWebsiteApiBaseUrl()).toThrow(
'Missing NEXT_PUBLIC_API_BASE_URL. In Docker/CI/test we do not allow falling back to localhost.'
);
});
it('should work in test environment when URL is configured', () => {
vi.stubGlobal('window', undefined as any);
process.env.NODE_ENV = 'test';
process.env.API_BASE_URL = 'https://test-api.example.com';
const result = getWebsiteApiBaseUrl();
expect(result).toBe('https://test-api.example.com');
});
});
describe('empty string handling', () => {
it('should treat empty string as not configured', () => {
vi.stubGlobal('window', undefined as any);
process.env.NODE_ENV = 'development';
process.env.API_BASE_URL = '';
delete process.env.NEXT_PUBLIC_API_BASE_URL;
const result = getWebsiteApiBaseUrl();
expect(result).toBe('http://localhost:3001');
});
it('should treat whitespace-only string as not configured', () => {
vi.stubGlobal('window', undefined as any);
process.env.NODE_ENV = 'development';
process.env.API_BASE_URL = ' ';
delete process.env.NEXT_PUBLIC_API_BASE_URL;
const result = getWebsiteApiBaseUrl();
expect(result).toBe('http://localhost:3001');
});
});
});