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 +1 -1
- package/src/Connection.js +2 -1
- package/src/lib/buildSearchParams.js +26 -0
- package/src/lib/getEventStreamed.js +4 -2
- package/src/utils.js +2 -1
- package/test/Accesses.test.js +126 -0
- package/test/Account.test.js +73 -0
- package/test/AuthController.test.js +193 -0
- package/test/Browser.AuthController.test.js +4 -4
- package/test/Browser.test.js +3 -3
- package/test/Connection.edge-cases.test.js +102 -0
- package/test/Connection.test.js +88 -43
- package/test/CookieUtils.test.js +69 -0
- package/test/LoginButton.test.js +196 -0
- package/test/LoginMessages.test.js +48 -0
- package/test/PryvError.test.js +40 -0
- package/test/Service.test.js +10 -10
- package/test/ServiceAssets.test.js +7 -7
- package/test/Streams.test.js +135 -0
- package/test/buildSearchParams.test.js +61 -0
- package/test/json-parser.test.js +198 -0
- package/test/utils.test.js +6 -6
package/package.json
CHANGED
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 = '?' +
|
|
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 =
|
|
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 = '?' +
|
|
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
|
|
package/test/Browser.test.js
CHANGED
|
@@ -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
|
+
});
|