Skip to content

Commit 38107f3

Browse files
committed
Add e2e test for opening files externally
1 parent dcdcaf3 commit 38107f3

File tree

2 files changed

+86
-34
lines changed

2 files changed

+86
-34
lines changed

test/e2e/models/CodeServer.ts

+78-32
Original file line numberDiff line numberDiff line change
@@ -117,40 +117,26 @@ export class CodeServer {
117117
* directories.
118118
*/
119119
private async spawn(): Promise<CodeServerProcess> {
120-
// This will be used both as the workspace and data directory to ensure
121-
// instances don't bleed into each other.
122120
const dir = await this.createWorkspace()
123-
121+
const args = await this.argsWithDefaults([
122+
"--auth",
123+
"none",
124+
// The workspace to open.
125+
...(this.args.includes("--ignore-last-opened") ? [] : [dir]),
126+
...this.args,
127+
// Using port zero will spawn on a random port.
128+
"--bind-addr",
129+
"127.0.0.1:0",
130+
])
124131
return new Promise((resolve, reject) => {
125-
const args = [
126-
this.entry,
127-
"--extensions-dir",
128-
path.join(dir, "extensions"),
129-
"--auth",
130-
"none",
131-
// The workspace to open.
132-
...(this.args.includes("--ignore-last-opened") ? [] : [dir]),
133-
...this.args,
134-
// Using port zero will spawn on a random port.
135-
"--bind-addr",
136-
"127.0.0.1:0",
137-
// Setting the XDG variables would be easier and more thorough but the
138-
// modules we import ignores those variables for non-Linux operating
139-
// systems so use these flags instead.
140-
"--config",
141-
path.join(dir, "config.yaml"),
142-
"--user-data-dir",
143-
dir,
144-
]
145132
this.logger.debug("spawning `node " + args.join(" ") + "`")
146133
const proc = cp.spawn("node", args, {
147134
cwd: path.join(__dirname, "../../.."),
148135
env: {
149136
...process.env,
150137
...this.env,
151-
// Set to empty string to prevent code-server from
152-
// using the existing instance when running the e2e tests
153-
// from an integrated terminal.
138+
// Prevent code-server from using the existing instance when running
139+
// the e2e tests from an integrated terminal.
154140
VSCODE_IPC_HOOK_CLI: "",
155141
PASSWORD,
156142
},
@@ -173,11 +159,15 @@ export class CodeServer {
173159
reject(error)
174160
})
175161

162+
// Tracks when the HTTP and session servers are ready.
163+
let httpAddress: string | undefined
164+
let sessionAddress: string | undefined
165+
176166
let resolved = false
177167
proc.stdout.setEncoding("utf8")
178168
onLine(proc, (line) => {
179169
// As long as we are actively getting input reset the timer. If we stop
180-
// getting input and still have not found the address the timer will
170+
// getting input and still have not found the addresses the timer will
181171
// reject.
182172
timer.reset()
183173

@@ -186,20 +176,69 @@ export class CodeServer {
186176
if (resolved) {
187177
return
188178
}
189-
const match = line.trim().match(/HTTPS? server listening on (https?:\/\/[.:\d]+)\/?$/)
179+
180+
let match = line.trim().match(/HTTPS? server listening on (https?:\/\/[.:\d]+)\/?$/)
190181
if (match) {
191-
// Cookies don't seem to work on IP address so swap to localhost.
182+
// Cookies don't seem to work on IP addresses so swap to localhost.
192183
// TODO: Investigate whether this is a bug with code-server.
193-
const address = match[1].replace("127.0.0.1", "localhost")
194-
this.logger.debug(`spawned on ${address}`)
184+
httpAddress = match[1].replace("127.0.0.1", "localhost")
185+
}
186+
187+
match = line.trim().match(/Session server listening on (.+)$/)
188+
if (match) {
189+
sessionAddress = match[1]
190+
}
191+
192+
if (typeof httpAddress !== "undefined" && typeof sessionAddress !== "undefined") {
195193
resolved = true
196194
timer.dispose()
197-
resolve({ process: proc, address })
195+
this.logger.debug(`code-server is ready: ${httpAddress} ${sessionAddress}`)
196+
resolve({ process: proc, address: httpAddress })
198197
}
199198
})
200199
})
201200
}
202201

202+
/**
203+
* Execute a short-lived command.
204+
*/
205+
async run(args: string[]): Promise<void> {
206+
args = await this.argsWithDefaults(args)
207+
this.logger.debug("executing `node " + args.join(" ") + "`")
208+
await util.promisify(cp.exec)("node " + args.join(" "), {
209+
cwd: path.join(__dirname, "../../.."),
210+
env: {
211+
...process.env,
212+
...this.env,
213+
// Prevent code-server from using the existing instance when running
214+
// the e2e tests from an integrated terminal.
215+
VSCODE_IPC_HOOK_CLI: "",
216+
},
217+
})
218+
}
219+
220+
/**
221+
* Combine arguments with defaults.
222+
*/
223+
private async argsWithDefaults(args: string[]): Promise<string[]> {
224+
// This will be used both as the workspace and data directory to ensure
225+
// instances don't bleed into each other.
226+
const dir = await this.workspaceDir
227+
return [
228+
this.entry,
229+
"--extensions-dir",
230+
path.join(dir, "extensions"),
231+
...args,
232+
// Setting the XDG variables would be easier and more thorough but the
233+
// modules we import ignores those variables for non-Linux operating
234+
// systems so use these flags instead.
235+
"--config",
236+
path.join(dir, "config.yaml"),
237+
"--user-data-dir",
238+
dir,
239+
]
240+
}
241+
203242
/**
204243
* Close the code-server process.
205244
*/
@@ -364,6 +403,13 @@ export class CodeServerPage {
364403
await this.waitForTab(file)
365404
}
366405

406+
/**
407+
* Open a file through an external command.
408+
*/
409+
async openFileExternally(file: string) {
410+
await this.codeServer.run(["--reuse-window", file])
411+
}
412+
367413
/**
368414
* Wait for a tab to open for the specified file.
369415
*/

test/e2e/terminal.test.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,19 @@ describe("Integrated Terminal", ["--disable-workspace-trust"], {}, () => {
3535
const tmpFolderPath = await tmpdir(testName)
3636
const tmpFile = path.join(tmpFolderPath, "test-file")
3737
await fs.writeFile(tmpFile, "test")
38-
const fileName = path.basename(tmpFile)
3938

4039
await codeServerPage.focusTerminal()
4140

4241
await codeServerPage.page.keyboard.type(`code-server ${tmpFile}`)
4342
await codeServerPage.page.keyboard.press("Enter")
4443

45-
await codeServerPage.waitForTab(fileName)
44+
await codeServerPage.waitForTab(path.basename(tmpFile))
45+
46+
const externalTmpFile = path.join(tmpFolderPath, "test-external-file")
47+
await fs.writeFile(externalTmpFile, "foobar")
48+
49+
await codeServerPage.openFileExternally(externalTmpFile)
50+
51+
await codeServerPage.waitForTab(path.basename(externalTmpFile))
4652
})
4753
})

0 commit comments

Comments
 (0)