godcrm/backend/tests/database-schema.test.js
GOD CRM Release f89e074dd1
Some checks failed
CI / Lint / Typecheck / Test / Build (push) Has been cancelled
CI / PostgreSQL Integration Tests (push) Has been cancelled
GOD CRM — public scrubbed snapshot
Governed substrate for autonomous agents: scoped identity (passports),
audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
2026-08-10 04:01:45 +03:00

342 lines
12 KiB
JavaScript

// Test 1.1: Create users table with encryption_key_encrypted
import { describe, test, expect, beforeEach, afterEach } from 'vitest';
import { setupTestDatabase, cleanupTestDatabase } from './helpers/test-db.js';
import { dbGet, dbAll, dbRun } from '../database/connection.js';
// Set env vars for tests
process.env.MASTER_ENCRYPTION_KEY = 'test-master-key-32-chars-long!!';
process.env.JWT_SECRET = 'test-jwt-secret';
process.env.SKIP_DEV_USER = 'true'; // Don't create dev user in tests
// Helper to generate unique email
const uniqueEmail = (prefix = 'test') => `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}@hltrn.cc`;
describe.skip('Database Schema - Users Table', () => {
beforeEach(async () => {
await setupTestDatabase();
});
afterEach(async () => {
await cleanupTestDatabase();
});
test('should create users table with all required columns', async () => {
// Check if table exists
const tableInfo = await dbAll(`PRAGMA table_info(users)`);
expect(tableInfo).toBeDefined();
expect(tableInfo.length).toBeGreaterThan(0);
// Verify columns
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('id');
expect(columnNames).toContain('email');
expect(columnNames).toContain('password_hash');
expect(columnNames).toContain('name');
expect(columnNames).toContain('avatar');
expect(columnNames).toContain('role');
expect(columnNames).toContain('encryption_key_encrypted'); // NEW!
expect(columnNames).toContain('totp_secret');
expect(columnNames).toContain('totp_enabled');
expect(columnNames).toContain('email_verification_code');
expect(columnNames).toContain('email_verified');
expect(columnNames).toContain('created_at');
expect(columnNames).toContain('updated_at');
});
test('should enforce email uniqueness', async () => {
const testEmail = uniqueEmail('unique');
await dbRun(`
INSERT INTO users (email, password_hash, name, encryption_key_encrypted)
VALUES (?, ?, ?, ?)
`, [testEmail, 'hash123', 'Test User', 'encrypted_key_123']);
// Try to insert duplicate email
await expect(
dbRun(`
INSERT INTO users (email, password_hash, name, encryption_key_encrypted)
VALUES (?, ?, ?, ?)
`, [testEmail, 'hash456', 'Another User', 'encrypted_key_456'])
).rejects.toThrow();
});
test('should set default values correctly', async () => {
const result = await dbRun(`
INSERT INTO users (email, password_hash, name, encryption_key_encrypted)
VALUES (?, ?, ?, ?)
`, [uniqueEmail('default'), 'hash', 'Default User', 'enc_key']);
const user = await dbGet('SELECT * FROM users WHERE id = ?', [result.lastInsertRowid]);
expect(user.role).toBe('user');
expect(user.totp_enabled).toBe(0);
expect(user.email_verified).toBe(0);
expect(user.created_at).toBeDefined();
expect(user.updated_at).toBeDefined();
});
test('should require encryption_key_encrypted', async () => {
// Try to insert without encryption key
await expect(
dbRun(`
INSERT INTO users (email, password_hash, name)
VALUES (?, ?, ?)
`, [uniqueEmail('nokey'), 'hash', 'No Key User'])
).rejects.toThrow();
});
});
// Test 1.2: Projects table with 3 theme colors
describe.skip('Database Schema - Projects Table', () => {
beforeEach(async () => {
process.env.TEST_MODE = 'true';
await setupTestDatabase();
// Create a test user first
await dbRun(`
INSERT INTO users (email, password_hash, name, encryption_key_encrypted)
VALUES (?, ?, ?, ?)
`, [uniqueEmail('owner'), 'hash', 'Owner', 'key123']);
});
afterEach(async () => {
await cleanupTestDatabase();
});
test('should create projects table with theme colors', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(projects)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('id');
expect(columnNames).toContain('name');
expect(columnNames).toContain('description');
expect(columnNames).toContain('icon');
expect(columnNames).toContain('type');
expect(columnNames).toContain('owner_id');
expect(columnNames).toContain('theme_primary');
expect(columnNames).toContain('theme_secondary');
expect(columnNames).toContain('theme_tertiary');
expect(columnNames).toContain('settings');
expect(columnNames).toContain('created_at');
expect(columnNames).toContain('updated_at');
});
test('should set default theme colors', async () => {
const result = await dbRun(`
INSERT INTO projects (name, type, owner_id)
VALUES (?, ?, ?)
`, ['Test Project', 'custom', 1]);
const project = await dbGet('SELECT * FROM projects WHERE id = ?', [result.lastInsertRowid]);
expect(project.theme_primary).toBe('#0ea5e9');
expect(project.theme_secondary).toBe('#8b5cf6');
expect(project.theme_tertiary).toBe('#10b981');
});
test('should allow custom theme colors', async () => {
const result = await dbRun(`
INSERT INTO projects (name, type, owner_id, theme_primary, theme_secondary, theme_tertiary)
VALUES (?, ?, ?, ?, ?, ?)
`, ['Custom Project', 'custom', 1, '#ff0000', '#00ff00', '#0000ff']);
const project = await dbGet('SELECT * FROM projects WHERE id = ?', [result.lastInsertRowid]);
expect(project.theme_primary).toBe('#ff0000');
expect(project.theme_secondary).toBe('#00ff00');
expect(project.theme_tertiary).toBe('#0000ff');
});
test('should cascade delete when user is deleted', async () => {
await dbRun(`
INSERT INTO projects (name, type, owner_id)
VALUES (?, ?, ?)
`, ['Project to Delete', 'custom', 1]);
await dbRun('DELETE FROM users WHERE id = ?', [1]);
const projects = await dbAll('SELECT * FROM projects');
expect(projects.length).toBe(0);
});
});
// Test 1.3: Universal Tables
describe.skip('Database Schema - Universal Tables', () => {
beforeEach(async () => {
process.env.TEST_MODE = 'true';
await setupTestDatabase();
await dbRun(`INSERT INTO users (email, password_hash, name, encryption_key_encrypted) VALUES (?, ?, ?, ?)`, [uniqueEmail('ut'), 'h', 'U', 'k']);
await dbRun(`INSERT INTO projects (name, type, owner_id) VALUES (?, ?, ?)`, ['P', 'custom', 1]);
});
afterEach(async () => {
await cleanupTestDatabase();
});
test('should create universal_tables with sync_target', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(universal_tables)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('sync_target');
expect(columnNames).toContain('is_system');
});
test('should create system table with sync_target', async () => {
const result = await dbRun(`
INSERT INTO universal_tables (project_id, name, is_system, sync_target)
VALUES (?, ?, ?, ?)
`, [1, 'Users', 1, 'users']);
const table = await dbGet('SELECT * FROM universal_tables WHERE id = ?', [result.lastInsertRowid]);
expect(table.is_system).toBe(1);
expect(table.sync_target).toBe('users');
});
});
// Test 1.4: Table Columns
describe.skip('Database Schema - Table Columns', () => {
beforeEach(async () => {
process.env.TEST_MODE = 'true';
await setupTestDatabase();
await dbRun(`INSERT INTO users (email, password_hash, name, encryption_key_encrypted) VALUES (?, ?, ?, ?)`, [uniqueEmail('tc'), 'h', 'U', 'k']);
await dbRun(`INSERT INTO projects (name, type, owner_id) VALUES (?, ?, ?)`, ['P', 'custom', 1]);
await dbRun(`INSERT INTO universal_tables (project_id, name) VALUES (?, ?)`, [1, 'TestTable']);
});
afterEach(async () => {
await cleanupTestDatabase();
});
test('should create table_columns with all fields', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(table_columns)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('column_name');
expect(columnNames).toContain('display_name');
expect(columnNames).toContain('type');
expect(columnNames).toContain('config');
expect(columnNames).toContain('is_system');
});
test('should store column configuration as JSON', async () => {
const config = JSON.stringify({ max_length: 255, multiline: false });
const result = await dbRun(`
INSERT INTO table_columns (table_id, column_name, display_name, type, config)
VALUES (?, ?, ?, ?, ?)
`, [1, 'description', 'Description', 'text', config]);
const column = await dbGet('SELECT * FROM table_columns WHERE id = ?', [result.lastInsertRowid]);
expect(column.config).toBe(config);
});
});
// Test 1.5: Table Rows with base_id
describe.skip('Database Schema - Table Rows', () => {
beforeEach(async () => {
process.env.TEST_MODE = 'true';
await setupTestDatabase();
await dbRun(`INSERT INTO users (email, password_hash, name, encryption_key_encrypted) VALUES (?, ?, ?, ?)`, [uniqueEmail('tr'), 'h', 'U', 'k']);
await dbRun(`INSERT INTO projects (name, type, owner_id) VALUES (?, ?, ?)`, ['P', 'custom', 1]);
await dbRun(`INSERT INTO universal_tables (project_id, name) VALUES (?, ?)`, [1, 'T']);
});
afterEach(async () => {
await cleanupTestDatabase();
});
test('should create table_rows with base_id', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(table_rows)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('base_id');
expect(columnNames).toContain('data');
});
test('should enforce unique base_id', async () => {
const baseId = 'proj_1_tbl_1_row_1_aBcD123456';
await dbRun(`
INSERT INTO table_rows (table_id, base_id, data)
VALUES (?, ?, ?)
`, [1, baseId, '{}']);
await expect(
dbRun(`
INSERT INTO table_rows (table_id, base_id, data)
VALUES (?, ?, ?)
`, [1, baseId, '{}'])
).rejects.toThrow();
});
});
// Test 1.6-1.8: Chat System
describe.skip('Database Schema - Chat System', () => {
beforeEach(async () => {
process.env.TEST_MODE = 'true';
await setupTestDatabase();
});
afterEach(async () => {
await cleanupTestDatabase();
});
test('should create chat_threads table', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(chat_threads)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('thread_id');
expect(columnNames).toContain('type');
expect(columnNames).toContain('encrypted_with_keys');
});
test('should create chat_participants table', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(chat_participants)`);
expect(tableInfo.length).toBeGreaterThan(0);
});
test('should create chat_messages with encryption', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(chat_messages)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('content_encrypted');
expect(columnNames).toContain('encryption_method');
});
});
// Test 1.9-1.11: Audit, Settings, Widgets
describe.skip('Database Schema - System Tables', () => {
beforeEach(async () => {
process.env.TEST_MODE = 'true';
await setupTestDatabase();
});
afterEach(async () => {
await cleanupTestDatabase();
});
test('should create audit_log table', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(audit_log)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('action');
expect(columnNames).toContain('entity_type');
expect(columnNames).toContain('entity_id');
});
test('should create system_settings table', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(system_settings)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('key');
expect(columnNames).toContain('value');
expect(columnNames).toContain('type');
});
test('should create dashboard_widgets table', async () => {
const tableInfo = await dbAll(`PRAGMA table_info(dashboard_widgets)`);
const columnNames = tableInfo.map(col => col.name);
expect(columnNames).toContain('type');
expect(columnNames).toContain('config');
expect(columnNames).toContain('position');
});
});