parse-multipart.test.mjs
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠ breaking
1 day ago
| 1 | /** |
| 2 | * Tests for hub/gateway/parse-multipart.mjs — minimal multipart/form-data file parser. |
| 3 | * Used by the gateway to extract image uploads without forwarding binary bodies to another Lambda. |
| 4 | */ |
| 5 | import { describe, it } from 'node:test'; |
| 6 | import assert from 'node:assert'; |
| 7 | import { parseMultipartFile } from '../hub/gateway/parse-multipart.mjs'; |
| 8 | |
| 9 | /** |
| 10 | * Build a minimal multipart/form-data body containing one file field. |
| 11 | */ |
| 12 | function buildMultipart(boundary, filename, contentType, data) { |
| 13 | const parts = [ |
| 14 | `--${boundary}\r\n`, |
| 15 | `Content-Disposition: form-data; name="image"; filename="${filename}"\r\n`, |
| 16 | `Content-Type: ${contentType}\r\n`, |
| 17 | `\r\n`, |
| 18 | ]; |
| 19 | const header = Buffer.from(parts.join(''), 'binary'); |
| 20 | const footer = Buffer.from(`\r\n--${boundary}--\r\n`, 'binary'); |
| 21 | return Buffer.concat([header, data, footer]); |
| 22 | } |
| 23 | |
| 24 | describe('parseMultipartFile', () => { |
| 25 | it('extracts file buffer from a well-formed multipart body', () => { |
| 26 | const boundary = 'TestBoundary1234'; |
| 27 | const payload = Buffer.from([0xFF, 0xD8, 0xFF, 0xE0, 0x01, 0x02]); |
| 28 | const body = buildMultipart(boundary, 'photo.jpg', 'image/jpeg', payload); |
| 29 | const result = parseMultipartFile(body, boundary); |
| 30 | assert.ok(result, 'should return a result'); |
| 31 | assert.strictEqual(result.filename, 'photo.jpg'); |
| 32 | assert.strictEqual(result.contentType, 'image/jpeg'); |
| 33 | assert.deepStrictEqual(result.data, payload); |
| 34 | }); |
| 35 | |
| 36 | it('returns null for a body with no file parts', () => { |
| 37 | const boundary = 'NoBoundary'; |
| 38 | // A text field (no filename) — should be ignored |
| 39 | const body = Buffer.from( |
| 40 | `--${boundary}\r\nContent-Disposition: form-data; name="text"\r\n\r\nhello\r\n--${boundary}--\r\n`, |
| 41 | 'binary', |
| 42 | ); |
| 43 | const result = parseMultipartFile(body, boundary); |
| 44 | assert.strictEqual(result, null); |
| 45 | }); |
| 46 | |
| 47 | it('returns null for empty body', () => { |
| 48 | assert.strictEqual(parseMultipartFile(Buffer.alloc(0), 'boundary'), null); |
| 49 | }); |
| 50 | |
| 51 | it('handles PNG payload correctly', () => { |
| 52 | const boundary = 'PngBoundary'; |
| 53 | const pngHeader = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); |
| 54 | const body = buildMultipart(boundary, 'image.png', 'image/png', pngHeader); |
| 55 | const result = parseMultipartFile(body, boundary); |
| 56 | assert.ok(result); |
| 57 | assert.strictEqual(result.filename, 'image.png'); |
| 58 | assert.deepStrictEqual(result.data, pngHeader); |
| 59 | }); |
| 60 | |
| 61 | it('handles filename with spaces and special chars', () => { |
| 62 | const boundary = 'SpaceBoundary'; |
| 63 | const data = Buffer.from([0xFF, 0xD8, 0xFF]); |
| 64 | const body = buildMultipart(boundary, 'my photo (1).jpg', 'image/jpeg', data); |
| 65 | const result = parseMultipartFile(body, boundary); |
| 66 | assert.ok(result); |
| 67 | assert.strictEqual(result.filename, 'my photo (1).jpg'); |
| 68 | }); |
| 69 | |
| 70 | it('defaults content-type to application/octet-stream when missing', () => { |
| 71 | const boundary = 'NoCtBoundary'; |
| 72 | const data = Buffer.from([0xFF, 0xD8, 0xFF]); |
| 73 | const parts = [ |
| 74 | `--${boundary}\r\n`, |
| 75 | `Content-Disposition: form-data; name="image"; filename="photo.jpg"\r\n`, |
| 76 | `\r\n`, |
| 77 | ]; |
| 78 | const header = Buffer.from(parts.join(''), 'binary'); |
| 79 | const footer = Buffer.from(`\r\n--${boundary}--\r\n`, 'binary'); |
| 80 | const body = Buffer.concat([header, data, footer]); |
| 81 | const result = parseMultipartFile(body, boundary); |
| 82 | assert.ok(result); |
| 83 | assert.strictEqual(result.contentType, 'application/octet-stream'); |
| 84 | }); |
| 85 | }); |
File History
2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠
1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6
docs: accept Calendar Events v0 spec with Phase 0 security …
Human
1 day ago