mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-10 04:22:12 +00:00
This PR is a follow-up to #8039, which provides an intuitive syntax for writing unit tests for interactive CLI commands. The heart of this is the new `await expect(stream).toOutput(test)` custom Jest matcher, which is intended for use with the mock Client `stdout` and `stderr` stream properties. The `test` is a string that will wait for the stream to output via "data" events until a match is found, or it will timeout (after 3 seconds by default). The timeout error has nice Jest-style formatting so that you can easily identify what was output: <img width="553" alt="Screen Shot 2022-06-29 at 10 33 06 PM" src="https://user-images.githubusercontent.com/71256/176600324-cb1ebecb-e891-42d9-bdc9-4864d3594a8c.png"> Below is an example of a unit test that was added for an interactive `vc login` session: ```typescript it('should allow login via email', async () => { const user = useUser(); const exitCodePromise = login(client); // Wait for login interactive prompt await expect(client.stderr).toOutput(`> Log in to Vercel`); // Move down to "Email" option client.stdin.write('\x1B[B'); // Down arrow client.stdin.write('\x1B[B'); // Down arrow client.stdin.write('\x1B[B'); // Down arrow client.stdin.write('\r'); // Return key // Wait for email input prompt await expect(client.stderr).toOutput('> Enter your email address:'); // Write user email address into prompt client.stdin.write(`${user.email}\n`); // Wait for login success message await expect(client.stderr).toOutput( `Success! Email authentication complete for ${user.email}` ); // Assert that the `login()` command returned 0 exit code await expect(exitCodePromise).resolves.toEqual(0); }); ``` **Note:** as a consequence of this PR, prompts are now written to stderr instead of stdout, so this change _may_ be considered a breaking change, in which case we should tag it for major release.
29 lines
1007 B
TypeScript
29 lines
1007 B
TypeScript
import { client } from '../../mocks/client';
|
|
import { useUser } from '../../mocks/user';
|
|
import { useDeployment } from '../../mocks/deployment';
|
|
import inspect from '../../../src/commands/inspect';
|
|
|
|
describe('inspect', () => {
|
|
it('should print out deployment information', async () => {
|
|
const user = useUser();
|
|
const deployment = useDeployment({ creator: user });
|
|
client.setArgv('inspect', deployment.url);
|
|
const exitCode = await inspect(client);
|
|
expect(exitCode).toEqual(0);
|
|
await expect(client.stderr).toOutput(
|
|
`> Fetched deployment "${deployment.url}" in ${user.username}`
|
|
);
|
|
});
|
|
|
|
it('should print error when deployment not found', async () => {
|
|
const user = useUser();
|
|
useDeployment({ creator: user });
|
|
client.setArgv('inspect', 'bad.com');
|
|
const exitCode = await inspect(client);
|
|
expect(exitCode).toEqual(1);
|
|
await expect(client.stderr).toOutput(
|
|
`Error! Failed to find deployment "bad.com" in ${user.username}\n`
|
|
);
|
|
});
|
|
});
|