You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
48 lines
2.8 KiB
TypeScript
48 lines
2.8 KiB
TypeScript
// apps/hq/test/settings-company.test.ts
|
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
|
|
import express from 'express'
|
|
import { openDb } from '../src/db'
|
|
import { seedIfEmpty } from '../src/seed'
|
|
import { createStaff } from '../src/auth'
|
|
import { apiRouter } from '../src/api'
|
|
|
|
async function appWith() {
|
|
const db = openDb(':memory:'); await seedIfEmpty(db)
|
|
await createStaff(db, { email: 'owner@test.in', displayName: 'Owner', role: 'owner', password: 'owner-password' })
|
|
await createStaff(db, { email: 'staff@test.in', displayName: 'Staff', role: 'staff', password: 'staff-password' })
|
|
const app = express(); app.use(express.json()); app.locals['db'] = db; app.use('/api', apiRouter(db))
|
|
const server = app.listen(0)
|
|
const base = `http://localhost:${(server.address() as { port: number }).port}/api`
|
|
return { db, server, base }
|
|
}
|
|
|
|
describe('company profile settings', () => {
|
|
let ctx: Awaited<ReturnType<typeof appWith>>
|
|
beforeAll(async () => { ctx = await appWith() })
|
|
afterAll(() => ctx.server.close())
|
|
const login = async (email: string, password: string) =>
|
|
(await (await fetch(`${ctx.base}/auth/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email, password }) })).json() as any).token
|
|
const call = async (token: string, method: string, path: string, body?: unknown) => {
|
|
const res = await fetch(ctx.base + path, { method, headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` }, ...(body ? { body: JSON.stringify(body) } : {}) })
|
|
return { status: res.status, json: await res.json() as any }
|
|
}
|
|
|
|
it('owner reads and updates company.* and it is audited', async () => {
|
|
const token = await login('owner@test.in', 'owner-password')
|
|
const before = await call(token, 'GET', '/settings/company')
|
|
expect(before.json.company['company.name']).toBe('Tecnostac')
|
|
const put = await call(token, 'PUT', '/settings/company', { name: 'Tecnostac Pvt Ltd', phone: '0484-1234567', stateCode: '32' })
|
|
expect(put.status).toBe(200)
|
|
expect(put.json.company['company.name']).toBe('Tecnostac Pvt Ltd')
|
|
expect(put.json.company['company.phone']).toBe('0484-1234567')
|
|
const audits = (await ctx.db.get<{ n: number }>(`SELECT COUNT(*) AS n FROM audit_log WHERE entity='setting' AND entity_id LIKE 'company.%'`))!
|
|
expect(audits.n).toBeGreaterThanOrEqual(3)
|
|
})
|
|
it('rejects a staff PUT (owner only) and an invalid GSTIN', async () => {
|
|
const staff = await login('staff@test.in', 'staff-password')
|
|
expect((await call(staff, 'PUT', '/settings/company', { name: 'Nope' })).status).toBe(403)
|
|
const owner = await login('owner@test.in', 'owner-password')
|
|
expect((await call(owner, 'PUT', '/settings/company', { gstin: 'NOTAGSTIN' })).status).toBe(400)
|
|
})
|
|
})
|