-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat: Add unit tests for prompt.ts #9054
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,6 +50,167 @@ | |
| }); | ||
| expect(result).to.be.true; | ||
| }); | ||
|
|
||
| it("handles non-interactive with default", async () => { | ||
| const result = await prompt.confirm({ | ||
| message: "Continue?", | ||
| nonInteractive: true, | ||
| default: false, | ||
| }); | ||
| expect(result).to.be.false; | ||
| }); | ||
|
|
||
| it("throws in non-interactive without default", async () => { | ||
| await expect( | ||
| prompt.confirm({ | ||
| message: "Continue?", | ||
| nonInteractive: true, | ||
| }), | ||
| ).to.be.rejectedWith( | ||
| FirebaseError, | ||
| 'Question "Continue?" does not have a default and cannot be answered in non-interactive mode', | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("input", () => { | ||
| it("handles non-interactive with default", async () => { | ||
| const result = await prompt.input({ | ||
| message: "Name?", | ||
| nonInteractive: true, | ||
| default: "Inigo Montoya", | ||
| }); | ||
| expect(result).to.equal("Inigo Montoya"); | ||
| }); | ||
|
|
||
| it("throws in non-interactive without default", async () => { | ||
| await expect( | ||
| prompt.input({ | ||
| message: "Name?", | ||
| nonInteractive: true, | ||
| }), | ||
| ).to.be.rejectedWith( | ||
| FirebaseError, | ||
| 'Question "Name?" does not have a default and cannot be answered in non-interactive mode', | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("checkbox", () => { | ||
| it("handles non-interactive with default", async () => { | ||
| const result = await prompt.checkbox({ | ||
| message: "Tools?", | ||
| nonInteractive: true, | ||
| choices: ["hammer", "wrench", "saw"], | ||
| default: ["hammer", "wrench"], | ||
| }); | ||
| expect(result).to.deep.equal(["hammer", "wrench"]); | ||
| }); | ||
|
|
||
| it("throws in non-interactive without default", async () => { | ||
| await expect( | ||
| prompt.checkbox({ | ||
| message: "Tools?", | ||
| nonInteractive: true, | ||
| choices: ["hammer", "wrench", "saw"], | ||
| }), | ||
| ).to.be.rejectedWith( | ||
| FirebaseError, | ||
| 'Question "Tools?" does not have a default and cannot be answered in non-interactive mode', | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("select", () => { | ||
| it("handles non-interactive with default", async () => { | ||
| const result = await prompt.select({ | ||
| message: "Tool?", | ||
| nonInteractive: true, | ||
| choices: ["hammer", "wrench", "saw"], | ||
| default: "wrench", | ||
| }); | ||
| expect(result).to.equal("wrench"); | ||
| }); | ||
|
|
||
| it("throws in non-interactive without default", async () => { | ||
| await expect( | ||
| prompt.select({ | ||
| message: "Tool?", | ||
| nonInteractive: true, | ||
| choices: ["hammer", "wrench", "saw"], | ||
| }), | ||
| ).to.be.rejectedWith( | ||
| FirebaseError, | ||
| 'Question "Tool?" does not have a default and cannot be answered in non-interactive mode', | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("number", () => { | ||
| it("handles non-interactive with default", async () => { | ||
| const result = await prompt.number({ | ||
| message: "Count?", | ||
| nonInteractive: true, | ||
| default: 42, | ||
| }); | ||
| expect(result).to.equal(42); | ||
| }); | ||
|
|
||
| it("throws in non-interactive without default", async () => { | ||
| await expect( | ||
| prompt.number({ | ||
| message: "Count?", | ||
| nonInteractive: true, | ||
| }), | ||
| ).to.be.rejectedWith( | ||
| FirebaseError, | ||
| 'Question "Count?" does not have a default and cannot be answered in non-interactive mode', | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("password", () => { | ||
| it("throws in non-interactive", async () => { | ||
| await expect( | ||
| prompt.password({ | ||
| message: "Password?", | ||
| nonInteractive: true, | ||
| }), | ||
| ).to.be.rejectedWith( | ||
| FirebaseError, | ||
| 'Question "Password?" does not have a default and cannot be answered in non-interactive mode', | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("search", () => { | ||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
| const source = (term: string | undefined) => { | ||
| return ["a", "b", "c"]; | ||
| }; | ||
|
|
||
| it("handles non-interactive with default", async () => { | ||
| const result = await prompt.search({ | ||
| message: "Letter?", | ||
| nonInteractive: true, | ||
| source, | ||
| default: "b", | ||
| }); | ||
| expect(result).to.equal("b"); | ||
| }); | ||
|
|
||
| it("throws in non-interactive without default", async () => { | ||
| await expect( | ||
| prompt.search({ | ||
| message: "Letter?", | ||
| nonInteractive: true, | ||
| source, | ||
| }), | ||
| ).to.be.rejectedWith( | ||
| FirebaseError, | ||
| 'Question "Letter?" does not have a default and cannot be answered in non-interactive mode', | ||
| ); | ||
| }); | ||
| }); | ||
|
Comment on lines
+54
to
214
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tests for different prompt types in non-interactive mode are very similar and contain a lot of duplicated code. This reduces readability and maintainability. To improve this, consider refactoring to a data-driven approach. You can define an array of test cases and iterate over it to generate the tests dynamically. This will make the test suite more concise and easier to extend. Here is an example of how you could structure this: const testCases = [
{
name: "confirm",
promptFn: prompt.confirm,
message: "Continue?",
default: false,
extraOpts: {},
assertion: (result: boolean) => expect(result).to.be.false,
},
{
name: "input",
promptFn: prompt.input,
message: "Name?",
default: "Inigo Montoya",
extraOpts: {},
assertion: (result: string) => expect(result).to.equal("Inigo Montoya"),
},
{
name: "checkbox",
promptFn: prompt.checkbox,
message: "Tools?",
default: ["hammer", "wrench"],
extraOpts: { choices: ["hammer", "wrench", "saw"] },
assertion: (result: string[]) => expect(result).to.deep.equal(["hammer", "wrench"]),
},
// ... other test cases for select, number, search
];
testCases.forEach(({ name, promptFn, message, default: defaultValue, extraOpts, assertion }) => {
describe(name, () => {
it("handles non-interactive with default", async () => {
const result = await (promptFn as any)({
message,
nonInteractive: true,
default: defaultValue,
...extraOpts,
});
assertion(result);
});
it("throws in non-interactive without default", async () => {
await expect(
(promptFn as any)({
message,
nonInteractive: true,
...extraOpts,
}),
).to.be.rejectedWith(
FirebaseError,
`Question "${message}" does not have a default and cannot be answered in non-interactive mode`,
);
});
});
});
// The 'password' prompt is a special case and can be tested separately.
describe("password", () => {
it("throws in non-interactive", async () => {
await expect(
prompt.password({
message: "Password?",
nonInteractive: true,
}),
).to.be.rejectedWith(
FirebaseError,
'Question "Password?" does not have a default and cannot be answered in non-interactive mode',
);
});
}); |
||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid using
eslint-disable-next-line, you can prefix the unusedtermparameter with an underscore. This is a common convention to signal that a parameter is intentionally unused and satisfies the linter.