import { describe, it, expect } from 'vitest'
import { buildApp } from '../src/app.js'
import { makeConfig, fakeCpClient, fakeMinter } from './helpers.js'

async function makeApp() {
  return buildApp({ config: makeConfig(), cpClient: fakeCpClient(), minter: fakeMinter(), staticRoot: null })
}

const HARDENING: Readonly<Record<string, string>> = {
  'x-content-type-options': 'nosniff',
  'x-frame-options': 'DENY',
  'referrer-policy': 'no-referrer',
}

describe('security response headers', () => {
  it('stamps CSP + hardening headers on a matched route', async () => {
    const app = await makeApp()
    const res = await app.inject({ method: 'GET', url: '/api/session' })
    expect(res.statusCode).toBe(200)
    for (const [name, value] of Object.entries(HARDENING)) expect(res.headers[name]).toBe(value)

    const csp = String(res.headers['content-security-policy'])
    expect(csp).toContain("default-src 'self'")
    expect(csp).toContain("img-src 'self' data:") // pairing QR is a data: image
    expect(csp).toContain("style-src 'self' 'unsafe-inline'")
    expect(csp).toContain("object-src 'none'")
    expect(csp).toContain("base-uri 'none'")
    expect(csp).toContain("frame-ancestors 'none'")
    await app.close()
  })

  it('stamps the headers even on an unmatched (404) response', async () => {
    const app = await makeApp()
    const res = await app.inject({ method: 'GET', url: '/definitely-not-a-route' })
    expect(res.statusCode).toBe(404)
    expect(res.headers['x-frame-options']).toBe('DENY')
    expect(String(res.headers['content-security-policy'])).toContain("default-src 'self'")
    await app.close()
  })
})
