Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions frontend/src/__tests__/a11y.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ describe('accessibility smoke', () => {
{
id: 'u1',
email: 'alice@example.com',
role: 'admin',
groups: [],
groups: ['00000000-0000-5000-8000-000000000001'],
mfa_enabled: false,
created_at: '2024-01-01T00:00:00Z',
last_login: '2024-06-01T00:00:00Z',
Expand All @@ -57,7 +56,6 @@ describe('accessibility smoke', () => {
{
id: 'u1',
email: 'bob@example.com',
role: 'user',
groups: [],
mfa_enabled: true,
created_at: '2024-01-01T00:00:00Z',
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/__tests__/allowed-accounts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ import { getCurrentUser } from '../state';
// Helpers
// ---------------------------------------------------------------------------

const ADMIN = { id: 'admin-uuid', email: 'admin@example.com', role: 'admin' };
const ADMIN = { id: 'admin-uuid', email: 'admin@example.com', groups: ['00000000-0000-5000-8000-000000000001'] };

function setupTopbarSlot(): void {
while (document.body.firstChild) document.body.removeChild(document.body.firstChild);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/__tests__/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ describe('API Requests', () => {
test('fetches current user', async () => {
fetchMock.mockResolvedValue({
ok: true,
json: () => Promise.resolve({ email: 'test@example.com', role: 'admin' })
json: () => Promise.resolve({ email: 'test@example.com', groups: ['00000000-0000-5000-8000-000000000001'] })
});

const user = await getCurrentUser();
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/__tests__/auth-mfa-enroll.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ beforeEach(() => {
`;
jest.clearAllMocks();
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'u1', email: 'user@x.com', role: 'user', mfa_enabled: false,
id: 'u1', email: 'user@x.com', groups: [], mfa_enabled: false,
});
updateUserUI();
});
Expand All @@ -84,7 +84,7 @@ describe('MFA enrollment flow', () => {

test('enabled state shows Disable and Regenerate buttons', async () => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'u1', email: 'user@x.com', role: 'user', mfa_enabled: true,
id: 'u1', email: 'user@x.com', groups: [], mfa_enabled: true,
});
updateUserUI();
await openProfile();
Expand Down Expand Up @@ -153,7 +153,7 @@ describe('MFA enrollment flow', () => {
describe('MFA disable flow', () => {
beforeEach(() => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'u1', email: 'user@x.com', role: 'user', mfa_enabled: true,
id: 'u1', email: 'user@x.com', groups: [], mfa_enabled: true,
});
updateUserUI();
});
Expand Down Expand Up @@ -183,7 +183,7 @@ describe('MFA disable flow', () => {
describe('MFA regenerate-recovery-codes flow', () => {
beforeEach(() => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'u1', email: 'user@x.com', role: 'user', mfa_enabled: true,
id: 'u1', email: 'user@x.com', groups: [], mfa_enabled: true,
});
updateUserUI();
});
Expand Down
15 changes: 8 additions & 7 deletions frontend/src/__tests__/auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Auth module tests
*/
import { showLoginModal, showResetPasswordModal, updateUserUI, logout } from '../auth';
import { ADMINISTRATORS_GROUP_ID } from '../permissions';

// Mock the api module
jest.mock('../api', () => {
Expand Down Expand Up @@ -404,7 +405,7 @@ describe('Auth Module', () => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'user-1',
email: 'test@example.com',
role: 'user'
groups: []
});

updateUserUI();
Expand All @@ -417,7 +418,7 @@ describe('Auth Module', () => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'user-1',
email: 'test@example.com',
role: 'user'
groups: []
});

updateUserUI();
Expand All @@ -439,7 +440,7 @@ describe('Auth Module', () => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'admin-1',
email: 'admin@example.com',
role: 'admin'
groups: [ADMINISTRATORS_GROUP_ID]
});

updateUserUI();
Expand All @@ -454,7 +455,7 @@ describe('Auth Module', () => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'user-1',
email: 'user@example.com',
role: 'user'
groups: []
});

updateUserUI();
Expand All @@ -469,7 +470,7 @@ describe('Auth Module', () => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'user-1',
email: 'test@example.com',
role: 'user'
groups: []
});

updateUserUI();
Expand All @@ -483,7 +484,7 @@ describe('Auth Module', () => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'user-1',
email: 'test@example.com',
role: 'user'
groups: []
});
(api.logout as jest.Mock).mockResolvedValue({});

Expand Down Expand Up @@ -522,7 +523,7 @@ describe('Auth Module', () => {
(state.getCurrentUser as jest.Mock).mockReturnValue({
id: 'user-1',
email: 'test@example.com',
role: 'user'
groups: []
});
});

Expand Down
10 changes: 5 additions & 5 deletions frontend/src/__tests__/groups.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ const mockGroups: api.APIGroup[] = [
},
];

// Mock users that belong to groups
// Mock users that belong to groups (PR #912: role field removed, groups is the source of truth)
const mockUsers = [
{ id: 'user-1', email: 'admin@test.com', role: 'admin', groups: ['group-1'], mfa_enabled: true },
{ id: 'user-2', email: 'viewer@test.com', role: 'user', groups: ['group-2'], mfa_enabled: false },
{ id: 'user-3', email: 'both@test.com', role: 'user', groups: ['group-1', 'group-2'], mfa_enabled: true },
{ id: 'user-1', email: 'admin@test.com', groups: ['00000000-0000-5000-8000-000000000001', 'group-1'], mfa_enabled: true },
{ id: 'user-2', email: 'viewer@test.com', groups: ['group-2'], mfa_enabled: false },
{ id: 'user-3', email: 'both@test.com', groups: ['group-1', 'group-2'], mfa_enabled: true },
];

describe('groups/state', () => {
Expand Down Expand Up @@ -164,7 +164,7 @@ describe('groups/groupList', () => {
it('should use singular "member" when count is 1', () => {
// Set up users so group-1 has exactly 1 member
userState.setAllUsers([
{ id: 'user-1', email: 'admin@test.com', role: 'admin', groups: ['group-1'], mfa_enabled: true },
{ id: 'user-1', email: 'admin@test.com', groups: ['00000000-0000-5000-8000-000000000001', 'group-1'], mfa_enabled: true },
] as any);

const group = mockGroups[0];
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/__tests__/history-approval-queue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ import { confirmDialog } from '../confirmDialog';
import { showToast } from '../toast';
import { getCurrentUser } from '../state';
import { getAccountName } from '../recommendations';
import { ADMINISTRATORS_GROUP_ID } from '../permissions';

const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', role: 'admin' };
const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', groups: [ADMINISTRATORS_GROUP_ID] };

function setupDOM(): void {
while (document.body.firstChild) document.body.removeChild(document.body.firstChild);
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/__tests__/history-approve-button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ import * as api from '../api';
import { confirmDialog } from '../confirmDialog';
import { showToast } from '../toast';
import { getCurrentUser } from '../state';
import { ADMINISTRATORS_GROUP_ID } from '../permissions';

const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', role: 'admin' };
const REG_USER = { id: 'user-uuid', email: 'user@example.com', role: 'user' };
const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', groups: [ADMINISTRATORS_GROUP_ID] };
const REG_USER = { id: 'user-uuid', email: 'user@example.com', groups: [] };
const OTHER_UUID = 'other-uuid';

function setupDOM(): void {
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/__tests__/history-cancel-button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ import * as api from '../api';
import { confirmDialog } from '../confirmDialog';
import { showToast } from '../toast';
import { getCurrentUser } from '../state';
import { ADMINISTRATORS_GROUP_ID } from '../permissions';

const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', role: 'admin' };
const REG_USER = { id: 'user-uuid', email: 'user@example.com', role: 'user' };
const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', groups: [ADMINISTRATORS_GROUP_ID] };
const REG_USER = { id: 'user-uuid', email: 'user@example.com', groups: [] };
const OTHER_UUID = 'other-uuid';

function setupDOM(): void {
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/__tests__/history-retry-button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ import * as api from '../api';
import { confirmDialog } from '../confirmDialog';
import { showToast } from '../toast';
import { getCurrentUser } from '../state';
import { ADMINISTRATORS_GROUP_ID } from '../permissions';

const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', role: 'admin' };
const REG_USER = { id: 'user-uuid', email: 'user@example.com', role: 'user' };
const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', groups: [ADMINISTRATORS_GROUP_ID] };
const REG_USER = { id: 'user-uuid', email: 'user@example.com', groups: [] };
const OTHER_UUID = 'other-uuid';

function setupDOM(): void {
Expand Down
16 changes: 8 additions & 8 deletions frontend/src/__tests__/html.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -501,20 +501,20 @@ describe('HTML Structure', () => {
expect(email?.hasAttribute('required')).toBe(true);
});

test('has user role select', () => {
test('user role select is absent (PR #912: role concept dropped)', () => {
// PR #912 removed the role column. The role selector was replaced by
// a required group multi-select. Verify the old element is gone so a
// regression that re-adds it is caught.
const role = document.getElementById('user-role') as HTMLSelectElement | null;
expect(role).toBeTruthy();
const options = Array.from(role?.querySelectorAll('option') ?? []).map(o => o.value);
// Exact-set equality (not toContain) so a regression that
// re-introduces the pre-fix viewer/editor values — or adds any
// other role the backend allowlist would reject — fails the test.
expect(new Set(options)).toEqual(new Set(['readonly', 'user', 'admin']));
expect(role).toBeNull();
});

test('has user groups multi-select', () => {
test('has user groups multi-select (required, PR #912)', () => {
const groups = document.getElementById('user-groups') as HTMLSelectElement | null;
expect(groups).toBeTruthy();
expect(groups?.hasAttribute('multiple')).toBe(true);
// PR #912: groups is now required (>= 1 group enforced by backend DB CHECK).
expect(groups?.hasAttribute('required')).toBe(true);
});
});

Expand Down
Loading
Loading