Files
camofox-browser/tests/e2e/snapshotScreenshot.test.js
T
Pradeep Elankumaran 1bdd925371 feat: OpenAPI spec + swagger-stripey docs at /docs (#78)
Auto-generated OpenAPI 3.0 spec from JSDoc annotations on all 31 routes via swagger-jsdoc. Docs at /docs using swagger-stripey. CI split into parallel unit + e2e jobs (133s → 80s).

Supersedes #69. Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-04-25 11:52:02 -07:00

208 lines
6.6 KiB
JavaScript

import { createClient } from '../helpers/client.js';
import { PNG } from 'pngjs';
import { getSharedEnv } from './sharedEnv.js';
describe('Snapshot with includeScreenshot', () => {
let serverUrl;
let testSiteUrl;
beforeAll(() => {
const env = getSharedEnv();
serverUrl = env.serverUrl;
testSiteUrl = env.testSiteUrl;
});
// Server lifecycle managed by globalSetup/globalTeardown
test('snapshot without includeScreenshot has no screenshot field', async () => {
const client = createClient(serverUrl);
try {
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
const snapshot = await client.getSnapshot(tabId);
expect(snapshot.url).toContain('/pageA');
expect(snapshot.snapshot).toBeDefined();
expect(snapshot.refsCount).toBeDefined();
expect(snapshot.screenshot).toBeUndefined();
} finally {
await client.cleanup();
}
});
test('snapshot with includeScreenshot returns screenshot object', async () => {
const client = createClient(serverUrl);
try {
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
const snapshot = await client.getSnapshot(tabId, { includeScreenshot: true });
expect(snapshot.url).toContain('/pageA');
expect(snapshot.snapshot).toBeDefined();
expect(snapshot.refsCount).toBeDefined();
// Screenshot should be present with base64 data and mimeType
expect(snapshot.screenshot).toBeDefined();
expect(snapshot.screenshot.mimeType).toBe('image/png');
expect(typeof snapshot.screenshot.data).toBe('string');
expect(snapshot.screenshot.data.length).toBeGreaterThan(0);
} finally {
await client.cleanup();
}
});
test('screenshot data is valid base64-encoded PNG', async () => {
const client = createClient(serverUrl);
try {
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
const snapshot = await client.getSnapshot(tabId, { includeScreenshot: true });
const decoded = Buffer.from(snapshot.screenshot.data, 'base64');
// PNG magic bytes: 0x89 P N G
expect(decoded[0]).toBe(0x89);
expect(decoded[1]).toBe(0x50);
expect(decoded[2]).toBe(0x4e);
expect(decoded[3]).toBe(0x47);
} finally {
await client.cleanup();
}
});
test('snapshot ARIA tree is identical with and without screenshot', async () => {
const client = createClient(serverUrl);
try {
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
const withoutScreenshot = await client.getSnapshot(tabId);
const withScreenshot = await client.getSnapshot(tabId, { includeScreenshot: true });
expect(withScreenshot.snapshot).toBe(withoutScreenshot.snapshot);
expect(withScreenshot.refsCount).toBe(withoutScreenshot.refsCount);
expect(withScreenshot.url).toBe(withoutScreenshot.url);
} finally {
await client.cleanup();
}
});
test('includeScreenshot works on /snapshot (OpenClaw format)', async () => {
const client = createClient(serverUrl);
try {
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
// Use the /snapshot endpoint directly (OpenClaw format)
const res = await fetch(
`${serverUrl}/snapshot?userId=${client.userId}&targetId=${tabId}&includeScreenshot=true`
);
expect(res.ok).toBe(true);
const data = await res.json();
expect(data.ok).toBe(true);
expect(data.format).toBe('aria');
expect(data.snapshot).toBeDefined();
// Screenshot present
expect(data.screenshot).toBeDefined();
expect(data.screenshot.mimeType).toBe('image/png');
expect(data.screenshot.data.length).toBeGreaterThan(0);
// Decode and verify PNG
const decoded = Buffer.from(data.screenshot.data, 'base64');
expect(decoded[0]).toBe(0x89);
} finally {
await client.cleanup();
}
});
test('screenshot works after navigation', async () => {
const client = createClient(serverUrl);
try {
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
await client.navigate(tabId, `${testSiteUrl}/pageB`);
const snapshot = await client.getSnapshot(tabId, { includeScreenshot: true });
expect(snapshot.url).toContain('/pageB');
expect(snapshot.screenshot).toBeDefined();
expect(snapshot.screenshot.data.length).toBeGreaterThan(0);
} finally {
await client.cleanup();
}
});
test('screenshot captures actual page content (red pixels from red box)', async () => {
const client = createClient(serverUrl);
try {
const { tabId } = await client.createTab(`${testSiteUrl}/redbox`);
const snapshot = await client.getSnapshot(tabId, { includeScreenshot: true });
const pngBuffer = Buffer.from(snapshot.screenshot.data, 'base64');
const png = PNG.sync.read(pngBuffer);
// Image should have real dimensions
expect(png.width).toBeGreaterThan(0);
expect(png.height).toBeGreaterThan(0);
// Count red pixels (R=255, G=0, B=0) — the 200x200 red box should produce many
let redPixels = 0;
for (let i = 0; i < png.data.length; i += 4) {
const r = png.data[i];
const g = png.data[i + 1];
const b = png.data[i + 2];
if (r === 255 && g === 0 && b === 0) {
redPixels++;
}
}
// 200x200 box = 40,000 red pixels expected, allow some tolerance for anti-aliasing
expect(redPixels).toBeGreaterThan(30000);
} finally {
await client.cleanup();
}
});
test('screenshot of white page has no red pixels (control test)', async () => {
const client = createClient(serverUrl);
try {
const { tabId } = await client.createTab(`${testSiteUrl}/pageA`);
const snapshot = await client.getSnapshot(tabId, { includeScreenshot: true });
const pngBuffer = Buffer.from(snapshot.screenshot.data, 'base64');
const png = PNG.sync.read(pngBuffer);
let redPixels = 0;
for (let i = 0; i < png.data.length; i += 4) {
const r = png.data[i];
const g = png.data[i + 1];
const b = png.data[i + 2];
if (r === 255 && g === 0 && b === 0) {
redPixels++;
}
}
// A normal text page should have zero or near-zero pure red pixels
expect(redPixels).toBeLessThan(100);
} finally {
await client.cleanup();
}
});
test('non-existent tab returns 404 even with includeScreenshot', async () => {
const client = createClient(serverUrl);
try {
await expect(
client.getSnapshot('non-existent-tab', { includeScreenshot: true })
).rejects.toMatchObject({ status: 404 });
} finally {
await client.cleanup();
}
});
});