http.test.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. import { afterEach, describe, expect, it, vi } from 'vitest'
  2. vi.mock('@/lib/db', () => ({ db: {} }))
  3. const { createConnectorHttp } = await import('@/features/integrations/Lib/http')
  4. /**
  5. * The client labels a body as JSON when the caller did not say what it is.
  6. * A form has to be left alone: only fetch can write its content type, with
  7. * the boundary that separates the parts, and a file upload sent as JSON is
  8. * refused by the vendor.
  9. */
  10. describe('connector http', () => {
  11. afterEach(() => {
  12. vi.restoreAllMocks()
  13. })
  14. const client = () =>
  15. createConnectorHttp({
  16. connectionId: 'c1',
  17. credentials: { accessToken: 'tok' },
  18. auth: {},
  19. log: () => Promise.resolve(),
  20. })
  21. it('labels a text body as JSON and signs the request', async () => {
  22. const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response('{}'))
  23. await client().fetch('https://api.example.com/x', { method: 'POST', body: '{"a":1}' })
  24. const headers = new Headers(fetchMock.mock.calls[0][1]?.headers)
  25. expect(headers.get('content-type')).toBe('application/json')
  26. expect(headers.get('authorization')).toBe('Bearer tok')
  27. })
  28. it('leaves the content type of a form to fetch', async () => {
  29. const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response('{}'))
  30. const form = new FormData()
  31. form.set('filename', 'INV-1.pdf')
  32. form.set('file', new Blob(['%PDF'], { type: 'application/pdf' }), 'INV-1.pdf')
  33. await client().fetch('https://api.example.com/upload', { method: 'POST', body: form })
  34. const init = fetchMock.mock.calls[0][1]
  35. expect(new Headers(init?.headers).has('content-type')).toBe(false)
  36. expect(init?.body).toBe(form)
  37. })
  38. })