ConusAI vendor v0.1.0-dev.20261013+85463d22

This commit is contained in:
ConusAI vendor v0.1.0-dev.20261013+85463d22
2026-10-13 20:45:57 +00:00
parent c3c6526952
commit 0da8a2a81b
67 changed files with 1510 additions and 10153 deletions
+18 -2
View File
@@ -9,6 +9,8 @@ const mocks = vi.hoisted(() => ({
recordUsage: vi.fn(async () => ({ accepted: 1, duplicates: 0, rejected: [] })),
consumeUploadQuota: vi.fn(async () => null as { allowed: boolean; remaining: number } | null),
revalidatePath: vi.fn(),
loggerInfo: vi.fn(),
loggerRecordException: vi.fn(),
note: undefined as { id: string; authorId: string } | undefined,
inserted: [] as Record<string, unknown>[],
}))
@@ -32,6 +34,7 @@ vi.mock('@/shared/api', () => ({
blob: () => ({ put: mocks.put }),
recordUsage: mocks.recordUsage,
serverErrors: () => ({ captureException: vi.fn() }),
logger: () => ({ info: mocks.loggerInfo, recordException: mocks.loggerRecordException }),
}))
vi.mock('@/shared/config', () => ({
getEnv: () => ({ CONUSAI_API_URL: 'https://console.example.com', CONUSAI_API_TOKEN: 'dt_fixture' }),
@@ -56,13 +59,18 @@ describe('uploadFile', () => {
mocks.consumeUploadQuota.mockResolvedValue(null)
mocks.inserted.length = 0
mocks.note = { id: NOTE, authorId: 'visitor-1' }
mocks.loggerInfo.mockClear()
mocks.loggerRecordException.mockClear()
})
it('refuses a file over the size limit before any upload', async () => {
it('refuses a file over the size limit before any upload, and logs the failure', async () => {
const big = new File([new Uint8Array(5 * 1024 * 1024 + 1)], 'big.png', { type: 'image/png' })
await expect(uploadFile(NOTE, attach(big))).rejects.toThrow(/5 MiB/)
expect(mocks.put).not.toHaveBeenCalled()
expect(mocks.log).not.toHaveBeenCalled()
expect(mocks.loggerInfo).not.toHaveBeenCalled()
expect(mocks.loggerRecordException).toHaveBeenCalledTimes(1)
expect(mocks.loggerRecordException).toHaveBeenCalledWith(expect.any(Error), { 'conusai.action': 'file.uploaded', 'note.id': NOTE })
})
it('refuses a disallowed type before any upload', async () => {
@@ -71,12 +79,13 @@ describe('uploadFile', () => {
expect(mocks.put).not.toHaveBeenCalled()
})
it('refuses a note the visitor did not write, without uploading', async () => {
it('refuses a note the visitor did not write, without uploading or spending quota', async () => {
mocks.note = { id: NOTE, authorId: 'visitor-2' }
const png = new File(['png'], 'a.png', { type: 'image/png' })
await expect(uploadFile(NOTE, attach(png))).rejects.toThrow(/not yours/)
expect(mocks.put).not.toHaveBeenCalled()
expect(mocks.inserted).toHaveLength(0)
expect(mocks.consumeUploadQuota).not.toHaveBeenCalled()
})
it('stores the bytes, records the attachment, and audits file.uploaded once', async () => {
@@ -98,6 +107,13 @@ describe('uploadFile', () => {
actor: { kind: 'human', id: 'visitor-1' },
target: { id: '00000000-0000-4000-8000-0000000000ff' },
})
expect(mocks.loggerInfo).toHaveBeenCalledTimes(1)
expect(mocks.loggerInfo).toHaveBeenCalledWith('file.uploaded', {
'file.id': '00000000-0000-4000-8000-0000000000ff',
'note.id': NOTE,
outcome: 'ok',
})
expect(mocks.loggerRecordException).not.toHaveBeenCalled()
})
it('sends exactly one usage event, keyed by the attachment, for one upload', async () => {