Fix structured attachment rendering (#69)

* review: harden readonly git checks and lint verification

* test: satisfy readonly reviewer sandbox typing

* test: fix readonly reviewer sandbox assertions

* test: remove impossible readonly sandbox guards

* test: relax readonly sandbox assertions

* test: cast readonly sandbox expectation shape

* test: cast readonly sandbox expectation through unknown

* Phase 0 — STEP_DONE/TASK_DONE split + owner-follow-up integration smoke

* Add STEP_DONE guards, verdict storage, and stale delivery suppression

* style: format paired stepdone telemetry files

* Route STEP_DONE through reviewer

* Add structured Discord attachments

* style: format structured attachment test

* Fix room thread bot output parity

* Remove duplicate work item attachment migration from owner branch

* Remove legacy dashboard rooms renderer

* Extract dashboard parsed body renderer

* Extract dashboard redaction helpers

* Extract dashboard RoomCardV2 component

* Include RoomCardV2 test in vitest suite

* Extract dashboard RoomBoardV2 component

* Extract dashboard EmptyState component

* Extract dashboard InboxPanel component

* Split dashboard InboxPanel card renderer

* Extract dashboard TaskPanel component

* Extract dashboard UsagePanel component

* Fix dashboard room thread chunk rendering

* Extract dashboard ServicePanel component

* Render dashboard live progress markdown

* Extract dashboard SettingsPanel component

* Fix structured attachment rendering
This commit is contained in:
Eyejoker
2026-04-28 17:36:11 +09:00
committed by GitHub
parent 96d99f63e0
commit 6197e90c8c
18 changed files with 837 additions and 104 deletions

View File

@@ -0,0 +1,46 @@
import fs from 'fs';
import os from 'os';
import path from 'path';
import { afterEach, describe, expect, it } from 'vitest';
import { createWebDashboardHandler } from './web-dashboard-server.js';
const ONE_PIXEL_PNG = Buffer.from(
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII=',
'base64',
);
const tempFiles: string[] = [];
afterEach(() => {
for (const file of tempFiles.splice(0)) {
fs.rmSync(file, { force: true });
}
});
describe('web dashboard attachment previews', () => {
it('serves validated direct temp image attachments', async () => {
const filePath = path.join(
os.tmpdir(),
`bar-chart-label-fit-playwright-${Date.now()}.png`,
);
fs.writeFileSync(filePath, ONE_PIXEL_PNG);
tempFiles.push(filePath);
const handler = createWebDashboardHandler({
readStatusSnapshots: () => [],
getTasks: () => [],
getPairedTasks: () => [],
});
const response = await handler(
new Request(
`http://localhost/api/attachments?path=${encodeURIComponent(filePath)}`,
),
);
expect(response.status).toBe(200);
expect(response.headers.get('content-type')).toBe('image/png');
expect(Buffer.from(await response.arrayBuffer())).toEqual(ONE_PIXEL_PNG);
});
});