/**
 * Security Middleware Tests
 */

import { describe, it, expect, vi } from 'vitest'
import {
  securityHeadersMiddleware,
  sanitizeInput,
  sanitizeBodyMiddleware,
} from '../security'
import type { FastifyRequest, FastifyReply } from 'fastify'

describe('Security Middleware', () => {
  describe('securityHeadersMiddleware', () => {
    it('should add security headers', async () => {
      const mockReply = {
        header: vi.fn().mockReturnThis(),
      } as any

      await securityHeadersMiddleware({} as FastifyRequest, mockReply)

      expect(mockReply.header).toHaveBeenCalledWith('X-Content-Type-Options', 'nosniff')
      expect(mockReply.header).toHaveBeenCalledWith('X-Frame-Options', 'DENY')
      expect(mockReply.header).toHaveBeenCalledWith('X-XSS-Protection', '1; mode=block')
      expect(mockReply.header).toHaveBeenCalledWith(
        'Strict-Transport-Security',
        expect.stringContaining('max-age')
      )
    })
  })

  describe('sanitizeInput', () => {
    it('should remove script tags', () => {
      const input = '<script>alert("xss")</script>Hello'
      const sanitized = sanitizeInput(input)
      expect(sanitized).not.toContain('<script>')
      expect(sanitized).toContain('Hello')
    })

    it('should remove javascript: protocol', () => {
      const input = 'javascript:alert("xss")'
      const sanitized = sanitizeInput(input)
      expect(sanitized).not.toContain('javascript:')
    })

    it('should sanitize nested objects', () => {
      const input = {
        name: '<script>alert("xss")</script>',
        nested: {
          value: 'javascript:test',
        },
      }
      const sanitized = sanitizeInput(input)
      expect(sanitized.name).not.toContain('<script>')
      expect(sanitized.nested.value).not.toContain('javascript:')
    })

    it('should sanitize arrays', () => {
      const input = ['<script>test</script>', 'normal', 'javascript:test']
      const sanitized = sanitizeInput(input)
      expect(sanitized[0]).not.toContain('<script>')
      expect(sanitized[2]).not.toContain('javascript:')
    })
  })

  describe('sanitizeBodyMiddleware', () => {
    it('should sanitize request body', async () => {
      const mockRequest = {
        body: {
          name: '<script>alert("xss")</script>',
        },
      } as any

      const mockReply = {} as FastifyReply

      await sanitizeBodyMiddleware(mockRequest, mockReply)

      expect(mockRequest.body.name).not.toContain('<script>')
    })
  })
})

