File size: 2,880 Bytes
097fb32 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | /**
* test/unit-vision.mjs
*
* 单元测试:Vision 拦截器仅处理 user 图片消息
* 运行方式:node test/unit-vision.mjs
*/
let passed = 0;
let failed = 0;
async function test(name, fn) {
try {
await fn();
console.log(` ✅ ${name}`);
passed++;
} catch (e) {
console.error(` ❌ ${name}`);
console.error(` ${e.message}`);
failed++;
}
}
function assert(condition, msg) {
if (!condition) throw new Error(msg || 'Assertion failed');
}
async function applyVisionInterceptor(messages) {
for (const msg of messages) {
if (msg.role !== 'user') continue;
if (!Array.isArray(msg.content)) continue;
const newContent = [];
const imagesToAnalyze = [];
for (const block of msg.content) {
if (block.type === 'image') {
imagesToAnalyze.push(block);
} else {
newContent.push(block);
}
}
if (imagesToAnalyze.length > 0) {
newContent.push({
type: 'text',
text: `[System: The user attached ${imagesToAnalyze.length} image(s). Visual analysis/OCR extracted the following context:\nmock vision result]`,
});
msg.content = newContent;
}
}
}
console.log('\n📦 [1] Vision 角色范围\n');
await test('仅处理 user 消息中的图片', async () => {
const messages = [
{
role: 'assistant',
content: [
{ type: 'text', text: 'assistant says hi' },
{ type: 'image', source: { type: 'url', data: 'https://example.com/a.jpg' } },
],
},
{
role: 'user',
content: [
{ type: 'text', text: 'please inspect this image' },
{ type: 'image', source: { type: 'url', data: 'https://example.com/b.jpg' } },
],
},
];
await applyVisionInterceptor(messages);
assert(messages[0].content.some(block => block.type === 'image'), 'assistant image should remain untouched');
assert(messages[1].content.every(block => block.type !== 'image'), 'user images should be converted away');
assert(messages[1].content.some(block => block.type === 'text' && block.text.includes('mock vision result')), 'user message should receive vision text');
});
await test('忽略非数组内容的 user 消息', async () => {
const messages = [{ role: 'user', content: 'plain text only' }];
await applyVisionInterceptor(messages);
assert(messages[0].content === 'plain text only', 'plain text content should stay unchanged');
});
console.log('\n' + '═'.repeat(55));
console.log(` 结果: ${passed} 通过 / ${failed} 失败 / ${passed + failed} 总计`);
console.log('═'.repeat(55) + '\n');
if (failed > 0) process.exit(1);
|