@anmiles/google-api-wrapper 18.0.2 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nycrc.json +27 -0
- package/CHANGELOG.md +32 -21
- package/README.md +1 -1
- package/cspell.json +22 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +5 -11
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +5 -6
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/auth.d.ts +2 -9
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +3 -23
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/credentials/generator.d.ts +4 -0
- package/dist/lib/credentials/generator.d.ts.map +1 -0
- package/dist/lib/credentials/generator.js +60 -0
- package/dist/lib/credentials/generator.js.map +1 -0
- package/dist/lib/credentials/index.d.ts +5 -0
- package/dist/lib/credentials/index.d.ts.map +1 -0
- package/dist/lib/credentials/index.js +41 -0
- package/dist/lib/credentials/index.js.map +1 -0
- package/dist/lib/credentials/validator.d.ts +6 -0
- package/dist/lib/credentials/validator.d.ts.map +1 -0
- package/dist/lib/credentials/validator.js +21 -0
- package/dist/lib/credentials/validator.js.map +1 -0
- package/dist/lib/login.d.ts +3 -0
- package/dist/lib/login.d.ts.map +1 -0
- package/dist/lib/login.js +19 -0
- package/dist/lib/login.js.map +1 -0
- package/dist/lib/profiles.d.ts +4 -12
- package/dist/lib/profiles.d.ts.map +1 -1
- package/dist/lib/profiles.js +8 -11
- package/dist/lib/profiles.js.map +1 -1
- package/dist/lib/renderer.d.ts +7 -23
- package/dist/lib/renderer.d.ts.map +1 -1
- package/dist/lib/renderer.js +26 -20
- package/dist/lib/renderer.js.map +1 -1
- package/dist/lib/scopes.d.ts +2 -0
- package/dist/lib/scopes.d.ts.map +1 -0
- package/dist/lib/scopes.js +22 -0
- package/dist/lib/scopes.js.map +1 -0
- package/dist/lib/secrets.d.ts +2 -28
- package/dist/lib/secrets.d.ts.map +1 -1
- package/dist/lib/secrets.js +11 -112
- package/dist/lib/secrets.js.map +1 -1
- package/dist/lib/utils/paths.d.ts +7 -0
- package/dist/lib/utils/paths.d.ts.map +1 -0
- package/dist/lib/{paths.js → utils/paths.js} +6 -8
- package/dist/lib/utils/paths.js.map +1 -0
- package/dist/templates/auth.html +1 -1
- package/dist/templates/index.html +17 -0
- package/dist/templates/page.html +1 -2
- package/dist/templates/script.html +0 -0
- package/{src/templates/css.html → dist/templates/style.html} +2 -2
- package/dist/types/options.d.ts +2 -3
- package/dist/types/options.d.ts.map +1 -1
- package/dist/types/secrets.d.ts +1 -2
- package/dist/types/secrets.d.ts.map +1 -1
- package/eslint.config.mts +43 -0
- package/jest.config.js +9 -9
- package/package.json +40 -30
- package/src/index.ts +3 -2
- package/src/lib/__tests__/__snapshots__/renderer.test.ts.snap +273 -0
- package/src/lib/__tests__/__snapshots__/scopes.test.ts.snap +6 -0
- package/src/lib/__tests__/__snapshots__/secrets.test.ts.snap +38 -0
- package/src/lib/__tests__/api.test.ts +72 -74
- package/src/lib/__tests__/auth.test.ts +38 -114
- package/src/lib/__tests__/login.test.ts +71 -0
- package/src/lib/__tests__/profiles.test.ts +50 -93
- package/src/lib/__tests__/renderer.test.ts +16 -88
- package/src/lib/__tests__/scopes.test.ts +41 -0
- package/src/lib/__tests__/secrets.test.ts +47 -541
- package/src/lib/api.ts +19 -21
- package/src/lib/auth.ts +5 -25
- package/src/lib/credentials/__tests__/generator.test.ts +249 -0
- package/src/lib/credentials/__tests__/index.test.ts +213 -0
- package/src/lib/credentials/__tests__/validator.test.ts +34 -0
- package/src/lib/credentials/generator.ts +70 -0
- package/src/lib/credentials/index.ts +49 -0
- package/src/lib/credentials/validator.ts +24 -0
- package/src/lib/login.ts +22 -0
- package/src/lib/profiles.ts +9 -12
- package/src/lib/renderer.ts +31 -23
- package/src/lib/scopes.ts +18 -0
- package/src/lib/secrets.ts +17 -139
- package/src/lib/utils/paths.ts +30 -0
- package/src/templates/auth.html +1 -1
- package/src/templates/index.html +17 -0
- package/src/templates/page.html +1 -2
- package/src/templates/script.html +0 -0
- package/{dist/templates/css.html → src/templates/style.html} +2 -2
- package/src/types/options.ts +5 -7
- package/src/types/secrets.ts +8 -10
- package/tsconfig.build.json +6 -0
- package/tsconfig.json +0 -5
- package/tsconfig.test.json +1 -1
- package/.eslintignore +0 -2
- package/.eslintrc.js +0 -30
- package/.vscode/settings.json +0 -9
- package/coverage.config.js +0 -8
- package/dist/lib/paths.d.ts +0 -16
- package/dist/lib/paths.d.ts.map +0 -1
- package/dist/lib/paths.js.map +0 -1
- package/src/lib/__tests__/paths.test.ts +0 -77
- package/src/lib/paths.ts +0 -32
|
@@ -1,18 +1,26 @@
|
|
|
1
|
+
import logger from '@anmiles/logger';
|
|
2
|
+
import sleep from '@anmiles/sleep';
|
|
1
3
|
import type GoogleApis from 'googleapis';
|
|
2
4
|
import type { calendar_v3 } from 'googleapis/build/src/apis/calendar';
|
|
3
5
|
import { calendar } from 'googleapis/build/src/apis/calendar';
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import auth from '../auth';
|
|
7
|
-
import secrets from '../secrets';
|
|
6
|
+
|
|
7
|
+
import { API, getAPI } from '../api';
|
|
8
8
|
import type { CommonResponse } from '../api';
|
|
9
|
-
import
|
|
9
|
+
import { getAuth } from '../auth';
|
|
10
|
+
import { deleteCredentials } from '../credentials';
|
|
11
|
+
|
|
12
|
+
jest.mock('@anmiles/logger');
|
|
13
|
+
jest.mock('@anmiles/sleep');
|
|
14
|
+
jest.mock('googleapis/build/src/apis/calendar');
|
|
15
|
+
|
|
16
|
+
jest.mock('../auth');
|
|
17
|
+
jest.mock('../credentials');
|
|
10
18
|
|
|
11
|
-
const items: Array<{ data
|
|
12
|
-
{ data
|
|
13
|
-
{ data
|
|
14
|
-
{ data
|
|
15
|
-
{ data
|
|
19
|
+
const items: Array<{ data: string }> = [
|
|
20
|
+
{ data: 'first' },
|
|
21
|
+
{ data: 'second' },
|
|
22
|
+
{ data: 'third' },
|
|
23
|
+
{ data: 'forth' },
|
|
16
24
|
];
|
|
17
25
|
|
|
18
26
|
const response = [
|
|
@@ -27,11 +35,11 @@ const pageTokens = [
|
|
|
27
35
|
'token2',
|
|
28
36
|
];
|
|
29
37
|
|
|
30
|
-
const
|
|
31
|
-
list
|
|
32
|
-
update
|
|
38
|
+
const getCalendarAPI = <T>(items: Array<Array<T> | null>, pageTokens: Array<string | undefined>): {
|
|
39
|
+
list: jest.Mock;
|
|
40
|
+
update: jest.Mock;
|
|
33
41
|
} => ({
|
|
34
|
-
list
|
|
42
|
+
list: jest.fn().mockImplementation(({ pageToken }: { pageToken?: string }): Pick<GoogleApis.Common.GaxiosResponse<CommonResponse<unknown>>, 'data'> => {
|
|
35
43
|
const listException = getListException();
|
|
36
44
|
|
|
37
45
|
if (listException) {
|
|
@@ -41,107 +49,96 @@ const getAPI = <T>(items: Array<Array<T> | null>, pageTokens: Array<string | und
|
|
|
41
49
|
const index = pageTokens.indexOf(pageToken);
|
|
42
50
|
|
|
43
51
|
return {
|
|
44
|
-
data
|
|
45
|
-
items
|
|
46
|
-
nextPageToken
|
|
47
|
-
pageInfo
|
|
48
|
-
totalResults
|
|
52
|
+
data: {
|
|
53
|
+
items : items[index]!,
|
|
54
|
+
nextPageToken: pageTokens[index + 1],
|
|
55
|
+
pageInfo : {
|
|
56
|
+
totalResults: !items[index]
|
|
49
57
|
? null
|
|
50
58
|
: items.reduce((sum, list) => sum + (list?.length ?? 0), 0),
|
|
51
59
|
},
|
|
52
60
|
},
|
|
53
61
|
};
|
|
54
62
|
}),
|
|
55
|
-
update
|
|
63
|
+
update: jest.fn(),
|
|
56
64
|
});
|
|
57
65
|
|
|
58
|
-
const params = { key
|
|
66
|
+
const params = { key: 'value' };
|
|
59
67
|
|
|
60
|
-
const profile
|
|
61
|
-
const
|
|
62
|
-
|
|
68
|
+
const profile = 'username1';
|
|
69
|
+
const calendarList = getCalendarAPI(response, pageTokens);
|
|
70
|
+
const calendarApis = {
|
|
71
|
+
calendarList,
|
|
63
72
|
};
|
|
64
73
|
|
|
65
|
-
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
75
|
+
const googleAuth = {} as GoogleApis.Common.OAuth2Client;
|
|
66
76
|
|
|
67
77
|
const scopes = [ 'scope1', 'scope2' ];
|
|
68
78
|
|
|
69
|
-
const getListException = jest.fn()
|
|
79
|
+
const getListException = jest.mocked(jest.fn());
|
|
80
|
+
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
82
|
+
jest.mocked(calendar).mockImplementation(() => calendarApis as unknown as GoogleApis.calendar_v3.Calendar);
|
|
83
|
+
jest.mocked(getAuth).mockResolvedValue(googleAuth);
|
|
70
84
|
|
|
71
85
|
beforeEach(() => {
|
|
72
86
|
getListException.mockReturnValue(undefined);
|
|
73
87
|
});
|
|
74
88
|
|
|
75
|
-
jest.mock<{ calendar : typeof calendar }>('googleapis/build/src/apis/calendar', () => ({
|
|
76
|
-
calendar : jest.fn().mockImplementation(() => apis),
|
|
77
|
-
}));
|
|
78
|
-
|
|
79
|
-
jest.mock<Partial<typeof auth>>('../auth', () => ({
|
|
80
|
-
getAuth : jest.fn().mockImplementation(() => googleAuth),
|
|
81
|
-
}));
|
|
82
|
-
|
|
83
|
-
jest.mock<Partial<typeof secrets>>('../secrets', () => ({
|
|
84
|
-
deleteCredentials : jest.fn(),
|
|
85
|
-
}));
|
|
86
|
-
|
|
87
|
-
jest.mock<Partial<typeof logger>>('@anmiles/logger', () => ({
|
|
88
|
-
log : jest.fn(),
|
|
89
|
-
warn : jest.fn(),
|
|
90
|
-
}));
|
|
91
|
-
|
|
92
|
-
jest.mock<Partial<typeof sleep>>('@anmiles/sleep', () => jest.fn());
|
|
93
|
-
|
|
94
89
|
describe('src/lib/api', () => {
|
|
95
90
|
describe('getAPI', () => {
|
|
96
91
|
it('should call getAuth', async () => {
|
|
97
|
-
await
|
|
92
|
+
await getAPI((auth) => calendar({ version: 'v3', auth }), profile);
|
|
98
93
|
|
|
99
|
-
expect(
|
|
94
|
+
expect(getAuth).toHaveBeenCalledWith(profile, undefined);
|
|
100
95
|
});
|
|
101
96
|
|
|
102
97
|
it('should pass temporariness and scopes', async () => {
|
|
103
|
-
await
|
|
98
|
+
await getAPI((auth) => calendar({ version: 'v3', auth }), profile, { scopes, temporary: true });
|
|
104
99
|
|
|
105
|
-
expect(
|
|
100
|
+
expect(getAuth).toHaveBeenCalledWith(profile, { scopes, temporary: true });
|
|
106
101
|
});
|
|
107
102
|
|
|
108
103
|
it('should warn when creating permanent credentials using non-readonly scopes', async () => {
|
|
109
|
-
await
|
|
104
|
+
await getAPI((auth) => calendar({ version: 'v3', auth }), profile, { scopes });
|
|
110
105
|
|
|
111
|
-
expect(logger.warn).toHaveBeenCalledWith('
|
|
106
|
+
expect(logger.warn).toHaveBeenCalledWith('\
|
|
107
|
+
WARNING: trying to create permanent credentials using non-readonly scopes (scope1, scope2). \
|
|
108
|
+
Permanent credentials will be stored in the file and potentially might be re-used to modify your data');
|
|
112
109
|
});
|
|
113
110
|
|
|
114
111
|
it('should not warn when creating temporary credentials using non-readonly scopes', async () => {
|
|
115
|
-
await
|
|
112
|
+
await getAPI((auth) => calendar({ version: 'v3', auth }), profile, { scopes, temporary: true });
|
|
116
113
|
|
|
117
114
|
expect(logger.warn).not.toHaveBeenCalled();
|
|
118
115
|
});
|
|
119
116
|
|
|
120
117
|
it('should not warn when creating permanent credentials using readonly scopes only', async () => {
|
|
121
|
-
await
|
|
118
|
+
await getAPI((auth) => calendar({ version: 'v3', auth }), profile, { scopes: [ 'scope1.readonly', 'scope2.readonly' ], temporary: true });
|
|
122
119
|
|
|
123
120
|
expect(logger.warn).not.toHaveBeenCalled();
|
|
124
121
|
});
|
|
125
122
|
});
|
|
126
123
|
|
|
127
124
|
describe('API', () => {
|
|
128
|
-
let instance: InstanceType<typeof
|
|
125
|
+
let instance: InstanceType<typeof API<calendar_v3.Calendar>>;
|
|
129
126
|
|
|
130
127
|
beforeEach(async () => {
|
|
131
|
-
instance = await
|
|
128
|
+
instance = await getAPI((auth) => calendar({ version: 'v3', auth }), profile);
|
|
132
129
|
});
|
|
133
130
|
|
|
134
131
|
describe('getItems', () => {
|
|
135
132
|
it('should call API list method for each page', async () => {
|
|
136
|
-
await instance.getItems((
|
|
133
|
+
await instance.getItems(() => calendarList, params);
|
|
137
134
|
|
|
138
135
|
pageTokens.forEach((pageToken) => {
|
|
139
|
-
expect(
|
|
136
|
+
expect(calendarApis.calendarList.list).toHaveBeenCalledWith({ ...params, pageToken });
|
|
140
137
|
});
|
|
141
138
|
});
|
|
142
139
|
|
|
143
140
|
it('should output progress by default', async () => {
|
|
144
|
-
await instance.getItems((
|
|
141
|
+
await instance.getItems(() => calendarList, params);
|
|
145
142
|
|
|
146
143
|
expect(logger.log).toHaveBeenCalledTimes(response.length);
|
|
147
144
|
expect(logger.log).toHaveBeenCalledWith('Getting items (2 of 4)...');
|
|
@@ -150,25 +147,24 @@ describe('src/lib/api', () => {
|
|
|
150
147
|
});
|
|
151
148
|
|
|
152
149
|
it('should not output progress if hidden', async () => {
|
|
153
|
-
await instance.getItems((
|
|
150
|
+
await instance.getItems(() => calendarList, params, { hideProgress: true });
|
|
154
151
|
|
|
155
152
|
expect(logger.log).not.toHaveBeenCalled();
|
|
156
153
|
});
|
|
157
154
|
|
|
158
155
|
it('should sleep after reach request', async () => {
|
|
159
|
-
await instance.getItems((
|
|
156
|
+
await instance.getItems(() => calendarList, params);
|
|
160
157
|
|
|
161
158
|
expect(sleep).toHaveBeenCalledTimes(response.length);
|
|
162
159
|
expect(sleep).toHaveBeenCalledWith(300);
|
|
163
160
|
});
|
|
164
161
|
|
|
165
162
|
it('should be initialized and called once if no API error', async () => {
|
|
166
|
-
const getAuthSpy = jest.spyOn(auth, 'getAuth');
|
|
167
163
|
const getItemsSpy = jest.spyOn(instance, 'getItems');
|
|
168
164
|
|
|
169
|
-
await instance.getItems((
|
|
165
|
+
await instance.getItems(() => calendarList, params);
|
|
170
166
|
|
|
171
|
-
expect(
|
|
167
|
+
expect(getAuth).toHaveBeenCalledTimes(1);
|
|
172
168
|
expect(getItemsSpy).toHaveBeenCalledTimes(1);
|
|
173
169
|
});
|
|
174
170
|
|
|
@@ -178,16 +174,15 @@ describe('src/lib/api', () => {
|
|
|
178
174
|
// fail twice
|
|
179
175
|
getListException.mockReturnValueOnce(error).mockReturnValueOnce(error);
|
|
180
176
|
|
|
181
|
-
const getAuthSpy = jest.spyOn(auth, 'getAuth');
|
|
182
177
|
const getItemsSpy = jest.spyOn(instance, 'getItems');
|
|
183
|
-
|
|
178
|
+
jest.mocked(getAuth).mockClear();
|
|
184
179
|
getItemsSpy.mockClear();
|
|
185
180
|
|
|
186
|
-
await instance.getItems((
|
|
181
|
+
await instance.getItems(() => calendarList, params);
|
|
187
182
|
|
|
188
183
|
expect(logger.warn).toHaveBeenCalledWith('Access token stored is invalid, re-creating...');
|
|
189
|
-
expect(
|
|
190
|
-
expect(
|
|
184
|
+
expect(deleteCredentials).toHaveBeenCalledWith(profile);
|
|
185
|
+
expect(getAuth).toHaveBeenCalledTimes(2);
|
|
191
186
|
expect(getItemsSpy).toHaveBeenCalledTimes(3);
|
|
192
187
|
}
|
|
193
188
|
});
|
|
@@ -198,27 +193,30 @@ describe('src/lib/api', () => {
|
|
|
198
193
|
// fail twice
|
|
199
194
|
getListException.mockReturnValueOnce(error);
|
|
200
195
|
|
|
201
|
-
const instance = await
|
|
202
|
-
await expect(instance.getItems((
|
|
196
|
+
const instance = await getAPI((auth) => calendar({ version: 'v3', auth }), profile, { temporary: true });
|
|
197
|
+
await expect(instance.getItems(() => calendarList, params))
|
|
198
|
+
.rejects.toEqual(error);
|
|
203
199
|
}
|
|
204
200
|
});
|
|
205
201
|
|
|
206
202
|
it('should re-throw API exception if not invalid_grant or Invalid credentials', async () => {
|
|
207
203
|
const error = new Error('random exception');
|
|
208
204
|
getListException.mockReturnValueOnce(error);
|
|
209
|
-
await expect(instance.getItems((
|
|
205
|
+
await expect(instance.getItems(() => calendarList, params))
|
|
206
|
+
.rejects.toEqual(error);
|
|
210
207
|
});
|
|
211
208
|
|
|
212
209
|
it('should return items data', async () => {
|
|
213
|
-
const returnedItems = await instance.getItems((
|
|
210
|
+
const returnedItems = await instance.getItems(() => calendarList, params);
|
|
214
211
|
|
|
215
212
|
expect(returnedItems).toEqual(items);
|
|
216
213
|
});
|
|
217
214
|
|
|
218
215
|
it('should throw if api was not initialized before getting items', async () => {
|
|
219
|
-
instance = new
|
|
216
|
+
instance = new API((auth) => calendar({ version: 'v3', auth }), profile);
|
|
220
217
|
|
|
221
|
-
await expect(async () => instance.getItems((
|
|
218
|
+
await expect(async () => instance.getItems(() => calendarList, params))
|
|
219
|
+
.rejects.toEqual(new Error('API is not initialized. Call `init` before getting items.'));
|
|
222
220
|
});
|
|
223
221
|
});
|
|
224
222
|
});
|
|
@@ -1,149 +1,73 @@
|
|
|
1
1
|
import { google } from 'googleapis';
|
|
2
2
|
import type GoogleApis from 'googleapis';
|
|
3
|
-
import logger from '@anmiles/logger';
|
|
4
|
-
import profiles from '../profiles';
|
|
5
|
-
import secrets from '../secrets';
|
|
6
3
|
|
|
7
|
-
import
|
|
4
|
+
import type { Secrets } from '../../types/secrets';
|
|
5
|
+
import { getAuth } from '../auth';
|
|
6
|
+
import { getCredentials } from '../credentials';
|
|
7
|
+
import { getSecrets } from '../secrets';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
jest.mock
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
jest.mock<Partial<typeof logger>>('@anmiles/logger', () => ({
|
|
16
|
-
info : jest.fn(),
|
|
17
|
-
warn : jest.fn(),
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
jest.mock<Partial<typeof profiles>>('../profiles', () => ({
|
|
21
|
-
getProfiles : jest.fn().mockImplementation(() => allProfiles),
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
jest.mock<Partial<typeof secrets>>('../secrets', () => ({
|
|
25
|
-
getSecrets : jest.fn().mockImplementation(() => secretsObject),
|
|
26
|
-
getCredentials : jest.fn().mockImplementation(() => credentials),
|
|
27
|
-
}));
|
|
28
|
-
|
|
29
|
-
jest.mock('googleapis', () => ({
|
|
30
|
-
google : {
|
|
31
|
-
auth : {
|
|
32
|
-
OAuth2 : jest.fn().mockImplementation(() => googleAuth),
|
|
33
|
-
},
|
|
34
|
-
options : jest.fn(),
|
|
35
|
-
},
|
|
36
|
-
}));
|
|
9
|
+
jest.mock('googleapis');
|
|
10
|
+
jest.mock('@anmiles/logger');
|
|
11
|
+
jest.mock('../credentials');
|
|
12
|
+
jest.mock('../secrets');
|
|
37
13
|
|
|
38
14
|
const profile = 'username';
|
|
39
|
-
const
|
|
40
|
-
const credentials = 'credentials' as GoogleApis.Auth.Credentials;
|
|
15
|
+
const credentials = 'credentials' as GoogleApis.Auth.Credentials; // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
|
|
41
16
|
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
42
18
|
const googleAuth = {
|
|
43
|
-
setCredentials
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
web
|
|
48
|
-
client_id
|
|
49
|
-
|
|
50
|
-
|
|
19
|
+
setCredentials: jest.fn(),
|
|
20
|
+
} as unknown as GoogleApis.Common.OAuth2Client;
|
|
21
|
+
|
|
22
|
+
const secrets: Secrets = {
|
|
23
|
+
web: {
|
|
24
|
+
client_id : 'client_id.apps.googleusercontent.com',
|
|
25
|
+
project_id : 'project_id',
|
|
26
|
+
auth_uri : 'https://accounts.google.com/o/oauth2/auth',
|
|
27
|
+
token_uri : 'https://oauth2.googleapis.com/token',
|
|
28
|
+
auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs',
|
|
29
|
+
client_secret : 'client_secret',
|
|
30
|
+
redirect_uris : [ 'redirect_uri' ],
|
|
51
31
|
},
|
|
52
32
|
};
|
|
53
33
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
await original.login();
|
|
58
|
-
expect(profiles.getProfiles).toHaveBeenCalledWith();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should auth all profiles', async () => {
|
|
62
|
-
await original.login();
|
|
63
|
-
|
|
64
|
-
allProfiles.forEach((profile) => {
|
|
65
|
-
expect(auth.getAuth).toHaveBeenCalledWith(profile, undefined);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('should auth only specified profile', async () => {
|
|
70
|
-
await original.login('username1');
|
|
71
|
-
|
|
72
|
-
expect(auth.getAuth).toHaveBeenCalledWith('username1', undefined);
|
|
73
|
-
expect(auth.getAuth).not.toHaveBeenCalledWith('username2', undefined);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should pass temporariness for all profiles', async () => {
|
|
77
|
-
await original.login(undefined, { temporary : true });
|
|
78
|
-
|
|
79
|
-
expect(auth.getAuth).toHaveBeenCalledWith('username1', { temporary : true });
|
|
80
|
-
expect(auth.getAuth).toHaveBeenCalledWith('username2', { temporary : true });
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should pass temporariness only for specified profile', async () => {
|
|
85
|
-
await original.login('username1', { temporary : true });
|
|
86
|
-
|
|
87
|
-
expect(auth.getAuth).toHaveBeenCalledWith('username1', { temporary : true });
|
|
88
|
-
expect(auth.getAuth).not.toHaveBeenCalledWith('username2', { temporary : true });
|
|
89
|
-
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('should show auth progress for all profiles by default', async () => {
|
|
93
|
-
await original.login();
|
|
94
|
-
|
|
95
|
-
expect(logger.warn).toHaveBeenCalledWith('username1 - logging in...');
|
|
96
|
-
expect(logger.warn).toHaveBeenCalledWith('username2 - logging in...');
|
|
97
|
-
expect(logger.info).toHaveBeenCalledWith('username1 - logged in successfully');
|
|
98
|
-
expect(logger.info).toHaveBeenCalledWith('username2 - logged in successfully');
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should show auth progress for specified profile by default', async () => {
|
|
102
|
-
await original.login('username1');
|
|
103
|
-
|
|
104
|
-
expect(logger.warn).toHaveBeenCalledWith('username1 - logging in...');
|
|
105
|
-
expect(logger.info).toHaveBeenCalledWith('username1 - logged in successfully');
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('should not show auth progress if hidden', async () => {
|
|
109
|
-
await original.login(undefined, { hideProgress : true });
|
|
110
|
-
await original.login('username1', { hideProgress : true });
|
|
111
|
-
|
|
112
|
-
expect(logger.info).not.toHaveBeenCalled();
|
|
113
|
-
});
|
|
114
|
-
});
|
|
34
|
+
jest.mocked(getCredentials).mockResolvedValue(credentials);
|
|
35
|
+
jest.mocked(getSecrets).mockReturnValue(secrets);
|
|
36
|
+
jest.mocked(google.auth.OAuth2).mockReturnValue(googleAuth);
|
|
115
37
|
|
|
38
|
+
describe('src/lib/auth', () => {
|
|
116
39
|
describe('getAuth', () => {
|
|
117
40
|
it('should get secrets', async () => {
|
|
118
|
-
await
|
|
119
|
-
expect(
|
|
41
|
+
await getAuth(profile);
|
|
42
|
+
expect(getSecrets).toHaveBeenCalledWith(profile);
|
|
120
43
|
});
|
|
121
44
|
|
|
122
45
|
it('should get credentials', async () => {
|
|
123
|
-
await
|
|
124
|
-
expect(
|
|
46
|
+
await getAuth(profile);
|
|
47
|
+
expect(getCredentials).toHaveBeenCalledWith(profile, googleAuth, undefined);
|
|
125
48
|
});
|
|
126
49
|
|
|
127
50
|
it('should create OAuth2 instance', async () => {
|
|
128
|
-
await
|
|
129
|
-
expect(google.auth.OAuth2).toHaveBeenCalledWith(
|
|
51
|
+
await getAuth(profile);
|
|
52
|
+
expect(google.auth.OAuth2).toHaveBeenCalledWith(secrets.web.client_id, secrets.web.client_secret, secrets.web.redirect_uris[0]);
|
|
130
53
|
});
|
|
131
54
|
|
|
132
55
|
it('should set credentials', async () => {
|
|
133
|
-
await
|
|
56
|
+
await getAuth(profile);
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
134
58
|
expect(googleAuth.setCredentials).toHaveBeenCalledWith(credentials);
|
|
135
59
|
});
|
|
136
60
|
|
|
137
61
|
it('should pass temporariness', async () => {
|
|
138
|
-
await
|
|
62
|
+
await getAuth(profile, { temporary: true });
|
|
139
63
|
|
|
140
|
-
expect(
|
|
64
|
+
expect(getCredentials).toHaveBeenCalledWith(profile, googleAuth, { temporary: true });
|
|
141
65
|
});
|
|
142
66
|
|
|
143
67
|
it('should set google auth', async () => {
|
|
144
|
-
await
|
|
68
|
+
await getAuth(profile);
|
|
145
69
|
|
|
146
|
-
expect(google.options).toHaveBeenCalledWith({ auth
|
|
70
|
+
expect(google.options).toHaveBeenCalledWith({ auth: googleAuth }); // eslint-disable-line @typescript-eslint/unbound-method
|
|
147
71
|
});
|
|
148
72
|
});
|
|
149
73
|
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import logger from '@anmiles/logger';
|
|
2
|
+
|
|
3
|
+
import { getAuth } from '../auth';
|
|
4
|
+
import { login } from '../login';
|
|
5
|
+
import { getProfiles } from '../profiles';
|
|
6
|
+
|
|
7
|
+
const profiles = [ 'username1', 'username2' ];
|
|
8
|
+
|
|
9
|
+
jest.mock('@anmiles/logger');
|
|
10
|
+
jest.mock('../auth');
|
|
11
|
+
jest.mock('../profiles');
|
|
12
|
+
|
|
13
|
+
jest.mocked(getProfiles).mockReturnValue(profiles);
|
|
14
|
+
|
|
15
|
+
describe('src/lib/login', () => {
|
|
16
|
+
describe('login', () => {
|
|
17
|
+
it('should auth all profiles', async () => {
|
|
18
|
+
await login();
|
|
19
|
+
|
|
20
|
+
profiles.forEach((profile) => {
|
|
21
|
+
expect(getAuth).toHaveBeenCalledWith(profile, undefined);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should auth only specified profile', async () => {
|
|
26
|
+
await login('username1');
|
|
27
|
+
|
|
28
|
+
expect(getAuth).toHaveBeenCalledWith('username1', undefined);
|
|
29
|
+
expect(getAuth).not.toHaveBeenCalledWith('username2', undefined);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should pass temporariness for all profiles', async () => {
|
|
33
|
+
await login(undefined, { temporary: true });
|
|
34
|
+
|
|
35
|
+
expect(getAuth).toHaveBeenCalledWith('username1', { temporary: true });
|
|
36
|
+
expect(getAuth).toHaveBeenCalledWith('username2', { temporary: true });
|
|
37
|
+
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should pass temporariness only for specified profile', async () => {
|
|
41
|
+
await login('username1', { temporary: true });
|
|
42
|
+
|
|
43
|
+
expect(getAuth).toHaveBeenCalledWith('username1', { temporary: true });
|
|
44
|
+
expect(getAuth).not.toHaveBeenCalledWith('username2', { temporary: true });
|
|
45
|
+
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should show auth progress for all profiles by default', async () => {
|
|
49
|
+
await login();
|
|
50
|
+
|
|
51
|
+
expect(logger.warn).toHaveBeenCalledWith('username1 - logging in...');
|
|
52
|
+
expect(logger.warn).toHaveBeenCalledWith('username2 - logging in...');
|
|
53
|
+
expect(logger.info).toHaveBeenCalledWith('username1 - logged in successfully');
|
|
54
|
+
expect(logger.info).toHaveBeenCalledWith('username2 - logged in successfully');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should show auth progress for specified profile by default', async () => {
|
|
58
|
+
await login('username1');
|
|
59
|
+
|
|
60
|
+
expect(logger.warn).toHaveBeenCalledWith('username1 - logging in...');
|
|
61
|
+
expect(logger.info).toHaveBeenCalledWith('username1 - logged in successfully');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should not show auth progress if hidden', async () => {
|
|
65
|
+
await login(undefined, { hideProgress: true });
|
|
66
|
+
await login('username1', { hideProgress: true });
|
|
67
|
+
|
|
68
|
+
expect(logger.info).not.toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|