-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Expand file tree
/
Copy pathglobalSetup.ts
More file actions
155 lines (133 loc) · 4.62 KB
/
globalSetup.ts
File metadata and controls
155 lines (133 loc) · 4.62 KB
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
// Unset NO_COLOR environment variable to ensure consistent theme behavior between local and CI test runs
if (process.env['NO_COLOR'] !== undefined) {
delete process.env['NO_COLOR'];
}
import { mkdir, readdir, rm, readFile } from 'node:fs/promises';
import { join, dirname, extname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { resolveRipgrepPath } from '../packages/core/src/tools/ripGrep.js';
import { disableMouseTracking } from '@google/gemini-cli-core';
import { isolateTestEnv } from '../packages/test-utils/src/env-setup.js';
import { createServer, type Server } from 'node:http';
const __dirname = dirname(fileURLToPath(import.meta.url));
const rootDir = join(__dirname, '..');
const integrationTestsDir = join(rootDir, '.integration-tests');
let runDir = ''; // Make runDir accessible in teardown
let fixtureServer: Server | undefined;
const FIXTURE_PORT = 18923;
const FIXTURE_DIR = join(__dirname, 'test-fixtures');
const MIME_TYPES: Record<string, string> = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'application/javascript',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.svg': 'image/svg+xml',
};
async function startFixtureServer(): Promise<number> {
return new Promise((resolve, reject) => {
const server = createServer(async (req, res) => {
const urlPath = req.url?.split('?')[0] || '/';
const relativePath = urlPath === '/' ? 'index.html' : urlPath;
const filePath = join(FIXTURE_DIR, relativePath);
if (!filePath.startsWith(FIXTURE_DIR)) {
res.writeHead(403, { 'Content-Type': 'text/html' });
res.end('<h1>403 Forbidden</h1>');
return;
}
try {
const content = await readFile(filePath);
const ext = extname(filePath);
res.writeHead(200, {
'Content-Type': MIME_TYPES[ext] || 'application/octet-stream',
});
res.end(content);
} catch {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end('<h1>404 Not Found</h1>');
}
});
server.on('error', (err: NodeJS.ErrnoException) => {
if (err.code === 'EADDRINUSE') {
console.warn(
`Port ${FIXTURE_PORT} in use, trying ${FIXTURE_PORT + 1}...`,
);
server.listen(FIXTURE_PORT + 1, '127.0.0.1');
} else {
reject(err);
}
});
server.on('listening', () => {
const addr = server.address();
const port = typeof addr === 'object' && addr ? addr.port : FIXTURE_PORT;
fixtureServer = server;
console.log(`Test fixture server listening on http://127.0.0.1:${port}`);
resolve(port);
});
server.listen(FIXTURE_PORT, '127.0.0.1');
});
}
export async function setup() {
runDir = join(integrationTestsDir, `${Date.now()}`);
await mkdir(runDir, { recursive: true });
// Isolate environment variables
isolateTestEnv(runDir);
// Download ripgrep to avoid race conditions in parallel tests
const available = await resolveRipgrepPath();
if (!available) {
throw new Error('Failed to download ripgrep binary');
}
// Start the test fixture server
const port = await startFixtureServer();
process.env['TEST_FIXTURE_PORT'] = String(port);
// Clean up old test runs, but keep the latest few for debugging
try {
const testRuns = await readdir(integrationTestsDir);
if (testRuns.length > 5) {
const oldRuns = testRuns.sort().slice(0, testRuns.length - 5);
await Promise.all(
oldRuns.map((oldRun) =>
rm(join(integrationTestsDir, oldRun), {
recursive: true,
force: true,
}),
),
);
}
} catch (e) {
console.error('Error cleaning up old test runs:', e);
}
process.env['INTEGRATION_TEST_FILE_DIR'] = runDir;
if (process.env['KEEP_OUTPUT']) {
console.log(`Keeping output for test run in: ${runDir}`);
}
process.env['VERBOSE'] = process.env['VERBOSE'] ?? 'false';
console.log(`\nIntegration test output directory: ${runDir}`);
}
export async function teardown() {
// Stop the fixture server
if (fixtureServer) {
await new Promise<void>((resolve) => {
fixtureServer!.close(() => resolve());
});
fixtureServer = undefined;
}
// Disable mouse tracking
if (process.stdout.isTTY) {
disableMouseTracking();
}
// Cleanup the test run directory unless KEEP_OUTPUT is set
if (process.env['KEEP_OUTPUT'] !== 'true' && runDir) {
try {
await rm(runDir, { recursive: true, force: true });
} catch (e) {
console.warn('Failed to clean up test run directory:', e);
}
}
}