feat: Add comprehensive test suite and misc improvements
- Add frontend unit tests with Vitest for components, hooks, pages, and utilities - Add backend tests for webhooks, notifications, middleware, and edge cases - Add ForgotPassword, NotFound, and ResetPassword pages - Add migration for orphaned staff resources conversion - Add coverage directory to gitignore (generated reports) - Various bug fixes and improvements from previous work 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
143
frontend/src/api/__tests__/config.test.ts
Normal file
143
frontend/src/api/__tests__/config.test.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
|
||||
// Mock the domain module before importing config
|
||||
vi.mock('../../utils/domain', () => ({
|
||||
getBaseDomain: vi.fn(),
|
||||
isRootDomain: vi.fn(),
|
||||
}));
|
||||
|
||||
// Helper to mock window.location
|
||||
const mockLocation = (hostname: string, protocol = 'https:', port = '') => {
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
hostname,
|
||||
protocol,
|
||||
port,
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
};
|
||||
|
||||
describe('api/config', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.clearAllMocks();
|
||||
// Clear any env vars
|
||||
delete (import.meta as unknown as { env: Record<string, unknown> }).env.VITE_API_URL;
|
||||
});
|
||||
|
||||
describe('getSubdomain', () => {
|
||||
it('returns null for root domain', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(true);
|
||||
mockLocation('lvh.me');
|
||||
|
||||
const { getSubdomain } = await import('../config');
|
||||
expect(getSubdomain()).toBeNull();
|
||||
});
|
||||
|
||||
it('returns subdomain for business site', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(false);
|
||||
mockLocation('demo.lvh.me');
|
||||
|
||||
const { getSubdomain } = await import('../config');
|
||||
expect(getSubdomain()).toBe('demo');
|
||||
});
|
||||
|
||||
it('returns null for platform subdomain', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(false);
|
||||
mockLocation('platform.lvh.me');
|
||||
|
||||
const { getSubdomain } = await import('../config');
|
||||
expect(getSubdomain()).toBeNull();
|
||||
});
|
||||
|
||||
it('returns subdomain for www', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(false);
|
||||
mockLocation('www.lvh.me');
|
||||
|
||||
const { getSubdomain } = await import('../config');
|
||||
expect(getSubdomain()).toBe('www');
|
||||
});
|
||||
|
||||
it('returns subdomain for api', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(false);
|
||||
mockLocation('api.lvh.me');
|
||||
|
||||
const { getSubdomain } = await import('../config');
|
||||
expect(getSubdomain()).toBe('api');
|
||||
});
|
||||
|
||||
it('handles production business subdomain', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(false);
|
||||
mockLocation('acme-corp.smoothschedule.com');
|
||||
|
||||
const { getSubdomain } = await import('../config');
|
||||
expect(getSubdomain()).toBe('acme-corp');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPlatformSite', () => {
|
||||
it('returns true for platform subdomain', async () => {
|
||||
mockLocation('platform.lvh.me');
|
||||
|
||||
const { isPlatformSite } = await import('../config');
|
||||
expect(isPlatformSite()).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for platform in production', async () => {
|
||||
mockLocation('platform.smoothschedule.com');
|
||||
|
||||
const { isPlatformSite } = await import('../config');
|
||||
expect(isPlatformSite()).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for business subdomain', async () => {
|
||||
mockLocation('demo.lvh.me');
|
||||
|
||||
const { isPlatformSite } = await import('../config');
|
||||
expect(isPlatformSite()).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for root domain', async () => {
|
||||
mockLocation('lvh.me');
|
||||
|
||||
const { isPlatformSite } = await import('../config');
|
||||
expect(isPlatformSite()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isBusinessSite', () => {
|
||||
it('returns true for business subdomain', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(false);
|
||||
mockLocation('demo.lvh.me');
|
||||
|
||||
const { isBusinessSite } = await import('../config');
|
||||
expect(isBusinessSite()).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for platform site', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(false);
|
||||
mockLocation('platform.lvh.me');
|
||||
|
||||
const { isBusinessSite } = await import('../config');
|
||||
expect(isBusinessSite()).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for root domain', async () => {
|
||||
const domain = await import('../../utils/domain');
|
||||
vi.mocked(domain.isRootDomain).mockReturnValue(true);
|
||||
mockLocation('lvh.me');
|
||||
|
||||
const { isBusinessSite } = await import('../config');
|
||||
expect(isBusinessSite()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user