import { test } from '@japa/runner' import testUtils from '@adonisjs/core/services/test_utils' import Contact from '#base_modules/Contact/model/contact' import Tenant from '#base_modules/Tenant/model/tenant' import { createAdminWithToken } from '#tests/utils/auth' test.group('Contacts API', (group) => { group.each.setup(() => testUtils.db().wrapInGlobalTransaction()) test('rejects an unauthenticated list request', async ({ client }) => { const response = await client.get('/api/contacts').header('X-Tenant-Id', '1') response.assertStatus(401) }) test('lists only contacts owned by the selected tenant', async ({ assert, client }) => { const { admin, token } = await createAdminWithToken([]) const tenant = await Tenant.create({ name: 'Acme GmbH', slug: 'acme-gmbh', status: 'active' }) await tenant.related('admins').attach([admin.id]) await Contact.create({ tenantId: tenant.id, displayName: 'Ada Lovelace', email: 'ada@example.test', phone: null, status: 'active', }) const response = await client .get('/api/contacts') .header('X-Tenant-Id', String(tenant.id)) .bearerToken(token) response.assertStatus(200) assert.deepEqual(response.body(), { data: [ { id: 1, display_name: 'Ada Lovelace', email: 'ada@example.test', phone: null, status: 'active', }, ], }) }) test('creates a contact within the resolved tenant', async ({ assert, client }) => { const { admin, token } = await createAdminWithToken([]) const tenant = await Tenant.create({ name: 'Create GmbH', slug: 'create-gmbh', status: 'active', }) await tenant.related('admins').attach([admin.id]) const response = await client .post('/api/contacts') .header('X-Tenant-Id', String(tenant.id)) .bearerToken(token) .json({ display_name: 'Grace Hopper', email: 'grace@example.test', phone: '+1-555-0100' }) response.assertStatus(201) const created = response.body().data assert.deepInclude(created, { display_name: 'Grace Hopper', email: 'grace@example.test', phone: '+1-555-0100', status: 'active', }) const persistedContact = await Contact.find(created.id) assert.equal(persistedContact?.tenantId, tenant.id) }) test('rejects a contact without a display name', async ({ assert, client }) => { const { admin, token } = await createAdminWithToken([]) const tenant = await Tenant.create({ name: 'Validation GmbH', slug: 'validation-gmbh', status: 'active', }) await tenant.related('admins').attach([admin.id]) const response = await client .post('/api/contacts') .header('X-Tenant-Id', String(tenant.id)) .bearerToken(token) .json({ email: 'missing-name@example.test' }) response.assertStatus(422) assert.equal(response.body().errors[0].field, 'display_name') }) test('shows a contact only inside the resolved tenant', async ({ assert, client }) => { const { admin, token } = await createAdminWithToken([]) const tenant = await Tenant.create({ name: 'Show GmbH', slug: 'show-gmbh', status: 'active' }) await tenant.related('admins').attach([admin.id]) const contact = await Contact.create({ tenantId: tenant.id, displayName: 'Katherine Johnson', email: 'katherine@example.test', phone: null, status: 'active', }) const response = await client .get(`/api/contacts/${contact.id}`) .header('X-Tenant-Id', String(tenant.id)) .bearerToken(token) response.assertStatus(200) assert.deepEqual(response.body(), { data: { id: contact.id, display_name: 'Katherine Johnson', email: 'katherine@example.test', phone: null, status: 'active', }, }) const otherTenant = await Tenant.create({ name: 'Other GmbH', slug: 'other-gmbh', status: 'active', }) const foreignContact = await Contact.create({ tenantId: otherTenant.id, displayName: 'Tenant Two Contact', email: null, phone: null, status: 'active', }) const foreignResponse = await client .get(`/api/contacts/${foreignContact.id}`) .header('X-Tenant-Id', String(tenant.id)) .bearerToken(token) foreignResponse.assertStatus(404) }) test('updates a contact inside the resolved tenant', async ({ assert, client }) => { const { admin, token } = await createAdminWithToken([]) const tenant = await Tenant.create({ name: 'Update GmbH', slug: 'update-gmbh', status: 'active', }) await tenant.related('admins').attach([admin.id]) const contact = await Contact.create({ tenantId: tenant.id, displayName: 'Original Name', email: null, phone: null, status: 'active', }) const response = await client .put(`/api/contacts/${contact.id}`) .header('X-Tenant-Id', String(tenant.id)) .bearerToken(token) .json({ display_name: 'Updated Name', email: 'updated@example.test' }) response.assertStatus(200) assert.deepEqual(response.body(), { data: { id: contact.id, display_name: 'Updated Name', email: 'updated@example.test', phone: null, status: 'active', }, }) }) test('deletes a contact inside the resolved tenant', async ({ assert, client }) => { const { admin, token } = await createAdminWithToken([]) const tenant = await Tenant.create({ name: 'Delete GmbH', slug: 'delete-gmbh', status: 'active', }) await tenant.related('admins').attach([admin.id]) const contact = await Contact.create({ tenantId: tenant.id, displayName: 'Delete Me', email: null, phone: null, status: 'active', }) const response = await client .delete(`/api/contacts/${contact.id}`) .header('X-Tenant-Id', String(tenant.id)) .bearerToken(token) response.assertStatus(200) assert.equal(await Contact.find(contact.id), null) }) })