// tests/controllers/user_groups.controller.test.js jest.mock('../../models/users/user_groups.mdl', () => ({ mdl_UserGroups: { findOne: jest.fn() }, mdl_UserGroupMembers: {}, })); const { mdl_UserGroups } = require('../../models/users/user_groups.mdl'); const { __test__ } = require('../../controllers/admin/user_groups.controller'); const { buildSlugGroupCode, generateGroupCode } = __test__; describe('buildSlugGroupCode', () => { test('multi-word name -> acronym from first letters', () => { const result = buildSlugGroupCode('Group of Auditors'); expect(result).toBe('GA'); }); test('filters out stopwords before building acronym', () => { const result = buildSlugGroupCode('The Sales and Marketing Team'); expect(result).toBe('SMT'); }); test('single word -> truncated as-is', () => { const result = buildSlugGroupCode('Sales'); expect(result).toBe('SALE'); }); test('respects maxLen', () => { const result = buildSlugGroupCode('Internal Audit Team Extended', 3); expect(result).toBe('IAT'); }); test('strips non-alphanumeric characters per word', () => { const result = buildSlugGroupCode('R&D Ops'); expect(result).toBe('RO'); }); test('falls back to GROUP when name is only stopwords/empty after filtering', () => { const result = buildSlugGroupCode('The Of And'); expect(result).toBe('GROU'); }); test('falls back to first word when acronym would be 1 letter', () => { const result = buildSlugGroupCode('A Ops'); expect(result).toBe('OPS'); }); test('is case-insensitive on input', () => { const result = buildSlugGroupCode('group of auditors'); expect(result).toBe('GA'); }); }); describe('generateGroupCode', () => { beforeEach(() => { mdl_UserGroups.findOne.mockReset(); }); test('returns SLUG-XXXX when code is unique on first try', async () => { mdl_UserGroups.findOne.mockResolvedValueOnce(null); const code = await generateGroupCode('Group of Auditors'); console.log(`[TEST][GROUP CODE] Generated unique code: "${code}" (1 attempt)`); expect(code).toMatch(/^GA-[0-9A-F]{4}$/); expect(mdl_UserGroups.findOne).toHaveBeenCalledTimes(1); }); test('retries on collision until a unique code is found', async () => { mdl_UserGroups.findOne .mockResolvedValueOnce({ group_code: 'GA-AAAA' }) .mockResolvedValueOnce({ group_code: 'GA-BBBB' }) .mockResolvedValueOnce(null); const code = await generateGroupCode('Group of Auditors'); expect(code).toMatch(/^GA-[0-9A-F]{4}$/); expect(mdl_UserGroups.findOne).toHaveBeenCalledTimes(3); }); test('throws after 5 failed attempts', async () => { mdl_UserGroups.findOne.mockResolvedValue({ group_code: 'GA-AAAA' }); await expect(generateGroupCode('Group of Auditors')).rejects.toThrow( 'Could not generate a unique group code after 5 attempts.' ); expect(mdl_UserGroups.findOne).toHaveBeenCalledTimes(5); }); test('generated code stays within max slug length', async () => { mdl_UserGroups.findOne.mockResolvedValueOnce(null); const code = await generateGroupCode('Internal Audit Team For The Whole Organization Wide'); const [slug] = code.split('-'); console.log(`[TEST][GROUP CODE] Long name -> "${code}" (slug length: ${slug.length})`); expect(slug.length).toBeLessThanOrEqual(4); // 4, not 8 expect(code.length).toBeLessThanOrEqual(9); // total: XXXX-XXXX }); });