quality / changes (push) Successful in 7s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 30s
quality / web (push) Successful in 1m3s
quality / api (push) Successful in 1m15s
quality / linux-agent-smoke (push) Failing after 27s
quality / docker-check (push) Failing after 2m28s
CD / quality (push) Failing after 5m52s
CD / publish (push) Skipped
Implement reliable agent apply, telemetry v2, analytics retention, guarded rollouts, enrollment, labels and webhooks. Improve ReUI frontend data safety and bounded list loading, and add Docker smoke, recovery and resource checks. Document local verification and pending native acceptance.
53 lines
2.8 KiB
TypeScript
53 lines
2.8 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
import { EventEmitter } from 'node:events'
|
|
const dns = vi.hoisted(() => ({ lookup: vi.fn() }))
|
|
const https = vi.hoisted(() => ({ request: vi.fn() }))
|
|
vi.mock('node:dns/promises', () => dns)
|
|
vi.mock('node:https', () => https)
|
|
import { postWebhook } from './webhook-transport.js'
|
|
afterEach(() => vi.resetAllMocks())
|
|
describe('pinned webhook POST transport', () => {
|
|
it('rejects mixed DNS answers and rebinding on subsequent attempts without opening a socket', async () => {
|
|
dns.lookup.mockResolvedValue([{ address: '93.184.216.34', family: 4 }, { address: '127.0.0.1', family: 4 }])
|
|
await expect(postWebhook('https://hooks.example.com', 'secret', '{}', 'event', new AbortController().signal)).rejects.toThrow('INVALID_DESTINATION')
|
|
expect(https.request).not.toHaveBeenCalled()
|
|
dns.lookup.mockResolvedValue([{ address: '::ffff:10.0.0.1', family: 6 }])
|
|
await expect(postWebhook('https://hooks.example.com', 'secret', '{}', 'event', new AbortController().signal)).rejects.toThrow('INVALID_DESTINATION')
|
|
expect(dns.lookup).toHaveBeenCalledTimes(2)
|
|
})
|
|
it('pins the socket lookup, keeps TLS hostname, signs POST bytes and never follows redirects', async () => {
|
|
dns.lookup.mockResolvedValue([{ address: '93.184.216.34', family: 4 }])
|
|
const sent: string[] = []
|
|
https.request.mockImplementation((url, options, callback) => {
|
|
expect(url.hostname).toBe('hooks.example.com')
|
|
expect(options.method).toBe('POST')
|
|
expect(options.agent).toBe(false)
|
|
expect(options.rejectUnauthorized).not.toBe(false)
|
|
const selected = vi.fn()
|
|
options.lookup('hooks.example.com', {}, selected)
|
|
expect(selected).toHaveBeenCalledWith(null, '93.184.216.34', 4)
|
|
expect(options.headers['x-evofw-signature']).toMatch(/^v1=[a-f0-9]{64}$/)
|
|
expect(options.headers['x-evofw-event-id']).toBe('event')
|
|
const request = new EventEmitter() as EventEmitter & { end: (body: string) => void }
|
|
request.end = body => {
|
|
sent.push(body)
|
|
const response = Object.assign(new EventEmitter(), { statusCode: 302 })
|
|
callback(response)
|
|
queueMicrotask(() => response.emit('end'))
|
|
}
|
|
return request
|
|
})
|
|
await expect(postWebhook('https://hooks.example.com/path', 'secret', '{"id":1}', 'event', new AbortController().signal)).rejects.toThrow('HTTP_302')
|
|
expect(sent).toEqual(['{"id":1}'])
|
|
expect(https.request).toHaveBeenCalledTimes(1)
|
|
})
|
|
it('stops a DNS lookup when shutdown aborts', async () => {
|
|
dns.lookup.mockImplementation(() => new Promise(() => {}))
|
|
const controller = new AbortController()
|
|
const pending = postWebhook('https://hooks.example.com', 'secret', '{}', 'event', controller.signal)
|
|
controller.abort()
|
|
await expect(pending).rejects.toThrow('DELIVERY_TIMEOUT')
|
|
expect(https.request).not.toHaveBeenCalled()
|
|
})
|
|
})
|