visual-journal / scripts /dimension-check.test.mjs
misonL's picture
Deploy e9050df to Docker Space
a51c565 verified
Raw
History Blame Contribute Delete
11.6 kB
import {
DimensionCheckError,
assertImageDimensions,
buildDimensionCheckFailureBody,
isDimensionCheckError,
parseExpectedDimensions,
sanitizeImageResponse
} from '../skills/gpt-image-playground-agent/scripts/lib/dimension-check.mjs';
import assert from 'node:assert/strict';
import { createServer } from 'node:http';
import { test } from 'node:test';
test('assertImageDimensions records dimensions for inline base64 images', async () => {
const response = {
images: [{ id: 'ok', b64_json: pngBase64(320, 240) }]
};
const checked = await assertImageDimensions({
response,
expected: { width: 320, height: 240 },
baseUrl: 'http://127.0.0.1:1',
authHeaders: {}
});
assert.deepEqual(checked.images[0].dimensions, { width: 320, height: 240 });
assert.equal(checked.images[0].b64_json, response.images[0].b64_json);
});
test('assertImageDimensions rejects mismatched dimensions with sanitized response', async () => {
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{ id: 'bad', b64_json: pngBase64(512, 512) }] },
expected: { width: 1024, height: 1024 },
baseUrl: 'http://127.0.0.1:1',
authHeaders: {}
}),
(error) => {
assert.equal(error instanceof DimensionCheckError, true);
assert.equal(error.code, 'dimension_check_failed');
assert.deepEqual(error.expectedDimensions, { width: 1024, height: 1024 });
assert.deepEqual(error.actualDimensions, { width: 512, height: 512 });
assert.equal(error.response.images[0].b64_json, undefined);
assert.equal(Object.prototype.hasOwnProperty.call(error.response.images[0], 'b64_json'), false);
assert.equal(error.response.images[0].b64_json_length, pngBase64(512, 512).length);
assert.deepEqual(error.response.images[0].dimensions, { width: 512, height: 512 });
return true;
}
);
});
test('assertImageDimensions rejects missing and empty image lists', async () => {
for (const response of [{}, { images: [] }]) {
await assert.rejects(
() =>
assertImageDimensions({
response,
expected: { width: 1024, height: 1024 },
baseUrl: 'http://127.0.0.1:1',
authHeaders: {}
}),
/响应中没有可验收的图片/
);
}
});
test('assertImageDimensions reads same-origin content URLs with auth headers', async () => {
const requests = [];
await withServer(
(request, response) => {
requests.push({ url: request.url, authorization: request.headers.authorization });
response.writeHead(200, { 'content-type': 'image/png' });
response.end(pngBuffer(640, 360));
},
async (baseUrl) => {
const checked = await assertImageDimensions({
response: { images: [{ id: 'url-image', content_url: '/artifact/url-image.png' }] },
expected: { width: 640, height: 360 },
baseUrl,
authHeaders: () => ({ Authorization: 'Bearer test-token' })
});
assert.deepEqual(checked.images[0].dimensions, { width: 640, height: 360 });
assert.equal(requests[0].url, '/artifact/url-image.png');
assert.equal(requests[0].authorization, 'Bearer test-token');
}
);
});
test('assertImageDimensions rejects path fields unless callers opt in explicitly', async () => {
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{ path: '/artifact/from-path.png' }] },
expected: { width: 1, height: 1 },
baseUrl: 'http://127.0.0.1:1',
authHeaders: {}
}),
/dimension-check 需要 b64_json 或 absolute_content_url 或 content_url/
);
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{}] },
expected: { width: 1, height: 1 },
baseUrl: 'http://127.0.0.1:1',
authHeaders: {},
readUrlFields: ['absolute_path', 'path']
}),
/dimension-check 需要 b64_json 或 absolute_path 或 path/
);
});
test('assertImageDimensions converts download failures and cross-origin URLs to dimension failures', async () => {
await withServer(
(_request, response) => {
response.writeHead(404, { 'content-type': 'application/json' });
response.end(JSON.stringify({ error: 'missing' }));
},
async (baseUrl) => {
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{ content_url: '/missing.png' }] },
expected: { width: 1, height: 1 },
baseUrl,
authHeaders: {}
}),
/下载产物失败,状态码 404/
);
}
);
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{ content_url: 'https://evil.example.test/image.png' }] },
expected: { width: 1, height: 1 },
baseUrl: 'https://space.example.test',
authHeaders: {}
}),
/不同 origin/
);
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{ absolute_content_url: 'https://evil.example.test/image.png' }] },
expected: { width: 1, height: 1 },
baseUrl: 'https://space.example.test',
authHeaders: {}
}),
/absolute_content_url 指向不同 origin/
);
});
test('assertImageDimensions times out stalled streamed downloads', async () => {
await withServer(
(_request, response) => {
response.writeHead(200, { 'content-type': 'image/png' });
response.write(pngBuffer(1, 1).subarray(0, 8));
},
async (baseUrl) => {
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{ content_url: '/stalled.png' }] },
expected: { width: 1, height: 1 },
baseUrl,
authHeaders: {},
timeoutMs: 25
}),
/下载产物超时,已等待 25ms/
);
}
);
});
test('assertImageDimensions falls back to default URL fields for invalid readUrlFields', async () => {
await withServer(
(_request, response) => {
response.writeHead(200, { 'content-type': 'image/png' });
response.end(pngBuffer(16, 9));
},
async (baseUrl) => {
const checked = await assertImageDimensions({
response: { images: [{ content_url: '/default-field.png' }] },
expected: { width: 16, height: 9 },
baseUrl,
authHeaders: {},
readUrlFields: null
});
assert.deepEqual(checked.images[0].dimensions, { width: 16, height: 9 });
}
);
});
test('assertImageDimensions enforces the max image byte limit', async () => {
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{ b64_json: pngBase64(1, 1) }] },
expected: { width: 1, height: 1 },
baseUrl: 'http://127.0.0.1:1',
authHeaders: {},
maxImageBytes: 8
}),
/图片数据超过 8 字节限制/
);
await withServer(
(_request, response) => {
response.writeHead(200, {
'content-type': 'image/png',
'content-length': String(pngBuffer(1, 1).length)
});
response.end(pngBuffer(1, 1));
},
async (baseUrl) => {
await assert.rejects(
() =>
assertImageDimensions({
response: { images: [{ content_url: '/large.png' }] },
expected: { width: 1, height: 1 },
baseUrl,
authHeaders: {},
maxImageBytes: 8
}),
/图片数据超过 8 字节限制/
);
}
);
});
test('dimension-check helpers expose stable structured failure bodies', () => {
const sanitized = sanitizeImageResponse({ images: [{ id: 'secret', b64_json: pngBase64(1, 1) }] });
assert.equal(sanitized.images[0].b64_json, undefined);
assert.equal(Object.prototype.hasOwnProperty.call(sanitized.images[0], 'b64_json'), false);
assert.equal(sanitized.images[0].b64_json_length, pngBase64(1, 1).length);
assert.deepEqual(parseExpectedDimensions('1024x768'), { width: 1024, height: 768 });
assert.equal(parseExpectedDimensions('auto'), undefined);
assert.equal(isDimensionCheckError(new Error('plain')), false);
const error = new DimensionCheckError('bad size', {
expected: { width: 10, height: 10 },
actual: { width: 8, height: 8 },
response: { images: [{ id: 'bad', b64_json: pngBase64(8, 8) }] },
nextStep: 'inspect'
});
const body = buildDimensionCheckFailureBody(error, { transport: 'agent_json' });
assert.equal(body.billable, true);
assert.equal(body.error.code, 'dimension_check_failed');
assert.deepEqual(body.error.expected_dimensions, { width: 10, height: 10 });
assert.deepEqual(body.error.actual_dimensions, { width: 8, height: 8 });
assert.equal(body.validation_failure_kind, 'generated_artifact_failed_dimension_check');
assert.deepEqual(body.routing, { transport: 'agent_json' });
assert.equal(body.response.images[0].b64_json, undefined);
assert.equal(Object.prototype.hasOwnProperty.call(body.response.images[0], 'b64_json'), false);
assert.equal(body.next_step, 'inspect');
const malformed = buildDimensionCheckFailureBody(
new DimensionCheckError('bad metadata', {
expected: { width: 'wide', height: 10 },
actual: { width: 8, height: 0 }
}),
undefined
);
assert.equal(malformed.error.expected_dimensions, null);
assert.equal(malformed.error.actual_dimensions, null);
});
function pngBase64(width, height) {
return pngBuffer(width, height).toString('base64');
}
function pngBuffer(width, height) {
const buffer = Buffer.alloc(24);
buffer[0] = 0x89;
buffer.write('PNG', 1, 'ascii');
buffer[4] = 0x0d;
buffer[5] = 0x0a;
buffer[6] = 0x1a;
buffer[7] = 0x0a;
buffer.writeUInt32BE(13, 8);
buffer.write('IHDR', 12, 'ascii');
buffer.writeUInt32BE(width, 16);
buffer.writeUInt32BE(height, 20);
return buffer;
}
async function withServer(handler, run) {
const server = createServer(handler);
await new Promise((resolve, reject) => {
server.once('error', reject);
server.listen(0, '127.0.0.1', resolve);
});
const address = server.address();
try {
await run(`http://127.0.0.1:${address.port}`);
} finally {
await new Promise((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
});
}
}