pryv 3.0.0 → 3.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pryv",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Pryv JavaScript library",
5
5
  "keywords": [
6
6
  "Pryv",
package/src/Connection.js CHANGED
@@ -6,6 +6,7 @@ const utils = require('./utils.js');
6
6
  const jsonParser = require('./lib/json-parser');
7
7
  const libGetEventStreamed = require('./lib/getEventStreamed');
8
8
  const PryvError = require('./lib/PryvError');
9
+ const buildSearchParams = require('./lib/buildSearchParams');
9
10
 
10
11
  /**
11
12
  * @class Connection
@@ -290,7 +291,7 @@ class Connection {
290
291
  path = path || '';
291
292
  let queryStr = '';
292
293
  if (queryParams && Object.keys(queryParams).length > 0) {
293
- queryStr = '?' + new URLSearchParams(queryParams).toString();
294
+ queryStr = '?' + buildSearchParams(queryParams);
294
295
  }
295
296
  const response = await fetch(this.endpoint + path + queryStr, {
296
297
  headers: {
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license
3
+ * [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
4
+ */
5
+
6
+ /**
7
+ * Build URL search params string from an object, properly handling arrays.
8
+ * Arrays are expanded as repeated keys: { a: ['x', 'y'] } => 'a=x&a=y'
9
+ * @param {Object} params - Query parameters object
10
+ * @returns {string} - URL encoded query string
11
+ */
12
+ function buildSearchParams (params) {
13
+ const searchParams = new URLSearchParams();
14
+ for (const [key, value] of Object.entries(params)) {
15
+ if (Array.isArray(value)) {
16
+ for (const item of value) {
17
+ searchParams.append(key, item);
18
+ }
19
+ } else if (value !== undefined && value !== null) {
20
+ searchParams.append(key, value);
21
+ }
22
+ }
23
+ return searchParams.toString();
24
+ }
25
+
26
+ module.exports = buildSearchParams;
@@ -4,6 +4,8 @@
4
4
  */
5
5
  /* global fetch */
6
6
 
7
+ const buildSearchParams = require('./buildSearchParams');
8
+
7
9
  module.exports = getEventStreamed;
8
10
 
9
11
  async function getEventStreamed (conn, queryParam, parser) {
@@ -43,7 +45,7 @@ async function getEventStreamed (conn, queryParam, parser) {
43
45
 
44
46
  // ------------ fetch ------------------- //
45
47
  const url = new URL(conn.endpoint + 'events');
46
- url.search = new URLSearchParams(queryParam).toString();
48
+ url.search = buildSearchParams(queryParam);
47
49
  const fetchParams = { method: 'GET', headers: { Accept: 'application/json' } };
48
50
  if (conn.token) fetchParams.headers.Authorization = conn.token;
49
51
 
@@ -57,7 +59,7 @@ async function getEventStreamed (conn, queryParam, parser) {
57
59
  }
58
60
 
59
61
  if (errResult) {
60
- throw new Error(errResult);
62
+ throw new Error(errResult?.message + ' ' + errResult?.rawResponse);
61
63
  }
62
64
 
63
65
  // We're done!
package/src/utils.js CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
  const regexAPIandToken = /(.+):\/\/(.+)@(.+)/gm;
6
6
  const regexSchemaAndPath = /(.+):\/\/(.+)/gm;
7
+ const buildSearchParams = require('./lib/buildSearchParams');
7
8
 
8
9
  /**
9
10
  * Utilities to access Pryv API.
@@ -21,7 +22,7 @@ const utils = module.exports = {
21
22
  async fetchGet (url, queryParams = {}, headers = {}) {
22
23
  let queryStr = '';
23
24
  if (queryParams && Object.keys(queryParams).length > 0) {
24
- queryStr = '?' + new URLSearchParams(queryParams).toString();
25
+ queryStr = '?' + buildSearchParams(queryParams);
25
26
  }
26
27
  const myHeaders = Object.assign({ Accept: 'application/json' }, headers);
27
28
  const response = await fetch(url + queryStr, { headers: myHeaders });
@@ -0,0 +1,126 @@
1
+ /**
2
+ * @license
3
+ * [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
4
+ */
5
+ /* global describe, it, before, after, expect, pryv, testData */
6
+
7
+ const { createId: cuid } = require('@paralleldrive/cuid2');
8
+
9
+ let conn = null;
10
+ const testStreamId = 'acc-' + cuid().slice(0, 8);
11
+ let createdAccessId = null;
12
+ let createdAccessToken = null;
13
+
14
+ describe('[ACSX] Accesses', () => {
15
+ before(async function () {
16
+ this.timeout(15000);
17
+ await testData.prepare();
18
+ conn = new pryv.Connection(testData.apiEndpointWithToken);
19
+
20
+ // Create a test stream for permissions
21
+ await conn.api([{
22
+ method: 'streams.create',
23
+ params: { id: testStreamId, name: 'Access Test Stream' }
24
+ }]);
25
+ });
26
+
27
+ describe('[ACRX] accesses.create', function () {
28
+ it('[ACRA] create a shared access', async () => {
29
+ const res = await conn.api([{
30
+ method: 'accesses.create',
31
+ params: {
32
+ name: 'test-shared-' + cuid().slice(0, 8),
33
+ type: 'shared',
34
+ permissions: [{ streamId: testStreamId, level: 'read' }]
35
+ }
36
+ }]);
37
+ expect(res[0]).to.exist;
38
+ expect(res[0].access).to.exist;
39
+ expect(res[0].access.token).to.exist;
40
+ expect(res[0].access.type).to.equal('shared');
41
+ createdAccessId = res[0].access.id;
42
+ createdAccessToken = res[0].access.token;
43
+ });
44
+
45
+ it('[ACRB] create an app access', async () => {
46
+ const res = await conn.api([{
47
+ method: 'accesses.create',
48
+ params: {
49
+ name: 'test-app-' + cuid().slice(0, 8),
50
+ type: 'app',
51
+ permissions: [{ streamId: testStreamId, level: 'contribute' }]
52
+ }
53
+ }]);
54
+ expect(res[0]).to.exist;
55
+ expect(res[0].access).to.exist;
56
+ expect(res[0].access.type).to.equal('app');
57
+ });
58
+
59
+ it('[ACRC] reject access with invalid permission level', async () => {
60
+ const res = await conn.api([{
61
+ method: 'accesses.create',
62
+ params: {
63
+ name: 'bad-access',
64
+ type: 'shared',
65
+ permissions: [{ streamId: testStreamId, level: 'bogus' }]
66
+ }
67
+ }]);
68
+ expect(res[0]).to.exist;
69
+ expect(res[0].error).to.exist;
70
+ });
71
+ });
72
+
73
+ describe('[AGTX] accesses.get', function () {
74
+ it('[AGTA] list accesses', async () => {
75
+ const res = await conn.api([{
76
+ method: 'accesses.get',
77
+ params: {}
78
+ }]);
79
+ expect(res[0]).to.exist;
80
+ expect(res[0].accesses).to.exist;
81
+ expect(Array.isArray(res[0].accesses)).to.equal(true);
82
+ expect(res[0].accesses.length).to.be.gt(0);
83
+ });
84
+
85
+ it('[AGTB] created access is in the list', async () => {
86
+ const res = await conn.api([{
87
+ method: 'accesses.get',
88
+ params: {}
89
+ }]);
90
+ const found = res[0].accesses.find(a => a.id === createdAccessId);
91
+ expect(found).to.exist;
92
+ expect(found.token).to.equal(createdAccessToken);
93
+ });
94
+ });
95
+
96
+ describe('[ADLX] accesses.delete', function () {
97
+ it('[ADLA] delete (revoke) an access', async () => {
98
+ expect(createdAccessId).to.exist;
99
+ const res = await conn.api([{
100
+ method: 'accesses.delete',
101
+ params: { id: createdAccessId }
102
+ }]);
103
+ expect(res[0]).to.exist;
104
+ expect(res[0].accessDeletion).to.exist;
105
+ expect(res[0].accessDeletion.id).to.equal(createdAccessId);
106
+ });
107
+
108
+ it('[ADLB] deleted access is no longer in the list', async () => {
109
+ const res = await conn.api([{
110
+ method: 'accesses.get',
111
+ params: {}
112
+ }]);
113
+ const found = res[0].accesses.find(a => a.id === createdAccessId);
114
+ expect(found).to.not.exist;
115
+ });
116
+ });
117
+
118
+ // Cleanup
119
+ after(async () => {
120
+ if (!conn) return;
121
+ await conn.api([
122
+ { method: 'streams.delete', params: { id: testStreamId } },
123
+ { method: 'streams.delete', params: { id: testStreamId } }
124
+ ]);
125
+ });
126
+ });
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @license
3
+ * [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
4
+ */
5
+ /* global describe, it, before, expect, pryv, testData */
6
+
7
+ let conn = null;
8
+
9
+ describe('[ACTX] Account', () => {
10
+ before(async function () {
11
+ this.timeout(15000);
12
+ await testData.prepare();
13
+ conn = new pryv.Connection(testData.apiEndpointWithToken);
14
+ });
15
+
16
+ describe('[AINX] account.get', function () {
17
+ it('[AINA] get account info', async () => {
18
+ const res = await conn.api([{
19
+ method: 'account.get',
20
+ params: {}
21
+ }]);
22
+ expect(res[0]).to.exist;
23
+ expect(res[0].account).to.exist;
24
+ expect(res[0].account.username).to.equal(testData.username);
25
+ expect(res[0].account.email).to.exist;
26
+ });
27
+ });
28
+
29
+ describe('[ASUX] account.get storageUsed', function () {
30
+ it('[ASUA] storageUsed has expected fields', async () => {
31
+ const res = await conn.api([{
32
+ method: 'account.get',
33
+ params: {}
34
+ }]);
35
+ const account = res[0].account;
36
+ expect(account.storageUsed).to.exist;
37
+ expect(account.storageUsed.dbDocuments).to.be.a('number');
38
+ expect(account.storageUsed.attachedFiles).to.be.a('number');
39
+ });
40
+ });
41
+
42
+ describe('[ACPX] account.changePassword', function () {
43
+ it('[ACPA] change password and change back', async () => {
44
+ const oldPassword = testData.password;
45
+ const newPassword = oldPassword + '-new';
46
+
47
+ // Change to new password
48
+ const res1 = await conn.api([{
49
+ method: 'account.changePassword',
50
+ params: { oldPassword, newPassword }
51
+ }]);
52
+ expect(res1[0]).to.exist;
53
+ expect(res1[0].error).to.not.exist;
54
+
55
+ // Change back to original
56
+ const res2 = await conn.api([{
57
+ method: 'account.changePassword',
58
+ params: { oldPassword: newPassword, newPassword: oldPassword }
59
+ }]);
60
+ expect(res2[0]).to.exist;
61
+ expect(res2[0].error).to.not.exist;
62
+ });
63
+
64
+ it('[ACPB] reject wrong old password', async () => {
65
+ const res = await conn.api([{
66
+ method: 'account.changePassword',
67
+ params: { oldPassword: 'wrong-password', newPassword: 'new-password' }
68
+ }]);
69
+ expect(res[0]).to.exist;
70
+ expect(res[0].error).to.exist;
71
+ });
72
+ });
73
+ });
@@ -0,0 +1,193 @@
1
+ /**
2
+ * @license
3
+ * [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
4
+ */
5
+ /* global describe, it, before, after, expect, JSDOM, testData */
6
+
7
+ const AuthController = require('../src/Auth/AuthController');
8
+ const AuthStates = require('../src/Auth/AuthStates');
9
+ const Service = require('../src/Service');
10
+
11
+ describe('[ACNX] AuthController', function () {
12
+ this.timeout(15000);
13
+
14
+ let service;
15
+ let cleanupDom = false;
16
+
17
+ before(async function () {
18
+ await testData.prepare();
19
+ service = new Service(testData.serviceInfoUrl);
20
+ await service.info();
21
+ });
22
+
23
+ before(async () => {
24
+ if (typeof document !== 'undefined') return;
25
+ cleanupDom = true;
26
+ const dom = new JSDOM('<!DOCTYPE html>', {
27
+ url: 'http://localhost/'
28
+ });
29
+ global.document = dom.window.document;
30
+ global.window = dom.window;
31
+ global.location = dom.window.location;
32
+ global.navigator = { userAgent: 'Safari' };
33
+ });
34
+
35
+ after(async () => {
36
+ if (!cleanupDom) return;
37
+ delete global.document;
38
+ delete global.window;
39
+ delete global.location;
40
+ });
41
+
42
+ describe('[ACVX] Validation', function () {
43
+ it('[ACVA] throws error when settings is null', function () {
44
+ expect(() => new AuthController(null, service)).to.throw('settings cannot be null');
45
+ });
46
+
47
+ it('[ACVB] throws error when authRequest is missing', function () {
48
+ expect(() => new AuthController({}, service)).to.throw('Missing settings.authRequest');
49
+ });
50
+
51
+ it('[ACVC] throws error when requestingAppId is missing', function () {
52
+ expect(() => new AuthController({
53
+ authRequest: { requestedPermissions: [] }
54
+ }, service)).to.throw('Missing settings.authRequest.requestingAppId');
55
+ });
56
+
57
+ it('[ACVD] throws error when requestedPermissions is missing', function () {
58
+ expect(() => new AuthController({
59
+ authRequest: { requestingAppId: 'test-app' }
60
+ }, service)).to.throw('Missing settings.authRequest.requestedPermissions');
61
+ });
62
+ });
63
+
64
+ describe('[ACLX] Listeners', function () {
65
+ it('[ACLA] calls onStateChange listener when state changes', async function () {
66
+ const stateChanges = [];
67
+ const auth = new AuthController({
68
+ authRequest: {
69
+ requestingAppId: 'test-app',
70
+ requestedPermissions: []
71
+ },
72
+ onStateChange: (state) => stateChanges.push(state)
73
+ }, service);
74
+
75
+ await auth.init();
76
+ expect(stateChanges.length).to.be.greaterThan(0);
77
+ expect(stateChanges[0].status).to.equal(AuthStates.LOADING);
78
+ });
79
+
80
+ it('[ACLB] handles listener errors gracefully', async function () {
81
+ const auth = new AuthController({
82
+ authRequest: {
83
+ requestingAppId: 'test-app',
84
+ requestedPermissions: []
85
+ },
86
+ onStateChange: () => { throw new Error('Listener error'); }
87
+ }, service);
88
+
89
+ // Should not throw
90
+ await auth.init();
91
+ expect(auth.state).to.exist;
92
+ });
93
+ });
94
+
95
+ describe('[ACHX] handleClick', function () {
96
+ it('[ACHA] triggers SIGNOUT when authorized', async function () {
97
+ const stateChanges = [];
98
+ const auth = new AuthController({
99
+ authRequest: {
100
+ requestingAppId: 'test-app',
101
+ requestedPermissions: []
102
+ },
103
+ onStateChange: (state) => stateChanges.push(state)
104
+ }, service);
105
+
106
+ await auth.init();
107
+
108
+ // Simulate authorized state
109
+ auth._state = { status: AuthStates.AUTHORIZED };
110
+
111
+ await auth.handleClick();
112
+ const lastState = stateChanges[stateChanges.length - 1];
113
+ expect(lastState.status).to.equal(AuthStates.SIGNOUT);
114
+ });
115
+
116
+ it('[ACHB] handles NEED_SIGNIN click (reopens popup)', async function () {
117
+ const auth = new AuthController({
118
+ authRequest: {
119
+ requestingAppId: 'test-app',
120
+ requestedPermissions: []
121
+ }
122
+ }, service);
123
+
124
+ await auth.init();
125
+
126
+ // Simulate NEED_SIGNIN state
127
+ const needSigninState = { status: AuthStates.NEED_SIGNIN, authUrl: 'http://test.url' };
128
+ auth._state = needSigninState;
129
+
130
+ await auth.handleClick();
131
+ // Should trigger state change with same state
132
+ expect(auth.state.status).to.equal(AuthStates.NEED_SIGNIN);
133
+ });
134
+ });
135
+
136
+ describe('[ACSX] stopAuthRequest', function () {
137
+ it('[ACSA] sets error state with message', async function () {
138
+ const auth = new AuthController({
139
+ authRequest: {
140
+ requestingAppId: 'test-app',
141
+ requestedPermissions: []
142
+ }
143
+ }, service);
144
+
145
+ await auth.init();
146
+ auth.stopAuthRequest('Test error message');
147
+
148
+ expect(auth.state.status).to.equal(AuthStates.ERROR);
149
+ expect(auth.state.message).to.equal('Test error message');
150
+ });
151
+ });
152
+
153
+ describe('[ACRX] returnURL', function () {
154
+ it('[ACRA] throws on invalid returnURL trailer', function () {
155
+ const auth = new AuthController({
156
+ authRequest: {
157
+ requestingAppId: 'test-app',
158
+ requestedPermissions: []
159
+ }
160
+ }, service);
161
+
162
+ expect(() => auth.getReturnURL('http://example.com')).to.throw('Last character');
163
+ });
164
+
165
+ it('[ACRB] handles null/undefined returnURL', function () {
166
+ const auth = new AuthController({
167
+ authRequest: {
168
+ requestingAppId: 'test-app',
169
+ requestedPermissions: []
170
+ }
171
+ }, service);
172
+
173
+ // Desktop browser (Safari) returns false for auto mode
174
+ const result = auth.getReturnURL(undefined, 'http://test.com', { userAgent: 'Safari' });
175
+ expect(result).to.equal(false);
176
+ });
177
+ });
178
+
179
+ describe('[AIST] State', function () {
180
+ it('[AISA] state getter and setter work correctly', async function () {
181
+ const auth = new AuthController({
182
+ authRequest: {
183
+ requestingAppId: 'test-app',
184
+ requestedPermissions: []
185
+ }
186
+ }, service);
187
+
188
+ auth.state = { status: AuthStates.LOADING };
189
+ expect(auth.state.status).to.equal(AuthStates.LOADING);
190
+ expect(auth.state.id).to.equal(AuthStates.LOADING); // retro-compatibility
191
+ });
192
+ });
193
+ });
@@ -8,7 +8,7 @@ const utils = require('../src/utils.js');
8
8
  const Service = require('../src/Service');
9
9
  const AuthController = require('../src/Auth/AuthController.js');
10
10
 
11
- describe('Browser.LoginButton', function () {
11
+ describe('[AUTX] Browser.LoginButton', function () {
12
12
  this.timeout(15000);
13
13
 
14
14
  let auth;
@@ -43,7 +43,7 @@ describe('Browser.LoginButton', function () {
43
43
  await auth.init();
44
44
  });
45
45
 
46
- it('getReturnURL()', async function () {
46
+ it('[AUTA] getReturnURL()', async function () {
47
47
  const myUrl = 'https://mysite.com/bobby';
48
48
  let error = null;
49
49
  try {
@@ -71,12 +71,12 @@ describe('Browser.LoginButton', function () {
71
71
  expect(auth.getReturnURL('self?', myUrl, fakeNavigator)).to.equal(myUrl + '?');
72
72
  });
73
73
 
74
- it('browserIsMobileOrTablet()', async function () {
74
+ it('[AUTB] browserIsMobileOrTablet()', async function () {
75
75
  expect(utils.browserIsMobileOrTablet({ userAgent: 'android' })).to.be.true;
76
76
  expect(utils.browserIsMobileOrTablet({ userAgent: 'Safari' })).to.be.false;
77
77
  });
78
78
 
79
- it('cleanURLFromPrYvParams()', async function () {
79
+ it('[AUTC] cleanURLFromPrYvParams()', async function () {
80
80
  expect('https://my.Url.com/?bobby=2').to.equal(utils.cleanURLFromPrYvParams(
81
81
  'https://my.Url.com/?bobby=2&prYvZoutOu=1&prYvstatus=2jsadh'));
82
82
 
@@ -17,7 +17,7 @@ function genSettings () {
17
17
  };
18
18
  }
19
19
 
20
- describe('Browser', function () {
20
+ describe('[BRWX] Browser', function () {
21
21
  this.timeout(15000);
22
22
 
23
23
  before(async function () {
@@ -46,7 +46,7 @@ describe('Browser', function () {
46
46
  delete global.location;
47
47
  });
48
48
 
49
- it('setupAuth()', async () => {
49
+ it('[BRWA] setupAuth()', async () => {
50
50
  const settings = genSettings();
51
51
  let AuthLoaded = false;
52
52
  settings.onStateChange = function (state) {
@@ -70,7 +70,7 @@ describe('Browser', function () {
70
70
  }
71
71
  });
72
72
 
73
- it('serviceInfoFromUrl()', async () => {
73
+ it('[BRWB] serviceInfoFromUrl()', async () => {
74
74
  expect('https://zou.zou/service/info').to.equal(pryv.Browser.serviceInfoFromUrl());
75
75
  });
76
76
  });
@@ -0,0 +1,102 @@
1
+ /**
2
+ * @license
3
+ * [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
4
+ */
5
+ /* global describe, it, before, expect, pryv, testData */
6
+
7
+ describe('[CECX] Connection Edge Cases', function () {
8
+ this.timeout(15000);
9
+
10
+ let conn;
11
+
12
+ before(async function () {
13
+ await testData.prepare();
14
+ conn = new pryv.Connection(testData.apiEndpointWithToken);
15
+ });
16
+
17
+ describe('[CERX] Error handling', function () {
18
+ it('[CERA] api() throws on non-array input', async function () {
19
+ let error = null;
20
+ try {
21
+ await conn.api({ method: 'events.get' });
22
+ } catch (e) {
23
+ error = e;
24
+ }
25
+ expect(error).to.exist;
26
+ expect(error.message).to.include('array');
27
+ });
28
+
29
+ it('[CERB] apiOne() throws on error response', async function () {
30
+ let error = null;
31
+ try {
32
+ await conn.apiOne('invalid.method', {});
33
+ } catch (e) {
34
+ error = e;
35
+ }
36
+ expect(error).to.exist;
37
+ });
38
+
39
+ it('[CERC] constructor throws on invalid service param', function () {
40
+ let error = null;
41
+ try {
42
+ const _conn = new pryv.Connection(testData.apiEndpointWithToken, { notAService: true });
43
+ expect(_conn).to.not.exist; // Should not reach here
44
+ } catch (e) {
45
+ error = e;
46
+ }
47
+ expect(error).to.exist;
48
+ expect(error.message).to.include('Invalid service');
49
+ });
50
+
51
+ it('[CERD] _handleMeta throws on missing meta', async function () {
52
+ let error = null;
53
+ try {
54
+ conn._handleMeta({}, Date.now() / 1000);
55
+ } catch (e) {
56
+ error = e;
57
+ }
58
+ expect(error).to.exist;
59
+ expect(error.message).to.include('meta');
60
+ });
61
+
62
+ it('[CERE] _handleMeta throws on missing serverTime', async function () {
63
+ let error = null;
64
+ try {
65
+ conn._handleMeta({ meta: {} }, Date.now() / 1000);
66
+ } catch (e) {
67
+ error = e;
68
+ }
69
+ expect(error).to.exist;
70
+ expect(error.message).to.include('serverTime');
71
+ });
72
+ });
73
+
74
+ describe('[CSCX] Service getter', function () {
75
+ it('[CSCA] creates service when not provided', function () {
76
+ const conn2 = new pryv.Connection(testData.apiEndpoint);
77
+ const service = conn2.service;
78
+ expect(service).to.exist;
79
+ // Second access returns same instance
80
+ expect(conn2.service).to.equal(service);
81
+ });
82
+
83
+ it('[CSCB] uses provided service', async function () {
84
+ const service = new pryv.Service(testData.serviceInfoUrl);
85
+ await service.info();
86
+ const conn2 = new pryv.Connection(testData.apiEndpoint, service);
87
+ expect(conn2.service).to.equal(service);
88
+ });
89
+ });
90
+
91
+ describe('[CGEX] get() method', function () {
92
+ it('[CGEA] get() without query params', async function () {
93
+ const result = await conn.get('access-info');
94
+ expect(result).to.exist;
95
+ });
96
+
97
+ it('[CGEB] get() with null query params', async function () {
98
+ const result = await conn.get('access-info', null);
99
+ expect(result).to.exist;
100
+ });
101
+ });
102
+ });