-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathlogin.test.ts
146 lines (108 loc) · 5.26 KB
/
login.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import prompts from 'prompts';
import { describe, beforeAll, afterEach, it, expect } from 'vitest';
import Command from '../../src/commands/login.js';
import configStore from '../../src/lib/configstore.js';
import { getAPIv1Mock } from '../helpers/get-api-mock.js';
import { runCommand, type OclifOutput } from '../helpers/oclif.js';
const apiKey = 'abcdefg';
const password = 'password';
const project = 'subdomain';
const token = '123456';
describe('rdme login', () => {
let run: (args?: string[]) => OclifOutput;
beforeAll(() => {
run = runCommand(Command);
});
afterEach(() => configStore.clear());
it('should error if no project provided', () => {
prompts.inject([email, password]);
return expect(run()).resolves.toMatchSnapshot();
});
it('should error if email is invalid', () => {
prompts.inject(['this-is-not-an-email', password, project]);
return expect(run()).resolves.toMatchSnapshot();
});
it('should post to /login on the API', async () => {
prompts.inject([email, password, project]);
const mock = getAPIv1Mock().post('/api/v1/login', { email, password, project }).reply(200, { apiKey });
await expect(run()).resolves.toMatchSnapshot();
mock.done();
expect(configStore.get('apiKey')).toBe(apiKey);
expect(configStore.get('email')).toBe(email);
expect(configStore.get('project')).toBe(project);
});
it('should post to /login on the API if passing in project via opt', async () => {
prompts.inject([email, password]);
const mock = getAPIv1Mock().post('/api/v1/login', { email, password, project }).reply(200, { apiKey });
await expect(run(['--project', project])).resolves.toMatchSnapshot();
mock.done();
expect(configStore.get('apiKey')).toBe(apiKey);
expect(configStore.get('email')).toBe(email);
expect(configStore.get('project')).toBe(project);
});
it('should bypass prompts and post to /login on the API if passing in every opt', async () => {
const mock = getAPIv1Mock().post('/api/v1/login', { email, password, project, token }).reply(200, { apiKey });
await expect(
run(['--email', email, '--password', password, '--project', project, '--otp', token]),
).resolves.toMatchSnapshot();
mock.done();
expect(configStore.get('apiKey')).toBe(apiKey);
expect(configStore.get('email')).toBe(email);
expect(configStore.get('project')).toBe(project);
});
it('should bypass prompts and post to /login on the API if passing in every opt (no 2FA)', async () => {
const mock = getAPIv1Mock().post('/api/v1/login', { email, password, project }).reply(200, { apiKey });
await expect(run(['--email', email, '--password', password, '--project', project])).resolves.toMatchSnapshot();
mock.done();
expect(configStore.get('apiKey')).toBe(apiKey);
expect(configStore.get('email')).toBe(email);
expect(configStore.get('project')).toBe(project);
});
it('should error if invalid credentials are given', async () => {
prompts.inject([email, password, project]);
const errorResponse = {
error: 'LOGIN_INVALID',
message: 'Either your email address or password is incorrect',
suggestion: 'You can reset your password at https://dash.readme.com/forgot',
};
const mock = getAPIv1Mock().post('/api/v1/login', { email, password, project }).reply(401, errorResponse);
await expect(run()).resolves.toMatchSnapshot();
mock.done();
});
it('should make additional prompt for token if login requires 2FA', async () => {
prompts.inject([email, password, project, token]);
const errorResponse = {
error: 'LOGIN_TWOFACTOR',
message: 'You must provide a two-factor code',
suggestion: 'You can do it via the API using `token`, or via the CLI using `rdme login --2fa`',
};
const mock = getAPIv1Mock()
.post('/api/v1/login', { email, password, project })
.reply(401, errorResponse)
.post('/api/v1/login', { email, password, project, token })
.reply(200, { apiKey });
await expect(run()).resolves.toMatchSnapshot();
mock.done();
expect(configStore.get('apiKey')).toBe(apiKey);
expect(configStore.get('email')).toBe(email);
expect(configStore.get('project')).toBe(project);
});
it('should error if trying to access a project that is not yours', async () => {
const projectThatIsNotYours = 'unauthorized-project';
prompts.inject([email, password, projectThatIsNotYours]);
const errorResponse = {
error: 'PROJECT_NOTFOUND',
message: `The project (${projectThatIsNotYours}) can't be found.`,
suggestion: `The project is referred to as your \`subdomain\` in the dashboard when you're looking for it. If you're sure it exists, maybe you don't have access to it? You can check if it exists here: https://${projectThatIsNotYours}.readme.io.`,
};
const mock = getAPIv1Mock()
.post('/api/v1/login', { email, password, project: projectThatIsNotYours })
.reply(404, errorResponse);
await expect(run()).resolves.toMatchSnapshot();
mock.done();
});
});