Files
pn-new-crm/tests/e2e/smoke/global-setup.ts

192 lines
7.1 KiB
TypeScript
Raw Permalink Normal View History

/**
* Global Setup Seed the database with test users via Better Auth API
* and insert supporting data (berths, system_settings) via direct SQL.
*
* This runs BEFORE any test spec via Playwright's `dependencies` config.
*/
import { test as setup } from '@playwright/test';
const BASE = 'http://localhost:3000';
// ── Test user credentials ───────────────────────────────────────────────────
export const USERS = {
super_admin: {
email: 'admin@portnimara.test',
password: 'SuperAdmin12345!',
name: 'Test Admin',
},
sales_agent: {
email: 'agent@portnimara.test',
password: 'SalesAgent12345!',
name: 'Test Agent',
},
viewer: {
email: 'viewer@portnimara.test',
password: 'ViewerUser12345!',
name: 'Test Viewer',
},
};
// ── Helpers ─────────────────────────────────────────────────────────────────
/** Sign up a user via Better Auth REST API */
async function signUpUser(email: string, password: string, name: string) {
const headers = {
'Content-Type': 'application/json',
'Origin': BASE,
'Referer': `${BASE}/`,
};
const res = await fetch(`${BASE}/api/auth/sign-up/email`, {
method: 'POST',
headers,
body: JSON.stringify({ email, password, name }),
});
if (res.ok) {
const data = await res.json();
return data.user?.id ?? data.id;
}
// User may already exist — try sign-in instead
const loginRes = await fetch(`${BASE}/api/auth/sign-in/email`, {
method: 'POST',
headers,
body: JSON.stringify({ email, password }),
});
if (loginRes.ok) {
const loginData = await loginRes.json();
return loginData.user?.id ?? loginData.id;
}
const errorBody = await loginRes.text().catch(() => 'no body');
throw new Error(`Failed to create or sign in user ${email}: ${loginRes.status} ${errorBody}`);
}
/** Run raw SQL via docker psql using stdin piping */
async function runSQL(sql: string) {
const { execSync } = await import('child_process');
execSync(
`docker compose -f docker-compose.yml -f docker-compose.dev.yml exec -T postgres psql -U crm -d port_nimara_crm`,
{ cwd: process.cwd(), input: sql, stdio: ['pipe', 'pipe', 'pipe'] },
);
}
// ── Setup ───────────────────────────────────────────────────────────────────
setup('seed test database', async () => {
setup.setTimeout(120_000);
console.log('🔧 Creating test users via Better Auth...');
// 1. Create users via Better Auth sign-up endpoint
const adminId = await signUpUser(
USERS.super_admin.email,
USERS.super_admin.password,
USERS.super_admin.name,
);
console.log(` ✓ super_admin created: ${adminId}`);
const agentId = await signUpUser(
USERS.sales_agent.email,
USERS.sales_agent.password,
USERS.sales_agent.name,
);
console.log(` ✓ sales_agent created: ${agentId}`);
const viewerId = await signUpUser(
USERS.viewer.email,
USERS.viewer.password,
USERS.viewer.name,
);
console.log(` ✓ viewer created: ${viewerId}`);
// 2. Get portId and roleIds from seed data
console.log('🔧 Linking users to port and roles...');
// Create user_profiles + user_port_roles for each test user
// The super_admin profile already exists from db:seed with a placeholder userId.
// We need to update it and create profiles for agent + viewer.
await runSQL(`
-- Update super_admin profile to match the real auth user ID
UPDATE user_profiles SET user_id = '${adminId}' WHERE user_id = 'super-admin-matt-portnimara';
-- If that didn't match (profile might not exist), insert it
INSERT INTO user_profiles (id, user_id, display_name, is_super_admin, is_active, preferences)
VALUES (gen_random_uuid()::text, '${adminId}', 'Test Admin', true, true, '{}')
ON CONFLICT (user_id) DO UPDATE SET is_super_admin = true, is_active = true;
-- Create sales_agent profile
INSERT INTO user_profiles (id, user_id, display_name, is_super_admin, is_active, preferences)
VALUES (gen_random_uuid()::text, '${agentId}', 'Test Agent', false, true, '{}')
ON CONFLICT (user_id) DO NOTHING;
-- Create viewer profile
INSERT INTO user_profiles (id, user_id, display_name, is_super_admin, is_active, preferences)
VALUES (gen_random_uuid()::text, '${viewerId}', 'Test Viewer', false, true, '{}')
ON CONFLICT (user_id) DO NOTHING;
`);
await runSQL(`
-- Assign super_admin role to admin user
INSERT INTO user_port_roles (id, user_id, port_id, role_id)
SELECT gen_random_uuid()::text, '${adminId}', p.id, r.id
FROM ports p, roles r
WHERE p.slug = 'port-nimara' AND r.name = 'super_admin'
ON CONFLICT DO NOTHING;
-- Assign sales_agent role to agent user
INSERT INTO user_port_roles (id, user_id, port_id, role_id)
SELECT gen_random_uuid()::text, '${agentId}', p.id, r.id
FROM ports p, roles r
WHERE p.slug = 'port-nimara' AND r.name = 'sales_agent'
ON CONFLICT DO NOTHING;
-- Assign viewer role to viewer user
INSERT INTO user_port_roles (id, user_id, port_id, role_id)
SELECT gen_random_uuid()::text, '${viewerId}', p.id, r.id
FROM ports p, roles r
WHERE p.slug = 'port-nimara' AND r.name = 'viewer'
ON CONFLICT DO NOTHING;
`);
console.log(' ✓ Users linked to port-nimara with correct roles');
// 3. Seed berths for testing
console.log('🔧 Seeding berths...');
await runSQL(`
INSERT INTO berths (id, port_id, mooring_number, area, status, length_ft, width_ft, price, tenure_type)
SELECT gen_random_uuid()::text, p.id, 'A-001', 'Marina A', 'available', '60', '20', '150000', 'permanent'
FROM ports p WHERE p.slug = 'port-nimara'
ON CONFLICT DO NOTHING;
INSERT INTO berths (id, port_id, mooring_number, area, status, length_ft, width_ft, price, tenure_type)
SELECT gen_random_uuid()::text, p.id, 'A-002', 'Marina A', 'available', '80', '25', '250000', 'permanent'
FROM ports p WHERE p.slug = 'port-nimara'
ON CONFLICT DO NOTHING;
INSERT INTO berths (id, port_id, mooring_number, area, status, length_ft, width_ft, price, tenure_type)
SELECT gen_random_uuid()::text, p.id, 'B-001', 'Marina B', 'under_offer', '45', '15', '95000', 'fixed_term'
FROM ports p WHERE p.slug = 'port-nimara'
ON CONFLICT DO NOTHING;
`);
console.log(' ✓ 3 berths seeded');
// 4. Seed system settings
console.log('🔧 Seeding system settings...');
await runSQL(`
INSERT INTO system_settings (key, value, port_id)
SELECT 'invoice_prefix', '"INV"'::jsonb, p.id FROM ports p WHERE p.slug = 'port-nimara'
ON CONFLICT DO NOTHING;
INSERT INTO system_settings (key, value, port_id)
SELECT 'default_payment_terms', '"net30"'::jsonb, p.id FROM ports p WHERE p.slug = 'port-nimara'
ON CONFLICT DO NOTHING;
`);
console.log(' ✓ System settings seeded');
console.log('✅ Global setup complete!');
});