Skip to content

Commit b1aea61

Browse files
committed
fix(auth/tests): align permission tests with admin carve-out for purchase execution
The Purchaser-group carve-out (issue #923) removed execute:purchases, approve-any:purchases, and retry-any:purchases from the admin:* wildcard. Four tests were written before that contract existed and expected admin-alone membership to grant those verbs. - permissions.test.ts: split the "Administrators group member passes all checks" test into two -- admin-alone now asserts execute:purchases === false (regression guard for the carve-out), admin+Purchaser asserts all three carved-out verbs pass - recommendations-permissions.test.ts: mockUser('admin') now includes Purchaser group membership, matching the auto-migration path for existing admins - history-approve-button.test.ts: ADMIN_USER gains Purchaser membership so approve-any:purchases is granted (approve button visible on all pending rows) - history-retry-button.test.ts: ADMIN_USER gains Purchaser membership so retry-any:purchases is granted (retry button visible on all failed rows)
1 parent 5c02240 commit b1aea61

4 files changed

Lines changed: 32 additions & 8 deletions

File tree

‎frontend/src/__tests__/history-approve-button.test.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,12 @@ import * as api from '../api';
6363
import { confirmDialog } from '../confirmDialog';
6464
import { showToast } from '../toast';
6565
import { getCurrentUser } from '../state';
66-
import { ADMINISTRATORS_GROUP_ID } from '../permissions';
66+
import { ADMINISTRATORS_GROUP_ID, PURCHASER_GROUP_ID } from '../permissions';
6767

68-
const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', groups: [ADMINISTRATORS_GROUP_ID] };
68+
// Admin user includes Purchaser membership (mirrors the auto-migration for
69+
// existing admins on first deploy of issue #923). approve-any:purchases is
70+
// carved out of admin:* and requires Purchaser group membership.
71+
const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', groups: [ADMINISTRATORS_GROUP_ID, PURCHASER_GROUP_ID] };
6972
const REG_USER = { id: 'user-uuid', email: 'user@example.com', groups: [] };
7073
const OTHER_UUID = 'other-uuid';
7174

‎frontend/src/__tests__/history-retry-button.test.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,12 @@ import * as api from '../api';
6969
import { confirmDialog } from '../confirmDialog';
7070
import { showToast } from '../toast';
7171
import { getCurrentUser } from '../state';
72-
import { ADMINISTRATORS_GROUP_ID } from '../permissions';
72+
import { ADMINISTRATORS_GROUP_ID, PURCHASER_GROUP_ID } from '../permissions';
7373

74-
const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', groups: [ADMINISTRATORS_GROUP_ID] };
74+
// Admin user includes Purchaser membership (mirrors the auto-migration for
75+
// existing admins on first deploy of issue #923). retry-any:purchases is
76+
// carved out of admin:* and requires Purchaser group membership.
77+
const ADMIN_USER = { id: 'admin-uuid', email: 'admin@example.com', groups: [ADMINISTRATORS_GROUP_ID, PURCHASER_GROUP_ID] };
7578
const REG_USER = { id: 'user-uuid', email: 'user@example.com', groups: [] };
7679
const OTHER_UUID = 'other-uuid';
7780

‎frontend/src/__tests__/permissions.test.ts‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* getRolePermissions() is kept for the effective-permissions display in
1111
* the admin Users page and still returns the same sets as before.
1212
*/
13-
import { canAccess, getRolePermissions, isAdmin, ADMINISTRATORS_GROUP_ID } from '../permissions';
13+
import { canAccess, getRolePermissions, isAdmin, ADMINISTRATORS_GROUP_ID, PURCHASER_GROUP_ID } from '../permissions';
1414

1515
jest.mock('../state', () => ({
1616
getCurrentUser: jest.fn(),
@@ -123,12 +123,24 @@ describe('permissions', () => {
123123
});
124124

125125
describe('canAccess', () => {
126-
test('Administrators group member passes all checks', () => {
126+
test('Administrators group member passes non-spending checks', () => {
127127
mockUserWithGroups([ADMIN_GID]);
128128
expect(canAccess('admin', '*')).toBe(true);
129129
expect(canAccess('view', 'users')).toBe(true);
130130
expect(canAccess('delete', 'plans')).toBe(true);
131+
expect(canAccess('view', 'accounts')).toBe(true);
132+
// execute:purchases is carved out of admin:* and requires Purchaser membership.
133+
expect(canAccess('execute', 'purchases')).toBe(false);
134+
});
135+
136+
test('Administrators + Purchaser group member passes all checks including spending', () => {
137+
mockUserWithGroups([ADMIN_GID, PURCHASER_GROUP_ID]);
138+
expect(canAccess('admin', '*')).toBe(true);
139+
expect(canAccess('view', 'users')).toBe(true);
140+
expect(canAccess('delete', 'plans')).toBe(true);
131141
expect(canAccess('execute', 'purchases')).toBe(true);
142+
expect(canAccess('approve-any', 'purchases')).toBe(true);
143+
expect(canAccess('retry-any', 'purchases')).toBe(true);
132144
expect(canAccess('view', 'accounts')).toBe(true);
133145
});
134146

‎frontend/src/__tests__/recommendations-permissions.test.ts‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,17 @@ jest.mock('../toast', () => ({
6363
}));
6464

6565
import * as state from '../state';
66-
import { ADMINISTRATORS_GROUP_ID } from '../permissions';
66+
import { ADMINISTRATORS_GROUP_ID, PURCHASER_GROUP_ID } from '../permissions';
6767

6868
const mockUser = (role: string | null) => {
69+
// 'admin' represents a fully-capable admin: Administrators + Purchaser
70+
// (mirrors the auto-migration that adds existing admins to Purchaser on
71+
// first deploy of issue #923). Tests that want to assert admin-alone
72+
// behaviour (no spending access) should call mockUserWithGroups directly.
6973
(state.getCurrentUser as jest.Mock).mockReturnValue(
70-
role === null ? null : { id: 'u', email: 'u@example.com', groups: role === 'admin' ? [ADMINISTRATORS_GROUP_ID] : [] },
74+
role === null
75+
? null
76+
: { id: 'u', email: 'u@example.com', groups: role === 'admin' ? [ADMINISTRATORS_GROUP_ID, PURCHASER_GROUP_ID] : [] },
7177
);
7278
};
7379

0 commit comments

Comments
 (0)