code-server/test/cli.test.ts

211 lines
6.2 KiB
TypeScript
Raw Normal View History

import { logger, Level } from "@coder/logger"
2020-02-07 08:26:07 +08:00
import * as assert from "assert"
import * as path from "path"
import { parse } from "../src/node/cli"
import { paths } from "../src/node/util"
2020-02-07 08:26:07 +08:00
describe("cli", () => {
beforeEach(() => {
delete process.env.LOG_LEVEL
})
// The parser will always fill these out.
const defaults = {
_: [],
"extensions-dir": path.join(paths.data, "extensions"),
"user-data-dir": paths.data,
}
it("should set defaults", async () => {
assert.deepEqual(await await parse([]), defaults)
2020-02-07 08:26:07 +08:00
})
it("should parse all available options", async () => {
2020-02-07 08:26:07 +08:00
assert.deepEqual(
await await parse([
"--bind-addr=192.169.0.1:8080",
2020-02-07 08:26:07 +08:00
"--auth",
"none",
"--extensions-dir",
"foo",
"--builtin-extensions-dir",
"foobar",
"--extra-extensions-dir",
"nozzle",
"1",
"--extra-builtin-extensions-dir",
"bazzle",
"--verbose",
"2",
"--log",
"error",
"--help",
"--open",
"--socket=mumble",
2020-02-07 08:26:07 +08:00
"3",
"--user-data-dir",
"bar",
"--cert=baz",
2020-02-07 08:26:07 +08:00
"--cert-key",
"qux",
"--version",
"--json",
"--port=8081",
2020-02-07 08:26:07 +08:00
"--host",
"0.0.0.0",
"4",
"--",
"-5",
"--6",
]),
{
_: ["1", "2", "3", "4", "-5", "--6"],
auth: "none",
"builtin-extensions-dir": path.resolve("foobar"),
"cert-key": path.resolve("qux"),
cert: {
value: path.resolve("baz"),
},
"extensions-dir": path.resolve("foo"),
"extra-builtin-extensions-dir": [path.resolve("bazzle")],
"extra-extensions-dir": [path.resolve("nozzle")],
help: true,
host: "0.0.0.0",
json: true,
log: "trace",
open: true,
port: 8081,
socket: path.resolve("mumble"),
"user-data-dir": path.resolve("bar"),
verbose: true,
version: true,
"bind-addr": "192.169.0.1:8080",
2020-02-15 08:46:00 +08:00
},
2020-02-07 08:26:07 +08:00
)
})
it("should work with short options", async () => {
assert.deepEqual(await parse(["-vvv", "-v"]), {
...defaults,
2020-02-07 08:26:07 +08:00
log: "trace",
verbose: true,
version: true,
})
assert.equal(process.env.LOG_LEVEL, "trace")
assert.equal(logger.level, Level.Trace)
})
it("should use log level env var", async () => {
process.env.LOG_LEVEL = "debug"
assert.deepEqual(await parse([]), {
...defaults,
log: "debug",
})
assert.equal(process.env.LOG_LEVEL, "debug")
assert.equal(logger.level, Level.Debug)
process.env.LOG_LEVEL = "trace"
assert.deepEqual(await parse([]), {
...defaults,
log: "trace",
verbose: true,
})
assert.equal(process.env.LOG_LEVEL, "trace")
assert.equal(logger.level, Level.Trace)
})
it("should prefer --log to env var and --verbose to --log", async () => {
process.env.LOG_LEVEL = "debug"
assert.deepEqual(await parse(["--log", "info"]), {
...defaults,
log: "info",
})
assert.equal(process.env.LOG_LEVEL, "info")
assert.equal(logger.level, Level.Info)
process.env.LOG_LEVEL = "trace"
assert.deepEqual(await parse(["--log", "info"]), {
...defaults,
log: "info",
})
assert.equal(process.env.LOG_LEVEL, "info")
assert.equal(logger.level, Level.Info)
process.env.LOG_LEVEL = "warn"
assert.deepEqual(await parse(["--log", "info", "--verbose"]), {
...defaults,
log: "trace",
verbose: true,
})
assert.equal(process.env.LOG_LEVEL, "trace")
assert.equal(logger.level, Level.Trace)
})
it("should ignore invalid log level env var", async () => {
process.env.LOG_LEVEL = "bogus"
assert.deepEqual(await parse([]), defaults)
2020-02-07 08:26:07 +08:00
})
it("should error if value isn't provided", async () => {
await assert.rejects(async () => await parse(["--auth"]), /--auth requires a value/)
await assert.rejects(async () => await parse(["--auth=", "--log=debug"]), /--auth requires a value/)
await assert.rejects(async () => await parse(["--auth", "--log"]), /--auth requires a value/)
await assert.rejects(async () => await parse(["--auth", "--invalid"]), /--auth requires a value/)
await assert.rejects(async () => await parse(["--bind-addr"]), /--bind-addr requires a value/)
2020-02-07 08:26:07 +08:00
})
it("should error if value is invalid", async () => {
await assert.rejects(async () => await parse(["--port", "foo"]), /--port must be a number/)
await assert.rejects(async () => await parse(["--auth", "invalid"]), /--auth valid values: \[password, none\]/)
await assert.rejects(
async () => await parse(["--log", "invalid"]),
/--log valid values: \[trace, debug, info, warn, error\]/,
)
2020-02-07 08:26:07 +08:00
})
it("should error if the option doesn't exist", async () => {
await assert.rejects(async () => await parse(["--foo"]), /Unknown option --foo/)
2020-02-07 08:26:07 +08:00
})
it("should not error if the value is optional", async () => {
assert.deepEqual(await parse(["--cert"]), {
...defaults,
2020-02-07 08:26:07 +08:00
cert: {
value: undefined,
},
})
})
it("should not allow option-like values", async () => {
await assert.rejects(async () => await parse(["--socket", "--socket-path-value"]), /--socket requires a value/)
2020-02-07 08:26:07 +08:00
// If you actually had a path like this you would do this instead:
assert.deepEqual(await parse(["--socket", "./--socket-path-value"]), {
...defaults,
2020-02-07 08:26:07 +08:00
socket: path.resolve("--socket-path-value"),
})
await assert.rejects(
async () => await parse(["--cert", "--socket-path-value"]),
/Unknown option --socket-path-value/,
)
2020-02-07 08:26:07 +08:00
})
it("should allow positional arguments before options", async () => {
assert.deepEqual(await parse(["foo", "test", "--auth", "none"]), {
...defaults,
_: ["foo", "test"],
auth: "none",
})
})
it("should support repeatable flags", async () => {
assert.deepEqual(await parse(["--proxy-domain", "*.coder.com"]), {
...defaults,
"proxy-domain": ["*.coder.com"],
})
assert.deepEqual(await parse(["--proxy-domain", "*.coder.com", "--proxy-domain", "test.com"]), {
...defaults,
"proxy-domain": ["*.coder.com", "test.com"],
})
})
2020-02-07 08:26:07 +08:00
})