b90ec08966
- Update all test files to use named mock variables instead of inline mocks - Clear mock history in beforeEach instead of using mock.restore() - Add default mock implementations stored at module level - Document that tests should not use --randomize flag due to mock.module() limitations - All 89 unit tests pass consistently without randomization
161 lines
5.3 KiB
TypeScript
161 lines
5.3 KiB
TypeScript
/**
|
|
* Unit Tests: Permissions
|
|
*
|
|
* Tests the permission system for tournament management
|
|
*/
|
|
|
|
import { describe, test, expect, mock, beforeEach } from 'bun:test';
|
|
import { hasRole, canManageTournament, canCreateTournaments } from '@/lib/permissions';
|
|
import { getSession } from '@/lib/auth-simple';
|
|
import { prisma } from '@/lib/prisma';
|
|
import type { User } from '@prisma/client';
|
|
|
|
// Create mock functions at module level
|
|
const getSessionMock = mock(() => {});
|
|
const userFindUniqueMock = mock(() => {});
|
|
const eventFindUniqueMock = mock(() => {});
|
|
|
|
// Mock the getSession and prisma functions
|
|
mock.module('@/lib/auth-simple', () => ({
|
|
getSession: getSessionMock,
|
|
}));
|
|
|
|
mock.module('@/lib/prisma', () => ({
|
|
prisma: {
|
|
user: {
|
|
findUnique: userFindUniqueMock,
|
|
},
|
|
event: {
|
|
findUnique: eventFindUniqueMock,
|
|
},
|
|
},
|
|
}));
|
|
|
|
// Helper to create mock user
|
|
const createMockUser = (id: string, email: string, role: string): User => ({
|
|
id,
|
|
email,
|
|
role,
|
|
emailVerified: false,
|
|
name: null,
|
|
image: null,
|
|
playerId: null,
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
});
|
|
|
|
describe('Permissions', () => {
|
|
beforeEach(() => {
|
|
// Reset mock implementations to default (no-op) before each test
|
|
getSessionMock.mockImplementation(() => undefined);
|
|
userFindUniqueMock.mockImplementation(() => undefined);
|
|
eventFindUniqueMock.mockImplementation(() => undefined);
|
|
});
|
|
|
|
describe('hasRole', () => {
|
|
test('should allow club_admin to access tournament_admin resources', async () => {
|
|
getSessionMock.mockImplementation(async () => ({
|
|
user: { id: '1', email: 'test@example.com' },
|
|
session: { token: 'test', expiresAt: new Date() }
|
|
}));
|
|
userFindUniqueMock.mockImplementation(async () =>
|
|
createMockUser('1', 'test@example.com', 'club_admin')
|
|
);
|
|
|
|
const result = await hasRole('tournament_admin');
|
|
expect(result.allowed).toBe(true);
|
|
});
|
|
|
|
test('should deny player from accessing tournament_admin resources', async () => {
|
|
getSessionMock.mockImplementation(async () => ({
|
|
user: { id: '1', email: 'test@example.com' },
|
|
session: { token: 'test', expiresAt: new Date() }
|
|
}));
|
|
userFindUniqueMock.mockImplementation(async () =>
|
|
createMockUser('1', 'test@example.com', 'player')
|
|
);
|
|
|
|
const result = await hasRole('tournament_admin');
|
|
expect(result.allowed).toBe(false);
|
|
});
|
|
|
|
test('should deny unauthenticated user', async () => {
|
|
getSessionMock.mockImplementation(async () => null);
|
|
|
|
const result = await hasRole('club_admin');
|
|
expect(result.allowed).toBe(false);
|
|
expect(result.reason).toContain('Not authenticated');
|
|
});
|
|
});
|
|
|
|
describe('canManageTournament', () => {
|
|
test('should allow club_admin to manage any tournament', async () => {
|
|
getSessionMock.mockImplementation(async () => ({
|
|
user: { id: 'admin-1', email: 'admin@example.com' },
|
|
session: { token: 'test', expiresAt: new Date() }
|
|
}));
|
|
userFindUniqueMock.mockImplementation(async () =>
|
|
createMockUser('admin-1', 'admin@example.com', 'club_admin')
|
|
);
|
|
|
|
const result = await canManageTournament(999);
|
|
expect(result.allowed).toBe(true);
|
|
});
|
|
|
|
test('should deny player from managing tournaments', async () => {
|
|
getSessionMock.mockImplementation(async () => ({
|
|
user: { id: 'player-1', email: 'player@example.com' },
|
|
session: { token: 'test', expiresAt: new Date() }
|
|
}));
|
|
userFindUniqueMock.mockImplementation(async () =>
|
|
createMockUser('player-1', 'player@example.com', 'player')
|
|
);
|
|
|
|
const result = await canManageTournament(999);
|
|
expect(result.allowed).toBe(false);
|
|
expect(result.reason).toContain('Insufficient permissions');
|
|
});
|
|
});
|
|
|
|
describe('canCreateTournaments', () => {
|
|
test('should allow tournament_admin to create tournaments', async () => {
|
|
getSessionMock.mockImplementation(async () => ({
|
|
user: { id: 'admin-1', email: 'admin@example.com' },
|
|
session: { token: 'test', expiresAt: new Date() }
|
|
}));
|
|
userFindUniqueMock.mockImplementation(async () =>
|
|
createMockUser('admin-1', 'admin@example.com', 'tournament_admin')
|
|
);
|
|
|
|
const result = await canCreateTournaments();
|
|
expect(result.allowed).toBe(true);
|
|
});
|
|
|
|
test('should allow club_admin to create tournaments', async () => {
|
|
getSessionMock.mockImplementation(async () => ({
|
|
user: { id: 'admin-1', email: 'admin@example.com' },
|
|
session: { token: 'test', expiresAt: new Date() }
|
|
}));
|
|
userFindUniqueMock.mockImplementation(async () =>
|
|
createMockUser('admin-1', 'admin@example.com', 'club_admin')
|
|
);
|
|
|
|
const result = await canCreateTournaments();
|
|
expect(result.allowed).toBe(true);
|
|
});
|
|
|
|
test('should deny player from creating tournaments', async () => {
|
|
getSessionMock.mockImplementation(async () => ({
|
|
user: { id: 'player-1', email: 'player@example.com' },
|
|
session: { token: 'test', expiresAt: new Date() }
|
|
}));
|
|
userFindUniqueMock.mockImplementation(async () =>
|
|
createMockUser('player-1', 'player@example.com', 'player')
|
|
);
|
|
|
|
const result = await canCreateTournaments();
|
|
expect(result.allowed).toBe(false);
|
|
});
|
|
});
|
|
});
|