212 lines
7.0 KiB
TypeScript
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');
|
|
});
|
|
});
|
|
}); |