Files
makelore/tests/e2e/opencode-image-compression.spec.ts

199 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import sharp from 'sharp';
import {
closeElectronApp,
expect,
getStableWindow,
test,
} from './fixtures/electron';
test.describe('OpenCode image compression composer', () => {
test('preprocesses a 4K image and lets the user switch variants', async ({
launchElectronApp,
}) => {
const app = await launchElectronApp({ skipSetup: true });
try {
await app.evaluate(async () => {
const { ipcMain } = process.mainModule!.require('electron') as typeof import('electron');
const activeProject = {
id: 'prj_e2e_compression',
path: 'D:/e2e/image-compression',
name: 'image-compression',
createdAt: '2026-07-18T00:00:00.000Z',
updatedAt: '2026-07-18T00:00:00.000Z',
lastOpenedAt: '2026-07-18T00:00:00.000Z',
};
const agent = {
id: 'game-development',
avatarId: 'avatar-01',
roleName: 'Game Developer',
name: 'Game Developer',
builtIn: false,
enabled: true,
model: 'niancode-user-models/qwen3.7-plus',
skillIds: [],
responsibility: {
mission: 'Build and verify the project.',
owns: [],
boundaries: [],
collaborators: [],
principles: [],
},
prompt: '',
archivedAt: null,
pinned: false,
};
const projectConfig = {
schemaVersion: 1,
projectType: 'custom',
initialized: true,
defaultModel: agent.model,
agents: [agent],
knowledgeDirectory: 'knowledge',
createdAt: '2026-07-18T00:00:00.000Z',
updatedAt: '2026-07-18T00:00:00.000Z',
};
const respond = (json: unknown, status = 200) => ({
ok: true,
data: {
status,
ok: status >= 200 && status < 300,
json,
},
});
ipcMain.removeHandler('hostapi:fetch');
ipcMain.handle('hostapi:fetch', async (
_event: unknown,
request: { path?: string; method?: string },
) => {
const path = request.path ?? '';
const method = request.method ?? 'GET';
if (path === '/api/opencode/status') {
return respond({
state: 'running',
port: 4096,
url: 'http://127.0.0.1:4096',
});
}
if (path.startsWith('/api/opencode/projects/config?')) {
return respond({
status: 'valid',
config: projectConfig,
knowledgeFiles: [],
});
}
if (path.startsWith('/api/opencode/projects/template?')) {
return respond({ status: 'missing' });
}
if (path.startsWith('/api/opencode/projects/conversations?')) {
return respond({
state: {
schemaVersion: 1,
sessions: [{
sessionId: 'ses_e2e_compression',
agentId: agent.id,
archivedAt: null,
unreadCount: 0,
createdAt: '2026-07-18T00:00:00.000Z',
updatedAt: '2026-07-18T00:00:00.000Z',
}],
updatedAt: '2026-07-18T00:00:00.000Z',
},
});
}
if (
path === '/api/opencode/projects'
|| path.startsWith('/api/opencode/projects?')
|| (path === '/api/opencode/projects/active' && method === 'GET')
) {
return respond({ projects: [activeProject], activeProject });
}
if (path === '/api/opencode/config-summary') {
return respond({
model: 'niancode-user-models/qwen3.7-plus',
smallModel: null,
providerIds: ['niancode-user-models'],
providerCount: 1,
});
}
if (path === '/api/opencode/sessions') {
return respond({
sessions: [{
id: 'ses_e2e_compression',
title: 'Image compression',
agent: agent.id,
updatedAt: '2026-07-18T00:00:00.000Z',
}],
});
}
if (path === '/api/opencode/sessions/status') {
return respond({
statuses: { ses_e2e_compression: { type: 'idle' } },
});
}
if (
path === '/api/opencode/sessions/ses_e2e_compression/messages'
&& method === 'GET'
) {
return respond({ messages: [] });
}
if (path.endsWith('/todos')) return respond({ todos: [] });
if (path === '/api/provider-accounts') return respond([]);
if (path === '/api/provider-accounts/key-info') return respond([]);
if (path === '/api/provider-vendors') return respond([]);
if (path === '/api/provider-accounts/default') {
return respond({ accountId: null });
}
return respond({});
});
});
const page = await getStableWindow(app);
await page.reload();
await expect(page.getByTestId('ai-module-selection-page')).toBeVisible();
await page.getByTestId('ai-module-option-programming').click();
const composer = page.getByTestId('opencode-message-composer');
await expect(composer).toBeVisible();
const projectAgent = page.getByTestId('project-agent-chat-game-development');
await projectAgent.click();
await expect(projectAgent).toHaveAttribute('aria-pressed', 'true');
await expect(composer.getByRole('button').first()).toBeEnabled();
const png = await sharp({
create: {
width: 3840,
height: 2160,
channels: 4,
background: { r: 64, g: 210, b: 200, alpha: 1 },
},
}).png().toBuffer();
await page.getByTestId('opencode-file-attachment-input').setInputFiles({
name: 'four-k.png',
mimeType: 'image/png',
buffer: png,
});
const card = page.getByTestId('opencode-composer-attachment');
await expect(card).toContainText('3840×2160');
await expect(card).toContainText('1930×1086');
await expect(page.getByTestId('opencode-attachment-use-compressed'))
.toHaveAttribute('aria-pressed', 'true');
await expect(page.getByTestId('opencode-attachment-token-estimate'))
.toContainText('约2049 Token');
await page.getByTestId('opencode-attachment-use-original').click();
await expect(page.getByTestId('opencode-attachment-use-original'))
.toHaveAttribute('aria-pressed', 'true');
await expect(page.getByTestId('opencode-attachment-token-estimate'))
.toContainText('约8102 Token');
await page.getByTestId('opencode-attachment-use-compressed').click();
await expect(page.getByTestId('opencode-attachment-use-compressed'))
.toHaveAttribute('aria-pressed', 'true');
await page.getByRole('button', { name: '移除附件 four-k.png' }).click();
await expect(card).toHaveCount(0);
} finally {
await closeElectronApp(app);
}
});
});