Skip to content

Commit 9d566e2

Browse files
committed
chore: add tests
1 parent af0f9dd commit 9d566e2

File tree

4 files changed

+98
-49
lines changed

4 files changed

+98
-49
lines changed

src/headers.test.ts

Lines changed: 84 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,100 @@
11
import * as os from "os"
2-
import { it, expect } from "vitest"
3-
import { getHeaders } from "./headers"
2+
import { it, expect, describe, beforeEach, afterEach, vi } from "vitest"
3+
import { WorkspaceConfiguration } from "vscode"
4+
import { getHeaderCommand, getHeaders } from "./headers"
45

56
const logger = {
67
writeToCoderOutputChannel() {
78
// no-op
89
},
910
}
1011

11-
it("should return no headers", async () => {
12-
await expect(getHeaders(undefined, undefined, logger)).resolves.toStrictEqual({})
13-
await expect(getHeaders("localhost", undefined, logger)).resolves.toStrictEqual({})
14-
await expect(getHeaders(undefined, "command", logger)).resolves.toStrictEqual({})
15-
await expect(getHeaders("localhost", "", logger)).resolves.toStrictEqual({})
16-
await expect(getHeaders("", "command", logger)).resolves.toStrictEqual({})
17-
await expect(getHeaders("localhost", " ", logger)).resolves.toStrictEqual({})
18-
await expect(getHeaders(" ", "command", logger)).resolves.toStrictEqual({})
19-
})
12+
describe("getHeaders", () => {
13+
it("should return no headers", async () => {
14+
await expect(getHeaders(undefined, undefined, logger)).resolves.toStrictEqual({})
15+
await expect(getHeaders("localhost", undefined, logger)).resolves.toStrictEqual({})
16+
await expect(getHeaders(undefined, "command", logger)).resolves.toStrictEqual({})
17+
await expect(getHeaders("localhost", "", logger)).resolves.toStrictEqual({})
18+
await expect(getHeaders("", "command", logger)).resolves.toStrictEqual({})
19+
await expect(getHeaders("localhost", " ", logger)).resolves.toStrictEqual({})
20+
await expect(getHeaders(" ", "command", logger)).resolves.toStrictEqual({})
21+
})
2022

21-
it("should return headers", async () => {
22-
await expect(getHeaders("localhost", "printf 'foo=bar\\nbaz=qux'", logger)).resolves.toStrictEqual({
23-
foo: "bar",
24-
baz: "qux",
23+
it("should return headers", async () => {
24+
await expect(getHeaders("localhost", "printf 'foo=bar\\nbaz=qux'", logger)).resolves.toStrictEqual({
25+
foo: "bar",
26+
baz: "qux",
27+
})
28+
await expect(getHeaders("localhost", "printf 'foo=bar\\r\\nbaz=qux'", logger)).resolves.toStrictEqual({
29+
foo: "bar",
30+
baz: "qux",
31+
})
32+
await expect(getHeaders("localhost", "printf 'foo=bar\\r\\n'", logger)).resolves.toStrictEqual({ foo: "bar" })
33+
await expect(getHeaders("localhost", "printf 'foo=bar'", logger)).resolves.toStrictEqual({ foo: "bar" })
34+
await expect(getHeaders("localhost", "printf 'foo=bar='", logger)).resolves.toStrictEqual({ foo: "bar=" })
35+
await expect(getHeaders("localhost", "printf 'foo=bar=baz'", logger)).resolves.toStrictEqual({ foo: "bar=baz" })
36+
await expect(getHeaders("localhost", "printf 'foo='", logger)).resolves.toStrictEqual({ foo: "" })
2537
})
26-
await expect(getHeaders("localhost", "printf 'foo=bar\\r\\nbaz=qux'", logger)).resolves.toStrictEqual({
27-
foo: "bar",
28-
baz: "qux",
38+
39+
it("should error on malformed or empty lines", async () => {
40+
await expect(getHeaders("localhost", "printf 'foo=bar\\r\\n\\r\\n'", logger)).rejects.toMatch(/Malformed/)
41+
await expect(getHeaders("localhost", "printf '\\r\\nfoo=bar'", logger)).rejects.toMatch(/Malformed/)
42+
await expect(getHeaders("localhost", "printf '=foo'", logger)).rejects.toMatch(/Malformed/)
43+
await expect(getHeaders("localhost", "printf 'foo'", logger)).rejects.toMatch(/Malformed/)
44+
await expect(getHeaders("localhost", "printf ' =foo'", logger)).rejects.toMatch(/Malformed/)
45+
await expect(getHeaders("localhost", "printf 'foo =bar'", logger)).rejects.toMatch(/Malformed/)
46+
await expect(getHeaders("localhost", "printf 'foo foo=bar'", logger)).rejects.toMatch(/Malformed/)
47+
await expect(getHeaders("localhost", "printf ''", logger)).rejects.toMatch(/Malformed/)
2948
})
30-
await expect(getHeaders("localhost", "printf 'foo=bar\\r\\n'", logger)).resolves.toStrictEqual({ foo: "bar" })
31-
await expect(getHeaders("localhost", "printf 'foo=bar'", logger)).resolves.toStrictEqual({ foo: "bar" })
32-
await expect(getHeaders("localhost", "printf 'foo=bar='", logger)).resolves.toStrictEqual({ foo: "bar=" })
33-
await expect(getHeaders("localhost", "printf 'foo=bar=baz'", logger)).resolves.toStrictEqual({ foo: "bar=baz" })
34-
await expect(getHeaders("localhost", "printf 'foo='", logger)).resolves.toStrictEqual({ foo: "" })
35-
})
3649

37-
it("should error on malformed or empty lines", async () => {
38-
await expect(getHeaders("localhost", "printf 'foo=bar\\r\\n\\r\\n'", logger)).rejects.toMatch(/Malformed/)
39-
await expect(getHeaders("localhost", "printf '\\r\\nfoo=bar'", logger)).rejects.toMatch(/Malformed/)
40-
await expect(getHeaders("localhost", "printf '=foo'", logger)).rejects.toMatch(/Malformed/)
41-
await expect(getHeaders("localhost", "printf 'foo'", logger)).rejects.toMatch(/Malformed/)
42-
await expect(getHeaders("localhost", "printf ' =foo'", logger)).rejects.toMatch(/Malformed/)
43-
await expect(getHeaders("localhost", "printf 'foo =bar'", logger)).rejects.toMatch(/Malformed/)
44-
await expect(getHeaders("localhost", "printf 'foo foo=bar'", logger)).rejects.toMatch(/Malformed/)
45-
await expect(getHeaders("localhost", "printf ''", logger)).rejects.toMatch(/Malformed/)
46-
})
50+
it("should have access to environment variables", async () => {
51+
const coderUrl = "dev.coder.com"
52+
await expect(
53+
getHeaders(coderUrl, os.platform() === "win32" ? "printf url=%CODER_URL%" : "printf url=$CODER_URL", logger),
54+
).resolves.toStrictEqual({ url: coderUrl })
55+
})
4756

48-
it("should have access to environment variables", async () => {
49-
const coderUrl = "dev.coder.com"
50-
await expect(
51-
getHeaders(coderUrl, os.platform() === "win32" ? "printf url=%CODER_URL%" : "printf url=$CODER_URL", logger),
52-
).resolves.toStrictEqual({ url: coderUrl })
57+
it("should error on non-zero exit", async () => {
58+
await expect(getHeaders("localhost", "exit 10", logger)).rejects.toMatch(/exited unexpectedly with code 10/)
59+
})
5360
})
5461

55-
it("should error on non-zero exit", async () => {
56-
await expect(getHeaders("localhost", "exit 10", logger)).rejects.toMatch(/exited unexpectedly with code 10/)
62+
describe("getHeaderCommand", () => {
63+
beforeEach(() => {
64+
vi.stubEnv("CODER_HEADER_COMMAND", "")
65+
})
66+
67+
afterEach(() => {
68+
vi.unstubAllEnvs()
69+
})
70+
71+
it("should return undefined if coder.headerCommand is not set in config", () => {
72+
const config = {
73+
get: () => undefined,
74+
} as unknown as WorkspaceConfiguration
75+
76+
expect(getHeaderCommand(config)).toBeUndefined()
77+
})
78+
79+
it("should return coder.headerCommand if set in config", () => {
80+
vi.stubEnv("CODER_HEADER_COMMAND", "printf 'x=y'")
81+
82+
const config = {
83+
get: () => "printf 'foo=bar'",
84+
} as unknown as WorkspaceConfiguration
85+
86+
expect(getHeaderCommand(config)).toBe("printf 'foo=bar'")
87+
})
88+
89+
it("should return CODER_HEADER_COMMAND if coder.headerCommand is not set in config and CODER_HEADER_COMMAND is set in environment", () => {
90+
vi.stubEnv("CODER_HEADER_COMMAND", "printf 'x=y'")
91+
92+
const config = {
93+
get: () => undefined,
94+
} as unknown as WorkspaceConfiguration
95+
96+
expect(getHeaderCommand(config)).toBe("printf 'x=y'")
97+
98+
delete process.env.CODER_HEADER_COMMAND
99+
})
57100
})

src/headers.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as cp from "child_process"
22
import * as util from "util"
33

4+
import { WorkspaceConfiguration } from "vscode"
5+
46
export interface Logger {
57
writeToCoderOutputChannel(message: string): void
68
}
@@ -15,6 +17,14 @@ function isExecException(err: unknown): err is ExecException {
1517
return typeof (err as ExecException).code !== "undefined"
1618
}
1719

20+
export function getHeaderCommand(config: WorkspaceConfiguration): string | undefined {
21+
const cmd = config.get("coder.headerCommand") || process.env.CODER_HEADER_COMMAND
22+
if (!cmd || typeof cmd !== "string") {
23+
return undefined
24+
}
25+
return cmd
26+
}
27+
1828
// TODO: getHeaders might make more sense to directly implement on Storage
1929
// but it is difficult to test Storage right now since we use vitest instead of
2030
// the standard extension testing framework which would give us access to vscode

src/remote.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import prettyBytes from "pretty-bytes"
2020
import * as semver from "semver"
2121
import * as vscode from "vscode"
2222
import * as ws from "ws"
23+
import { getHeaderCommand } from "./headers"
2324
import { SSHConfig, SSHValues, defaultSSHConfigResponse, mergeSSHConfigValues } from "./sshConfig"
2425
import { computeSSHProperties, sshSupportsSetEnv } from "./sshSupport"
2526
import { Storage } from "./storage"
@@ -537,8 +538,7 @@ export class Remote {
537538

538539
// Add headers from the header command.
539540
let headerArg = ""
540-
const headerCommand =
541-
vscode.workspace.getConfiguration().get("coder.headerCommand") || process.env.CODER_HEADER_COMMAND
541+
const headerCommand = getHeaderCommand(vscode.workspace.getConfiguration())
542542
if (typeof headerCommand === "string" && headerCommand.trim().length > 0) {
543543
headerArg = ` --header-command ${escape(headerCommand)}`
544544
}

src/storage.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import os from "os"
1111
import path from "path"
1212
import prettyBytes from "pretty-bytes"
1313
import * as vscode from "vscode"
14-
import { getHeaders } from "./headers"
14+
import { getHeaderCommand, getHeaders } from "./headers"
1515

1616
export class Storage {
1717
public workspace?: Workspace
@@ -397,11 +397,7 @@ export class Storage {
397397
}
398398

399399
public async getHeaders(url = this.getURL()): Promise<Record<string, string>> {
400-
return getHeaders(
401-
url,
402-
vscode.workspace.getConfiguration().get("coder.headerCommand") || process.env.CODER_HEADER_COMMAND,
403-
this,
404-
)
400+
return getHeaders(url, getHeaderCommand(vscode.workspace.getConfiguration()), this)
405401
}
406402
}
407403

0 commit comments

Comments
 (0)