198 lines
6.0 KiB
TypeScript
198 lines
6.0 KiB
TypeScript
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)
|
|
})
|
|
})
|