234 lines
8.7 KiB
TypeScript
234 lines
8.7 KiB
TypeScript
import { describe, test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { buildSeededPermissionNamesForRole } from '@/db/seeders/20200430130760-user-roles';
|
|
import { ROLE_NAMES, type RoleName } from '@/shared/constants/roles';
|
|
import { FEATURE_PERMISSIONS } from '@/shared/constants/product-permissions';
|
|
|
|
function granted(role: RoleName): readonly string[] {
|
|
return buildSeededPermissionNamesForRole(role);
|
|
}
|
|
|
|
describe('user-role seed permission contract', () => {
|
|
test('parent communication is seeded for system admins plus office manager, teacher, and guardian', () => {
|
|
const parentCommRoles = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(FEATURE_PERMISSIONS.READ_PARENT_COMM),
|
|
);
|
|
|
|
assert.deepEqual(parentCommRoles, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OFFICE_MANAGER,
|
|
ROLE_NAMES.TEACHER,
|
|
ROLE_NAMES.GUARDIAN,
|
|
]);
|
|
});
|
|
|
|
test('registrar has audit/report reads without parent communication', () => {
|
|
const permissions = granted(ROLE_NAMES.REGISTRAR);
|
|
|
|
assert.equal(permissions.includes(FEATURE_PERMISSIONS.READ_PARENT_COMM), false);
|
|
assert.equal(permissions.includes(FEATURE_PERMISSIONS.READ_POLICY_ACKNOWLEDGMENT_REPORTS), true);
|
|
assert.equal(permissions.includes(FEATURE_PERMISSIONS.READ_STAFF_ATTENDANCE_REPORTS), true);
|
|
assert.equal(permissions.includes(FEATURE_PERMISSIONS.READ_ZONE_CHECKIN_REPORTS), true);
|
|
assert.equal(permissions.includes(FEATURE_PERMISSIONS.ZONE_CHECKIN), true);
|
|
});
|
|
|
|
test('daily zone check-in is seeded for tenant staff roles across scopes', () => {
|
|
const zoneCheckinRoles = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(FEATURE_PERMISSIONS.ZONE_CHECKIN),
|
|
);
|
|
|
|
assert.deepEqual(zoneCheckinRoles, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.REGISTRAR,
|
|
ROLE_NAMES.DIRECTOR,
|
|
ROLE_NAMES.OFFICE_MANAGER,
|
|
ROLE_NAMES.TEACHER,
|
|
ROLE_NAMES.SUPPORT_STAFF,
|
|
]);
|
|
});
|
|
|
|
test('zone check-in reports are seeded for leadership and report-reader roles', () => {
|
|
const reportRoles = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(FEATURE_PERMISSIONS.READ_ZONE_CHECKIN_REPORTS),
|
|
);
|
|
|
|
assert.deepEqual(reportRoles, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.REGISTRAR,
|
|
ROLE_NAMES.DIRECTOR,
|
|
]);
|
|
});
|
|
|
|
test('internal alerts read/manage grants match tenant leadership and staff expectations', () => {
|
|
const internalAlertReaders = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(FEATURE_PERMISSIONS.READ_INTERNAL_COMM),
|
|
);
|
|
const internalAlertManagers = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(FEATURE_PERMISSIONS.MANAGE_INTERNAL_COMM),
|
|
);
|
|
|
|
assert.deepEqual(internalAlertReaders, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.REGISTRAR,
|
|
ROLE_NAMES.DIRECTOR,
|
|
ROLE_NAMES.OFFICE_MANAGER,
|
|
ROLE_NAMES.TEACHER,
|
|
ROLE_NAMES.SUPPORT_STAFF,
|
|
]);
|
|
assert.deepEqual(internalAlertManagers, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.DIRECTOR,
|
|
]);
|
|
});
|
|
|
|
test('leadership full-access grants include zone check-in but not parent communication or policy acknowledgment', () => {
|
|
const ownerPermissions = granted(ROLE_NAMES.OWNER);
|
|
const principalPermissions = granted(ROLE_NAMES.PRINCIPAL);
|
|
const directorPermissions = granted(ROLE_NAMES.DIRECTOR);
|
|
const systemAdminPermissions = granted(ROLE_NAMES.SYSTEM_ADMIN);
|
|
|
|
assert.equal(ownerPermissions.includes(FEATURE_PERMISSIONS.READ_PARENT_COMM), false);
|
|
assert.equal(ownerPermissions.includes(FEATURE_PERMISSIONS.ACK_POLICY), false);
|
|
assert.equal(ownerPermissions.includes(FEATURE_PERMISSIONS.ZONE_CHECKIN), true);
|
|
assert.equal(principalPermissions.includes(FEATURE_PERMISSIONS.READ_PARENT_COMM), false);
|
|
assert.equal(principalPermissions.includes(FEATURE_PERMISSIONS.ACK_POLICY), false);
|
|
assert.equal(principalPermissions.includes(FEATURE_PERMISSIONS.ZONE_CHECKIN), true);
|
|
assert.equal(directorPermissions.includes(FEATURE_PERMISSIONS.READ_PARENT_COMM), false);
|
|
assert.equal(directorPermissions.includes(FEATURE_PERMISSIONS.ACK_POLICY), true);
|
|
assert.equal(directorPermissions.includes(FEATURE_PERMISSIONS.ZONE_CHECKIN), true);
|
|
assert.equal(systemAdminPermissions.includes(FEATURE_PERMISSIONS.READ_PARENT_COMM), true);
|
|
assert.equal(systemAdminPermissions.includes(FEATURE_PERMISSIONS.ACK_POLICY), true);
|
|
assert.equal(systemAdminPermissions.includes(FEATURE_PERMISSIONS.ZONE_CHECKIN), true);
|
|
});
|
|
|
|
test('attendance fill grants match operational writers', () => {
|
|
const attendanceFillRoles = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(FEATURE_PERMISSIONS.FILL_ATTENDANCE),
|
|
);
|
|
|
|
assert.deepEqual(attendanceFillRoles, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.DIRECTOR,
|
|
ROLE_NAMES.OFFICE_MANAGER,
|
|
ROLE_NAMES.TEACHER,
|
|
]);
|
|
});
|
|
|
|
test('teacher user-management grants are limited to student roster writes', () => {
|
|
const teacherPermissions = granted(ROLE_NAMES.TEACHER);
|
|
const supportStaffPermissions = granted(ROLE_NAMES.SUPPORT_STAFF);
|
|
|
|
assert.equal(teacherPermissions.includes('READ_USERS'), true);
|
|
assert.equal(teacherPermissions.includes('CREATE_USERS'), true);
|
|
assert.equal(teacherPermissions.includes('UPDATE_USERS'), true);
|
|
assert.equal(teacherPermissions.includes('CREATE_GUARDIAN_STUDENTS'), true);
|
|
assert.equal(teacherPermissions.includes('DELETE_USERS'), false);
|
|
assert.equal(supportStaffPermissions.includes('CREATE_USERS'), false);
|
|
assert.equal(supportStaffPermissions.includes('UPDATE_USERS'), false);
|
|
});
|
|
|
|
test('attendance notification eligibility is seeded through fill or report permissions', () => {
|
|
const attendanceNotificationRoles = Object.values(ROLE_NAMES).filter((role) => {
|
|
const permissions = granted(role);
|
|
return permissions.includes(FEATURE_PERMISSIONS.FILL_ATTENDANCE)
|
|
|| permissions.includes(FEATURE_PERMISSIONS.READ_STAFF_ATTENDANCE_REPORTS);
|
|
});
|
|
|
|
assert.deepEqual(attendanceNotificationRoles, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.REGISTRAR,
|
|
ROLE_NAMES.DIRECTOR,
|
|
ROLE_NAMES.OFFICE_MANAGER,
|
|
ROLE_NAMES.TEACHER,
|
|
]);
|
|
});
|
|
|
|
test('ESA funding management grants match campus and parent-scope managers', () => {
|
|
const esaManagers = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(FEATURE_PERMISSIONS.MANAGE_ESA_FUNDING_CONTENT),
|
|
);
|
|
|
|
assert.deepEqual(esaManagers, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.DIRECTOR,
|
|
ROLE_NAMES.OFFICE_MANAGER,
|
|
]);
|
|
});
|
|
|
|
test('staff support page reads are seeded for campus staff and leaders', () => {
|
|
for (const permission of [
|
|
FEATURE_PERMISSIONS.READ_AUTISM_SUPPORT_STEPS,
|
|
FEATURE_PERMISSIONS.READ_PARA_CERTIFICATIONS,
|
|
FEATURE_PERMISSIONS.READ_AWARDS_REVIEWS,
|
|
]) {
|
|
const readers = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(permission),
|
|
);
|
|
|
|
assert.deepEqual(readers, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.DIRECTOR,
|
|
ROLE_NAMES.OFFICE_MANAGER,
|
|
ROLE_NAMES.TEACHER,
|
|
ROLE_NAMES.SUPPORT_STAFF,
|
|
]);
|
|
}
|
|
});
|
|
|
|
test('staff support page management grants match leaders and office managers', () => {
|
|
for (const permission of [
|
|
FEATURE_PERMISSIONS.MANAGE_AUTISM_SUPPORT_STEPS,
|
|
FEATURE_PERMISSIONS.MANAGE_PARA_CERTIFICATIONS,
|
|
FEATURE_PERMISSIONS.MANAGE_AWARDS_REVIEWS,
|
|
]) {
|
|
const managers = Object.values(ROLE_NAMES).filter((role) =>
|
|
granted(role).includes(permission),
|
|
);
|
|
|
|
assert.deepEqual(managers, [
|
|
ROLE_NAMES.SYSTEM_ADMIN,
|
|
ROLE_NAMES.OWNER,
|
|
ROLE_NAMES.SUPERINTENDENT,
|
|
ROLE_NAMES.PRINCIPAL,
|
|
ROLE_NAMES.DIRECTOR,
|
|
ROLE_NAMES.OFFICE_MANAGER,
|
|
]);
|
|
}
|
|
});
|
|
|
|
test('seeded permission grants are unique per role', () => {
|
|
for (const role of Object.values(ROLE_NAMES)) {
|
|
const permissions = granted(role);
|
|
assert.equal(
|
|
new Set(permissions).size,
|
|
permissions.length,
|
|
`${role} should not seed duplicate permission links`,
|
|
);
|
|
}
|
|
});
|
|
});
|