Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/sessions/test/e2e/common.cjs
13394 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
// @ts-check
7
8
/**
9
* Shared helpers for the Sessions E2E test infrastructure.
10
*/
11
12
const fs = require('fs');
13
const path = require('path');
14
const cp = require('child_process');
15
16
const APP_ROOT = path.resolve(__dirname, '..', '..', '..', '..', '..');
17
const SCENARIOS_DIR = path.join(__dirname, 'scenarios');
18
19
// ---------------------------------------------------------------------------
20
// Scenario parser
21
// ---------------------------------------------------------------------------
22
23
function parseScenario(filePath) {
24
const raw = fs.readFileSync(filePath, 'utf-8');
25
const lines = raw.split('\n');
26
let name = path.basename(filePath, '.scenario.md');
27
const steps = [];
28
let inSteps = false;
29
30
for (const line of lines) {
31
const trimmed = line.trim();
32
if (trimmed.startsWith('# ')) { name = trimmed.slice(2).trim(); }
33
if (/^## steps?$/i.test(trimmed)) { inSteps = true; continue; }
34
if (trimmed.startsWith('## ')) { inSteps = false; continue; }
35
if (inSteps) {
36
const m = trimmed.match(/^(?:-|\d+\.)\s+(.*)/);
37
if (m) { steps.push(m[1].trim()); }
38
}
39
}
40
return { name, steps, filePath };
41
}
42
43
function discoverScenarios() {
44
return fs.readdirSync(SCENARIOS_DIR)
45
.filter(f => f.endsWith('.scenario.md'))
46
.sort()
47
.map(f => parseScenario(path.join(SCENARIOS_DIR, f)));
48
}
49
50
// ---------------------------------------------------------------------------
51
// playwright-cli wrapper
52
// ---------------------------------------------------------------------------
53
54
function runPlaywrightCli(args) {
55
const argList = Array.isArray(args)
56
? args
57
: (args.match(/"[^"]*"|\S+/g) || []).map(s => s.replace(/^"|"$/g, ''));
58
const result = cp.spawnSync('playwright-cli', argList, {
59
cwd: APP_ROOT,
60
stdio: ['ignore', 'pipe', 'pipe'],
61
timeout: 30_000,
62
env: { ...process.env },
63
});
64
const stdout = (result.stdout || '').toString();
65
const stderr = (result.stderr || '').toString();
66
return { ok: result.status === 0, stdout, stderr };
67
}
68
69
function getSnapshot() {
70
const result = runPlaywrightCli(['snapshot']);
71
if (!result.ok) {
72
console.error(` [snapshot] failed: ${result.stderr}`);
73
return {
74
stdout: '',
75
path: ''
76
};
77
}
78
const fileMatch = result.stdout.match(/\[Snapshot\]\((.+?\.yml)\)/);
79
let pathStr = '';
80
if (fileMatch) {
81
pathStr = path.join(APP_ROOT, fileMatch[1]);
82
try {
83
const content = fs.readFileSync(pathStr, 'utf-8');
84
if (!content.trim()) { console.error(` [snapshot] file is empty`); }
85
return { stdout: content, path: pathStr };
86
} catch (e) {
87
console.error(` [snapshot] failed to read: ${e.message}`);
88
}
89
}
90
return {
91
stdout: result.stdout,
92
path: pathStr
93
};
94
}
95
96
// ---------------------------------------------------------------------------
97
// Server management
98
// ---------------------------------------------------------------------------
99
100
function startServer(port, { mock = false } = {}) {
101
const args = ['--no-open', '--port', String(port)];
102
if (mock) { args.push('--mock'); }
103
const server = cp.spawn(process.execPath, [
104
path.join(APP_ROOT, 'scripts', 'code-sessions-web.js'),
105
...args,
106
], {
107
cwd: APP_ROOT,
108
stdio: ['ignore', 'pipe', 'pipe'],
109
env: { ...process.env },
110
});
111
server.stdout.on('data', () => { });
112
server.stderr.on('data', () => { });
113
return server;
114
}
115
116
async function waitForServer(url, timeoutMs) {
117
const http = require('http');
118
const deadline = Date.now() + timeoutMs;
119
while (Date.now() < deadline) {
120
const ok = await new Promise(resolve => {
121
const req = http.get(url, res => { res.resume(); resolve(res.statusCode === 200); });
122
req.on('error', () => resolve(false));
123
req.setTimeout(1000, () => { req.destroy(); resolve(false); });
124
});
125
if (ok) { return; }
126
await new Promise(r => setTimeout(r, 500));
127
}
128
throw new Error(`Server at ${url} did not start within ${timeoutMs}ms`);
129
}
130
131
// ---------------------------------------------------------------------------
132
// Commands file paths
133
// ---------------------------------------------------------------------------
134
135
function commandsPathForScenario(scenarioPath) {
136
const dir = path.join(path.dirname(scenarioPath), 'generated');
137
const name = path.basename(scenarioPath, '.scenario.md') + '.commands.json';
138
return path.join(dir, name);
139
}
140
141
module.exports = {
142
APP_ROOT,
143
SCENARIOS_DIR,
144
parseScenario,
145
discoverScenarios,
146
runPlaywrightCli,
147
getSnapshot,
148
startServer,
149
waitForServer,
150
commandsPathForScenario,
151
};
152
153