import { afterEach, mock, test } from 'node:test'; import assert from 'node:assert/strict'; import { inspect } from 'node:util'; import { Op, type FindAndCountOptions } from 'sequelize'; import db from '@/db/models'; import UsersDBApi from '@/db/api/users'; afterEach(() => { mock.restoreAll(); }); test('UsersDBApi query search uses correlated subqueries for related names', async () => { let capturedOptions: FindAndCountOptions | null = null; mock.method( db.users, 'findAndCountAll', (async (options: FindAndCountOptions) => { capturedOptions = options; return { rows: [], count: 0 }; }) as unknown as typeof db.users.findAndCountAll, ); await UsersDBApi.findAll({ query: 'John', limit: 10, page: 0 }, true, {}); assert.ok(capturedOptions, 'expected findAndCountAll to be called'); const options = capturedOptions as FindAndCountOptions; const where = options.where as Record; const andConditions = where[Op.and]; assert.ok(Array.isArray(andConditions), 'expected query search conditions in Op.and'); const serializedWhere = inspect(where, { depth: 10 }); assert.ok( serializedWhere.includes('FROM "organizations"'), 'expected organization name search to use a correlated subquery', ); assert.ok( serializedWhere.includes('FROM "schools"'), 'expected school name search to use a correlated subquery', ); assert.ok( serializedWhere.includes('FROM "campuses"'), 'expected campus name search to use a correlated subquery', ); assert.ok( serializedWhere.includes('FROM "classes"'), 'expected class name search to use a correlated subquery', ); assert.ok( serializedWhere.includes('FROM "roles"'), 'expected role name search to use a correlated subquery', ); assert.equal( serializedWhere.includes('lower("school"."name")') || serializedWhere.includes('lower("campus"."name")') || serializedWhere.includes('lower("class"."name")') || serializedWhere.includes('lower("app_role"."name")'), false, 'expected no direct joined-alias name references in the where clause', ); }); test('UsersDBApi ignores removed user filters', async () => { let capturedOptions: FindAndCountOptions | null = null; mock.method( db.users, 'findAndCountAll', (async (options: FindAndCountOptions) => { capturedOptions = options; return { rows: [], count: 0 }; }) as unknown as typeof db.users.findAndCountAll, ); const removedFilter = { active: 'true', password: 'secret', emailVerificationToken: 'verify-token', passwordResetToken: 'reset-token', disabled: 'false', limit: 10, page: 0, }; await UsersDBApi.findAll(removedFilter, true, {}); assert.ok(capturedOptions, 'expected findAndCountAll to be called'); const options = capturedOptions as FindAndCountOptions; const where = options.where as Record; const serializedWhere = inspect(where, { depth: 10 }); assert.equal(where.disabled, false); assert.equal(serializedWhere.includes('active'), false); assert.equal(serializedWhere.includes('password'), false); assert.equal(serializedWhere.includes('emailVerificationToken'), false); assert.equal(serializedWhere.includes('passwordResetToken'), false); }); test('UsersDBApi campus filter includes class-scoped users inside that campus', async () => { let capturedOptions: FindAndCountOptions | null = null; mock.method( db.users, 'findAndCountAll', (async (options: FindAndCountOptions) => { capturedOptions = options; return { rows: [], count: 0 }; }) as unknown as typeof db.users.findAndCountAll, ); await UsersDBApi.findAll( { campusId: '00000000-0000-4000-8000-000000000001', limit: 10, page: 0 }, true, {}, ); assert.ok(capturedOptions, 'expected findAndCountAll to be called'); const options = capturedOptions as FindAndCountOptions; const where = options.where as Record; const serializedWhere = inspect(where, { depth: 10 }); assert.ok( serializedWhere.includes('FROM "classes" WHERE "campusId"'), 'expected campus filtering to include class-scoped users', ); }); test('UsersDBApi class filter includes enrolled students', async () => { let capturedOptions: FindAndCountOptions | null = null; mock.method( db.users, 'findAndCountAll', (async (options: FindAndCountOptions) => { capturedOptions = options; return { rows: [], count: 0 }; }) as unknown as typeof db.users.findAndCountAll, ); await UsersDBApi.findAll( { classId: '00000000-0000-4000-8000-000000000002', limit: 10, page: 0 }, true, {}, ); assert.ok(capturedOptions, 'expected findAndCountAll to be called'); const options = capturedOptions as FindAndCountOptions; const where = options.where as Record; const serializedWhere = inspect(where, { depth: 10 }); assert.ok( serializedWhere.includes('FROM "class_enrollments"'), 'expected class filtering to include enrolled students', ); });