import { suite } from '../lib/context.js' suite('Members', { tags: ['members', 'crud'] }, (t) => { t.test('creates a member with auto-generated number', { tags: ['create'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Member Create Test' }) const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Alice', lastName: 'Test', }) t.assert.status(res, 201) t.assert.equal(res.data.firstName, 'Alice') t.assert.ok(res.data.memberNumber, 'should auto-generate member number') t.assert.equal(res.data.memberNumber.length, 6) }) t.test('inherits email from account when not provided', { tags: ['inheritance'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Inherit Email', email: 'family@test.com', phone: '555-1234', }) const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Child', lastName: 'Inherit', }) t.assert.status(res, 201) t.assert.equal(res.data.email, 'family@test.com') t.assert.equal(res.data.phone, '555-1234') }) t.test('uses member email when explicitly provided', { tags: ['inheritance'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Override Email', email: 'family@test.com', }) const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Adult', lastName: 'Own', email: 'own@test.com', }) t.assert.status(res, 201) t.assert.equal(res.data.email, 'own@test.com') }) t.test('inherits address from account when not provided', { tags: ['inheritance'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Inherit Address', address: { street: '123 Main St', city: 'Austin', state: 'TX', zip: '78701' }, }) const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Kid', lastName: 'Home', }) t.assert.status(res, 201) t.assert.equal(res.data.address.city, 'Austin') t.assert.equal(res.data.address.state, 'TX') }) t.test('accepts explicit isMinor flag without DOB', { tags: ['create'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Minor Test' }) const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Kid', lastName: 'NoDate', isMinor: true, }) t.assert.status(res, 201) t.assert.equal(res.data.isMinor, true) }) t.test('creates member without email or DOB', { tags: ['create'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Minimal Member' }) const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Just', lastName: 'Name', }) t.assert.status(res, 201) t.assert.equal(res.data.firstName, 'Just') }) t.test('lists all members across accounts', { tags: ['read'] }, async () => { const acct1 = await t.api.post('/v1/accounts', { name: 'List A' }) const acct2 = await t.api.post('/v1/accounts', { name: 'List B' }) await t.api.post(`/v1/accounts/${acct1.data.id}/members`, { firstName: 'A1', lastName: 'One' }) await t.api.post(`/v1/accounts/${acct2.data.id}/members`, { firstName: 'B1', lastName: 'Two' }) const res = await t.api.get('/v1/members', { limit: 100 }) t.assert.status(res, 200) t.assert.greaterThan(res.data.data.length, 1) t.assert.ok(res.data.data[0].accountName, 'should include account name') }) t.test('searches members by name', { tags: ['search'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Search Member Acct' }) await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'UniqueSearchName', lastName: 'Person', }) const res = await t.api.get('/v1/members', { q: 'UniqueSearchName' }) t.assert.status(res, 200) t.assert.ok(res.data.data.some((m: { firstName: string }) => m.firstName === 'UniqueSearchName')) }) t.test('moves member to existing account', { tags: ['move'] }, async () => { const acct1 = await t.api.post('/v1/accounts', { name: 'Source Acct' }) const acct2 = await t.api.post('/v1/accounts', { name: 'Target Acct' }) const member = await t.api.post(`/v1/accounts/${acct1.data.id}/members`, { firstName: 'Mover', lastName: 'Person', }) const res = await t.api.post(`/v1/members/${member.data.id}/move`, { accountId: acct2.data.id, }) t.assert.status(res, 200) t.assert.equal(res.data.accountId, acct2.data.id) }) t.test('moves member to new account when no accountId given', { tags: ['move'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Move Source' }) const member = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Solo', lastName: 'Flyer', }) const res = await t.api.post(`/v1/members/${member.data.id}/move`, {}) t.assert.status(res, 200) t.assert.notEqual(res.data.accountId, acct.data.id) }) t.test('normalizes state on member address via account inheritance', { tags: ['inheritance'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'State Inherit', address: { state: 'California' }, }) const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Cal', lastName: 'Kid', }) t.assert.status(res, 201) t.assert.equal(res.data.address.state, 'CA') }) t.test('updates a member', { tags: ['update'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Update Test' }) const member = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Before', lastName: 'Update', }) const res = await t.api.patch(`/v1/members/${member.data.id}`, { firstName: 'After' }) t.assert.status(res, 200) t.assert.equal(res.data.firstName, 'After') }) t.test('deletes a member', { tags: ['delete'] }, async () => { const acct = await t.api.post('/v1/accounts', { name: 'Delete Test' }) const member = await t.api.post(`/v1/accounts/${acct.data.id}/members`, { firstName: 'Gone', lastName: 'Soon', }) const res = await t.api.del(`/v1/members/${member.data.id}`) t.assert.status(res, 200) }) })