mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-02-01 22:48:03 +00:00
111 lines
3.6 KiB
TypeScript
111 lines
3.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import { TestRig } from './test-helper.js';
|
|
import { execSync, spawnSync } from 'node:child_process';
|
|
import * as os from 'node:os';
|
|
import * as fs from 'node:fs';
|
|
import * as path from 'node:path';
|
|
|
|
// Minimal 1x1 PNG image base64
|
|
const DUMMY_PNG_BASE64 =
|
|
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==';
|
|
|
|
describe('Linux Clipboard Integration', () => {
|
|
let rig: TestRig;
|
|
let dummyImagePath: string;
|
|
|
|
beforeEach(() => {
|
|
rig = new TestRig();
|
|
// Create a dummy image file for testing
|
|
dummyImagePath = path.join(
|
|
os.tmpdir(),
|
|
`gemini-test-clipboard-${Date.now()}.png`,
|
|
);
|
|
fs.writeFileSync(dummyImagePath, Buffer.from(DUMMY_PNG_BASE64, 'base64'));
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await rig.cleanup();
|
|
try {
|
|
if (fs.existsSync(dummyImagePath)) {
|
|
fs.unlinkSync(dummyImagePath);
|
|
}
|
|
} catch {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
// Only run this test on Linux
|
|
const runIfLinux = os.platform() === 'linux' ? it : it.skip;
|
|
|
|
runIfLinux(
|
|
'should paste image from system clipboard when Ctrl+V is pressed',
|
|
async () => {
|
|
// 1. Setup rig
|
|
await rig.setup('linux-clipboard-paste');
|
|
|
|
// 2. Inject image into system clipboard
|
|
// We attempt both Wayland and X11 tools.
|
|
let clipboardSet = false;
|
|
|
|
// Try wl-copy (Wayland)
|
|
let sessionType = '';
|
|
const wlCopy = spawnSync('wl-copy', ['--type', 'image/png'], {
|
|
input: fs.readFileSync(dummyImagePath),
|
|
});
|
|
if (wlCopy.status === 0) {
|
|
clipboardSet = true;
|
|
sessionType = 'wayland';
|
|
} else {
|
|
// Try xclip (X11)
|
|
try {
|
|
execSync(
|
|
`xclip -selection clipboard -t image/png -i "${dummyImagePath}"`,
|
|
{ stdio: 'ignore' },
|
|
);
|
|
clipboardSet = true;
|
|
sessionType = 'x11';
|
|
} catch {
|
|
// Both failed
|
|
}
|
|
}
|
|
|
|
if (!clipboardSet) {
|
|
console.warn(
|
|
'Skipping test: Could not access system clipboard (wl-copy or xclip required)',
|
|
);
|
|
return;
|
|
}
|
|
|
|
// 3. Launch CLI and simulate Ctrl+V
|
|
// We send the control character \u0016 (SYN) which corresponds to Ctrl+V
|
|
// Note: The CLI must be running and accepting input.
|
|
// The TestRig usually sends args/stdin and waits for exit or output.
|
|
// To properly test "interactive" pasting, we need the rig to support sending input *while* running.
|
|
// Assuming rig.run with 'stdin' sends it immediately.
|
|
// The CLI treats stdin as typed input if it's interactive.
|
|
|
|
// We append a small delay or a newline to ensure processing?
|
|
// Ctrl+V (\u0016) followed by a newline (\r) to submit?
|
|
// Or just Ctrl+V and check if the buffer updates (which we can't easily see in non-verbose rig output).
|
|
// If we send Ctrl+V then Enter, the CLI should submit the prompt containing the image path.
|
|
|
|
const result = await rig.run({
|
|
stdin: '\u0016\r', // Ctrl+V then Enter
|
|
env: { XDG_SESSION_TYPE: sessionType },
|
|
});
|
|
|
|
// 4. Verify Output
|
|
// Expect the CLI to have processed the image and echoed back the path (or the prompt containing it)
|
|
// The output usually contains the user's input echoed back + model response.
|
|
// The pasted image path should look like @.../clipboard-....png
|
|
expect(result).toMatch(/@\/.*\.gemini-clipboard\/clipboard-.*\.png/);
|
|
},
|
|
);
|
|
});
|