Skip to content

Commit

Permalink
feat: prompt for login any time a user omits API key (#636)
Browse files Browse the repository at this point in the history
* feat: prompt for login any time a user omits API key

* chore: lint

* test: stricter login tests

* test: add nock cleanup to docs:edit so it's consistent

* test: update all affected tests

Now we split our `--key` tests into two tests: one for CI, and one for non-CI.

* chore: remove unnecessary JSDoc

TS handles this now

* refactor: add boolean to info statement to hide prefix

... and refactor console.info statements to use that instead

* refactor: remove redundant else

Co-Authored-By: Jon Ursenbach <[email protected]>

Co-authored-by: Jon Ursenbach <[email protected]>
  • Loading branch information
kanadgupta and erunion authored Oct 13, 2022
1 parent 31b5bae commit 542307b
Show file tree
Hide file tree
Showing 40 changed files with 303 additions and 156 deletions.
14 changes: 12 additions & 2 deletions __tests__/cmds/categories/create.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import nock from 'nock';
import prompts from 'prompts';

import CategoriesCreateCommand from '../../../src/cmds/categories/create';
import getAPIMock, { getAPIMockWithVersionHeader } from '../../helpers/get-api-mock';
Expand All @@ -13,10 +14,19 @@ describe('rdme categories:create', () => {

afterEach(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(categoriesCreate.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(categoriesCreate.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(categoriesCreate.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should error if no title provided', () => {
Expand Down
14 changes: 12 additions & 2 deletions __tests__/cmds/categories/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import nock from 'nock';
import prompts from 'prompts';

import CategoriesCommand from '../../../src/cmds/categories';
import getAPIMock, { getAPIMockWithVersionHeader } from '../../helpers/get-api-mock';
Expand All @@ -13,10 +14,19 @@ describe('rdme categories', () => {

afterEach(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(categories.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(categories.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(categories.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should return all categories for a single page', async () => {
Expand Down
14 changes: 12 additions & 2 deletions __tests__/cmds/changelogs/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path';
import chalk from 'chalk';
import frontMatter from 'gray-matter';
import nock from 'nock';
import prompts from 'prompts';

import ChangelogsCommand from '../../../src/cmds/changelogs';
import APIError from '../../../src/lib/apiError';
Expand All @@ -21,10 +22,19 @@ describe('rdme changelogs', () => {

afterAll(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(changelogs.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(changelogs.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(changelogs.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should error if no folder provided', () => {
Expand Down
14 changes: 12 additions & 2 deletions __tests__/cmds/changelogs/single.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path';
import chalk from 'chalk';
import frontMatter from 'gray-matter';
import nock from 'nock';
import prompts from 'prompts';

import SingleChangelogCommand from '../../../src/cmds/changelogs/single';
import APIError from '../../../src/lib/apiError';
Expand All @@ -21,10 +22,19 @@ describe('rdme changelogs:single', () => {

afterAll(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(changelogsSingle.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(changelogsSingle.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(changelogsSingle.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should error if no file path provided', () => {
Expand Down
14 changes: 12 additions & 2 deletions __tests__/cmds/custompages/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path';
import chalk from 'chalk';
import frontMatter from 'gray-matter';
import nock from 'nock';
import prompts from 'prompts';

import CustomPagesCommand from '../../../src/cmds/custompages';
import APIError from '../../../src/lib/apiError';
Expand All @@ -21,10 +22,19 @@ describe('rdme custompages', () => {

afterAll(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(custompages.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(custompages.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(custompages.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should error if no folder provided', () => {
Expand Down
14 changes: 12 additions & 2 deletions __tests__/cmds/custompages/single.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path';
import chalk from 'chalk';
import frontMatter from 'gray-matter';
import nock from 'nock';
import prompts from 'prompts';

import SingleCustomPageCommand from '../../../src/cmds/custompages/single';
import APIError from '../../../src/lib/apiError';
Expand All @@ -21,10 +22,19 @@ describe('rdme custompages:single', () => {

afterAll(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(customPagesSingle.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(customPagesSingle.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(customPagesSingle.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should error if no file path provided', () => {
Expand Down
22 changes: 18 additions & 4 deletions __tests__/cmds/docs/edit.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import fs from 'fs';

import nock from 'nock';
import prompts from 'prompts';

import DocsEditCommand from '../../../src/cmds/docs/edit';
import APIError from '../../../src/lib/apiError';
import getAPIMock, { getAPIMockWithVersionHeader } from '../../helpers/get-api-mock';
Expand All @@ -11,10 +14,21 @@ const version = '1.0.0';
const category = 'CATEGORY_ID';

describe('rdme docs:edit', () => {
it('should error if no api key provided', () => {
return expect(docsEdit.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
beforeAll(() => nock.disableNetConnect());

afterAll(() => nock.cleanAll());

it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(docsEdit.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(docsEdit.run({})).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
delete process.env.TEST_CI;
});

it('should error if no slug provided', () => {
Expand Down
13 changes: 11 additions & 2 deletions __tests__/cmds/docs/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,17 @@ describe('rdme docs', () => {

afterAll(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(docs.run({})).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(docs.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(docs.run({})).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
delete process.env.TEST_CI;
});

it('should error if no folder provided', () => {
Expand Down
14 changes: 12 additions & 2 deletions __tests__/cmds/docs/single.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path';
import chalk from 'chalk';
import frontMatter from 'gray-matter';
import nock from 'nock';
import prompts from 'prompts';

import DocsSingleCommand from '../../../src/cmds/docs/single';
import APIError from '../../../src/lib/apiError';
Expand All @@ -24,10 +25,19 @@ describe('rdme docs:single', () => {

afterAll(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(docsSingle.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(docsSingle.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(docsSingle.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should error if no file path provided', () => {
Expand Down
4 changes: 2 additions & 2 deletions __tests__/cmds/login.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('rdme login', () => {
it('should post to /login on the API', async () => {
prompts.inject([email, password, project]);

const mock = getAPIMock().post('/api/v1/login').reply(200, { apiKey });
const mock = getAPIMock().post('/api/v1/login', { email, password, project }).reply(200, { apiKey });

await expect(cmd.run({})).resolves.toBe('Successfully logged in as [email protected] to the subdomain project.');

Expand All @@ -50,7 +50,7 @@ describe('rdme login', () => {
it('should post to /login on the API if passing in project via opt', async () => {
prompts.inject([email, password]);

const mock = getAPIMock().post('/api/v1/login').reply(200, { apiKey });
const mock = getAPIMock().post('/api/v1/login', { email, password, project }).reply(200, { apiKey });

await expect(cmd.run({ project })).resolves.toBe(
'Successfully logged in as [email protected] to the subdomain project.'
Expand Down
15 changes: 11 additions & 4 deletions __tests__/cmds/openapi/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -839,10 +839,17 @@ describe('rdme openapi', () => {
});

describe('error handling', () => {
it('should error if no api key provided', () => {
return expect(
openapi.run({ spec: require.resolve('@readme/oas-examples/3.0/json/petstore.json') })
).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
it('should prompt for login if no API key provided', () => {
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
return expect(openapi.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(openapi.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should error if `--create` and `--update` flags are passed simultaneously', () => {
Expand Down
13 changes: 11 additions & 2 deletions __tests__/cmds/versions/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,19 @@ describe('rdme versions:create', () => {

afterEach(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(createVersion.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(createVersion.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(createVersion.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should error if no version provided', () => {
Expand Down
14 changes: 12 additions & 2 deletions __tests__/cmds/versions/delete.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import nock from 'nock';
import prompts from 'prompts';

import DeleteVersionCommand from '../../../src/cmds/versions/delete';
import APIError from '../../../src/lib/apiError';
Expand All @@ -14,10 +15,19 @@ describe('rdme versions:delete', () => {

afterEach(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(deleteVersion.run({})).rejects.toStrictEqual(
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(deleteVersion.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(deleteVersion.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
delete process.env.TEST_CI;
});

it('should delete a specific version', async () => {
Expand Down
16 changes: 12 additions & 4 deletions __tests__/cmds/versions/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Version } from '../../../src/cmds/versions';

import nock from 'nock';
import prompts from 'prompts';

import VersionsCommand from '../../../src/cmds/versions';
import getAPIMock from '../../helpers/get-api-mock';
Expand Down Expand Up @@ -36,10 +37,17 @@ describe('rdme versions', () => {

afterEach(() => nock.cleanAll());

it('should error if no api key provided', () => {
return expect(versions.run({})).rejects.toStrictEqual(
new Error('No project API key provided. Please use `--key`.')
);
it('should prompt for login if no API key provided', async () => {
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
prompts.inject(['this-is-not-an-email', 'password', 'subdomain']);
await expect(versions.run({})).rejects.toStrictEqual(new Error('You must provide a valid email address.'));
consoleInfoSpy.mockRestore();
});

it('should error in CI if no API key provided', async () => {
process.env.TEST_CI = 'true';
await expect(versions.run({})).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
delete process.env.TEST_CI;
});

it('should make a request to get a list of existing versions', async () => {
Expand Down
Loading

0 comments on commit 542307b

Please sign in to comment.