This commit is contained in:
2026-09-02 09:19:43 +03:00
parent 74cb5b6176
commit 962f489142
34 changed files with 1190 additions and 124 deletions
@@ -0,0 +1,197 @@
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)
})
})