Skip to content

Commit

Permalink
feat(testing): add test for optionDescriptions (#4970)
Browse files Browse the repository at this point in the history
* feat(testing): add test for optionDescriptions

* refactor(cli): optional arg in optionDescriptions

* feat: add more tests for optionDescriptions
  • Loading branch information
jsjoeio authored Mar 11, 2022
1 parent 77296c7 commit 91cabbc
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,11 @@ type OptionType<T> = T extends boolean
? "string[]"
: "unknown"

type Options<T> = {
export type Options<T> = {
[P in keyof T]: Option<OptionType<T[P]>>
}

const options: Options<Required<UserProvidedArgs>> = {
export const options: Options<Required<UserProvidedArgs>> = {
auth: { type: AuthType, description: "The type of authentication to use." },
password: {
type: "string",
Expand Down Expand Up @@ -235,8 +235,8 @@ const options: Options<Required<UserProvidedArgs>> = {
},
}

export const optionDescriptions = (): string[] => {
const entries = Object.entries(options).filter(([, v]) => !!v.description)
export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedArgs>>> = options): string[] => {
const entries = Object.entries(opts).filter(([, v]) => !!v.description)
const widths = entries.reduce(
(prev, [k, v]) => ({
long: k.length > prev.long ? k.length : prev.long,
Expand Down
99 changes: 99 additions & 0 deletions test/unit/node/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import {
shouldOpenInExistingInstance,
splitOnFirstEquals,
toVsCodeArgs,
optionDescriptions,
options,
Options,
AuthType,
OptionalString,
} from "../../../src/node/cli"
import { shouldSpawnCliProcess } from "../../../src/node/main"
import { generatePassword, paths } from "../../../src/node/util"
Expand Down Expand Up @@ -753,3 +758,97 @@ describe("toVsCodeArgs", () => {
})
})
})

describe("optionDescriptions", () => {
it("should return the descriptions of all the available options", () => {
const expectedOptionDescriptions = Object.entries(options)
.flat()
.filter((item: any) => {
if (item.description) {
return item.description
}
})
.map((item: any) => item.description)
const actualOptionDescriptions = optionDescriptions()
// We need both the expected and the actual
// Both of these are string[]
// We then loop through the expectedOptionDescriptions
// and check that this expectedDescription exists in the
// actualOptionDescriptions

// To do that we need to loop through actualOptionDescriptions
// and make sure we have a substring match
expectedOptionDescriptions.forEach((expectedDescription) => {
const exists = actualOptionDescriptions.find((desc) => {
if (
desc.replace(/\n/g, " ").replace(/ /g, "").includes(expectedDescription.replace(/\n/g, " ").replace(/ /g, ""))
) {
return true
}
return false
})
expect(exists).toBeTruthy()
})
})
it("should visually align multiple options", () => {
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
"cert-key": { type: "string", path: true, description: "Path to certificate key when using non-generated cert." },
"cert-host": {
type: "string",
description: "Hostname to use when generating a self signed certificate.",
},
"disable-update-check": {
type: "boolean",
description:
"Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" +
"then notifies you once every week that a new release is available.",
},
}
expect(optionDescriptions(opts)).toStrictEqual([
" --cert-key Path to certificate key when using non-generated cert.",
" --cert-host Hostname to use when generating a self signed certificate.",
` --disable-update-check Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and
then notifies you once every week that a new release is available.`,
])
})
it("should add all valid options for enumerated types", () => {
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
auth: { type: AuthType, description: "The type of authentication to use." },
}
expect(optionDescriptions(opts)).toStrictEqual([" --auth The type of authentication to use. [password, none]"])
})

it("should show if an option is deprecated", () => {
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
link: {
type: OptionalString,
description: `
Securely bind code-server via our cloud service with the passed name. You'll get a URL like
https://hostname-username.coder.co at which you can easily access your code-server instance.
Authorization is done via GitHub.
`,
deprecated: true,
},
}
expect(optionDescriptions(opts)).toStrictEqual([
` --link (deprecated) Securely bind code-server via our cloud service with the passed name. You'll get a URL like
https://hostname-username.coder.co at which you can easily access your code-server instance.
Authorization is done via GitHub.`,
])
})

it("should show newlines in description", () => {
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
"install-extension": {
type: "string[]",
description:
"Install or update a VS Code extension by id or vsix. The identifier of an extension is `${publisher}.${name}`.\n" +
"To install a specific version provide `@${version}`. For example: '[email protected]'.",
},
}
expect(optionDescriptions(opts)).toStrictEqual([
` --install-extension Install or update a VS Code extension by id or vsix. The identifier of an extension is \`\${publisher}.\${name}\`.
To install a specific version provide \`@\${version}\`. For example: '[email protected]'.`,
])
})
})

0 comments on commit 91cabbc

Please sign in to comment.