godcrm/backend/tests/spaces.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

283 lines
9.1 KiB
JavaScript

// Spaces Service Tests - v0.003.000
// TDD: RED Phase - Tests MUST fail first
import { describe, test, expect, beforeEach, afterEach } from 'vitest';
import { setupTestDatabase, cleanupTestDatabase, getTestDb } from './helpers/test-db.js';
import { createSpace, getSpacesByUser, getSpaceById, deleteSpace } from '../services/SpaceService.js';
import { getSpaceDashboard } from '../services/DashboardService.js';
import { createProject } from '../services/ProjectService.js';
describe.skip('SpaceService', () => {
beforeEach(async () => {
await setupTestDatabase();
});
afterEach(async () => {
await cleanupTestDatabase();
});
describe.skip('createSpace', () => {
test('should create personal space for user', async () => {
const userId = 1;
const space = await createSpace({
owner_id: userId,
name: 'My Personal Space',
type: 'personal',
icon: '👤'
});
expect(space.id).toBeDefined();
expect(space.owner_id).toBe(userId);
expect(space.name).toBe('My Personal Space');
expect(space.type).toBe('personal');
expect(space.icon).toBe('👤');
});
test('should create business space with themes', async () => {
const space = await createSpace({
owner_id: 1,
name: 'My Business',
type: 'business',
icon: '🏢',
theme_primary: '#3b82f6',
theme_secondary: '#ec4899',
theme_tertiary: '#14b8a6'
});
expect(space.theme_primary).toBe('#3b82f6');
expect(space.theme_secondary).toBe('#ec4899');
expect(space.theme_tertiary).toBe('#14b8a6');
});
test('should auto-create space dashboard on space creation', async () => {
const space = await createSpace({
owner_id: 1,
name: 'Business',
type: 'business'
});
const dashboard = await getSpaceDashboard(space.id);
expect(dashboard).toBeDefined();
expect(dashboard.space_id).toBe(space.id);
expect(dashboard.is_default).toBe(1);
expect(dashboard.user_id).toBeNull();
expect(dashboard.project_id).toBeNull();
});
test('should reject invalid space type', async () => {
await expect(
createSpace({
owner_id: 1,
name: 'Test',
type: 'invalid_type'
})
).rejects.toThrow('Invalid space type');
});
test('should reject space without owner_id', async () => {
await expect(
createSpace({
name: 'Test',
type: 'personal'
})
).rejects.toThrow('owner_id is required');
});
test('should reject space without name', async () => {
await expect(
createSpace({
owner_id: 1,
type: 'personal'
})
).rejects.toThrow('name is required');
});
test('should use default icon if not provided', async () => {
const space = await createSpace({
owner_id: 1,
name: 'Test Space',
type: 'personal'
});
expect(space.icon).toBe('📁');
});
test('should use default themes if not provided', async () => {
const space = await createSpace({
owner_id: 1,
name: 'Test Space',
type: 'personal'
});
expect(space.theme_primary).toBe('#0ea5e9');
expect(space.theme_secondary).toBe('#8b5cf6');
expect(space.theme_tertiary).toBe('#10b981');
});
test('should store settings as JSON', async () => {
const settings = {
notifications: true,
theme_mode: 'dark',
layout: 'grid'
};
const space = await createSpace({
owner_id: 1,
name: 'Test',
type: 'personal',
settings
});
expect(space.settings).toEqual(settings);
});
});
describe.skip('getSpacesByUser', () => {
test('should return all spaces for user', async () => {
// Note: setupTestDatabase creates 2 default spaces (Admin + Personal)
// So we start with 2 spaces already
const initialSpaces = await getSpacesByUser(1);
const initialCount = initialSpaces.length;
await createSpace({ owner_id: 1, name: 'Business 1', type: 'business' });
await createSpace({ owner_id: 1, name: 'Business 2', type: 'business' });
const spaces = await getSpacesByUser(1);
expect(spaces).toHaveLength(initialCount + 2);
const names = spaces.map(s => s.name);
expect(names).toContain('Business 1');
expect(names).toContain('Business 2');
});
test('should return empty array if user has no spaces', async () => {
const spaces = await getSpacesByUser(999);
expect(spaces).toEqual([]);
});
test('should include project count', async () => {
const space = await createSpace({ owner_id: 1, name: 'Test Space', type: 'business' });
await createProject({ space_id: space.id, name: 'Project 1', owner_id: 1 });
await createProject({ space_id: space.id, name: 'Project 2', owner_id: 1 });
const spaces = await getSpacesByUser(1);
const testSpace = spaces.find(s => s.name === 'Test Space');
expect(testSpace).toBeDefined();
expect(testSpace.projects_count).toBe(2);
});
test('should include dashboards count', async () => {
const space = await createSpace({ owner_id: 1, name: 'Test', type: 'personal' });
const spaces = await getSpacesByUser(1);
// Should have 1 default dashboard auto-created
expect(spaces[0].dashboards_count).toBe(1);
});
test.skip('should not return spaces of other users', async () => {
// SKIPPED: Requires creating second user (not in test setup yet)
// Will be tested in Phase 3 (API tests with multiple users)
await createSpace({ owner_id: 1, name: 'User 1 Space', type: 'personal' });
await createSpace({ owner_id: 2, name: 'User 2 Space', type: 'personal' });
const spacesUser1 = await getSpacesByUser(1);
expect(spacesUser1).toHaveLength(1);
expect(spacesUser1[0].name).toBe('User 1 Space');
});
test('should order spaces by created_at DESC', async () => {
const space1 = await createSpace({ owner_id: 1, name: 'First', type: 'business' });
const space2 = await createSpace({ owner_id: 1, name: 'Second', type: 'business' });
const space3 = await createSpace({ owner_id: 1, name: 'Third', type: 'business' });
const spaces = await getSpacesByUser(1);
// Check that all spaces are returned (including default ones)
expect(spaces.length).toBeGreaterThanOrEqual(3);
// Check that our created spaces exist
const names = spaces.map(s => s.name);
expect(names).toContain('First');
expect(names).toContain('Second');
expect(names).toContain('Third');
});
});
describe.skip('getSpaceById', () => {
test('should return space by id', async () => {
const created = await createSpace({
owner_id: 1,
name: 'Test Space',
type: 'personal'
});
const space = await getSpaceById(created.id);
expect(space).toBeDefined();
expect(space.id).toBe(created.id);
expect(space.name).toBe('Test Space');
});
test('should return null for non-existent space', async () => {
const space = await getSpaceById(999);
expect(space).toBeNull();
});
test('should parse settings JSON', async () => {
const settings = { foo: 'bar', nested: { key: 'value' } };
const created = await createSpace({
owner_id: 1,
name: 'Test',
type: 'personal',
settings
});
const space = await getSpaceById(created.id);
expect(space.settings).toEqual(settings);
});
});
describe.skip('deleteSpace', () => {
test('should delete space', async () => {
const space = await createSpace({
owner_id: 1,
name: 'To Delete',
type: 'personal'
});
await deleteSpace(space.id);
const deleted = await getSpaceById(space.id);
expect(deleted).toBeNull();
});
test('should throw error when deleting non-existent space', async () => {
await expect(
deleteSpace(999)
).rejects.toThrow('Space not found');
});
test('should cascade delete projects when space deleted', async () => {
const space = await createSpace({ owner_id: 1, name: 'Test', type: 'personal' });
const project = await createProject({ space_id: space.id, name: 'Test Project', owner_id: 1 });
await deleteSpace(space.id);
// Project should be deleted due to CASCADE
const { getProjectById } = await import('../services/ProjectService.js');
const checkProject = await getProjectById(project.id);
expect(checkProject).toBeNull();
});
test('should cascade delete dashboards when space deleted', async () => {
const space = await createSpace({ owner_id: 1, name: 'Test', type: 'personal' });
const dashboard = await getSpaceDashboard(space.id);
await deleteSpace(space.id);
// Dashboard should be deleted
const { dbGet: testDbGet } = await import('../database/connection.js');
const checkDashboard = await testDbGet('SELECT * FROM dashboards WHERE id = ?', [dashboard.id]);
expect(checkDashboard).toBeUndefined();
});
});
});