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/test/Service.test.js
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/* global describe, it, before, expect, pryv, testData */
|
|
6
6
|
|
|
7
|
-
describe('Service', function () {
|
|
7
|
+
describe('[SERX] Service', function () {
|
|
8
8
|
before(async function () {
|
|
9
9
|
this.timeout(15000);
|
|
10
10
|
await testData.prepare();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
it('info()', async () => {
|
|
13
|
+
it('[SERA] info()', async () => {
|
|
14
14
|
const pryvService = new pryv.Service(testData.serviceInfoUrl);
|
|
15
15
|
const res = await pryvService.info();
|
|
16
16
|
expect(res).to.exist;
|
|
@@ -22,7 +22,7 @@ describe('Service', function () {
|
|
|
22
22
|
});
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
it('info() 2x ', async () => {
|
|
25
|
+
it('[SERB] info() 2x ', async () => {
|
|
26
26
|
const pryvService = new pryv.Service(testData.serviceInfoUrl);
|
|
27
27
|
const res = await pryvService.info();
|
|
28
28
|
expect(res).to.exist;
|
|
@@ -32,7 +32,7 @@ describe('Service', function () {
|
|
|
32
32
|
expect(res2.access).to.exist;
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
it('login()', async function () {
|
|
35
|
+
it('[SERC] login()', async function () {
|
|
36
36
|
this.timeout(15000);
|
|
37
37
|
const pryvService = new pryv.Service(testData.serviceInfoUrl);
|
|
38
38
|
const conn = await pryvService.login(testData.username, testData.password, 'jslib-test');
|
|
@@ -41,7 +41,7 @@ describe('Service', function () {
|
|
|
41
41
|
expect(conn.endpoint).to.exist;
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
it('assets()', async function () {
|
|
44
|
+
it('[SERD] assets()', async function () {
|
|
45
45
|
const pryvService = new pryv.Service(null, testData.serviceInfo);
|
|
46
46
|
const assets = await pryvService.assets();
|
|
47
47
|
expect(assets).to.exist;
|
|
@@ -51,13 +51,13 @@ describe('Service', function () {
|
|
|
51
51
|
expect(assets).to.equal(assets2);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
describe('Errors', async function () {
|
|
55
|
-
it('Throw error with invalid content', async () => {
|
|
54
|
+
describe('[SEEX] Errors', async function () {
|
|
55
|
+
it('[SEEA] Throw error with invalid content', async () => {
|
|
56
56
|
const service = new pryv.Service(null, {});
|
|
57
57
|
await expect(service.info()).to.be.rejectedWith('Invalid data from service/info');
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
it('Warn if no assets', async () => {
|
|
60
|
+
it('[SEEB] Warn if no assets', async () => {
|
|
61
61
|
const serviceInfoCopy = Object.assign({}, testData.serviceInfo);
|
|
62
62
|
delete serviceInfoCopy.assets;
|
|
63
63
|
const pryvService = new pryv.Service(null, serviceInfoCopy);
|
|
@@ -65,13 +65,13 @@ describe('Service', function () {
|
|
|
65
65
|
expect(assets).to.be.null;
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
it('login() failed on wrong password', async function () {
|
|
68
|
+
it('[SEEC] login() failed on wrong password', async function () {
|
|
69
69
|
this.timeout(15000);
|
|
70
70
|
const pryvService = new pryv.Service(testData.serviceInfoUrl);
|
|
71
71
|
await expect(pryvService.login(testData.username, 'bobby', 'jslib-test')).to.be.rejectedWith('The given username/password pair is invalid.');
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it('login() failed on wrong username', async function () {
|
|
74
|
+
it('[SEED] login() failed on wrong username', async function () {
|
|
75
75
|
this.timeout(15000);
|
|
76
76
|
const pryvService = new pryv.Service(testData.serviceInfoUrl);
|
|
77
77
|
// check if username is in path or domain
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/* global describe, it, before, after, expect, JSDOM, pryv, testData */
|
|
6
6
|
|
|
7
|
-
describe('ServiceAssets', function () {
|
|
7
|
+
describe('[ASTX] ServiceAssets', function () {
|
|
8
8
|
let cleanupDom = false;
|
|
9
9
|
|
|
10
10
|
before(async function () {
|
|
@@ -28,19 +28,19 @@ describe('ServiceAssets', function () {
|
|
|
28
28
|
delete global.location;
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
it('relativeURL()', async () => {
|
|
31
|
+
it('[ASTA] relativeURL()', async () => {
|
|
32
32
|
const pryvService = new pryv.Service(null, testData.serviceInfo);
|
|
33
33
|
const assets = await pryvService.assets();
|
|
34
34
|
expect(assets.relativeURL('./toto')).to.eql(testData.serviceInfo.assets.definitions.replace('index.json', 'toto'));
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
it('setAllDefaults()', async () => {
|
|
37
|
+
it('[ASTB] setAllDefaults()', async () => {
|
|
38
38
|
const pryvService = new pryv.Service(null, testData.serviceInfo);
|
|
39
39
|
const assets = await pryvService.assets();
|
|
40
40
|
await assets.setAllDefaults();
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
it('Load all external elements', async () => {
|
|
43
|
+
it('[ASTC] Load all external elements', async () => {
|
|
44
44
|
const pryvService = new pryv.Service(null, testData.serviceInfo);
|
|
45
45
|
const assets = await pryvService.assets();
|
|
46
46
|
|
|
@@ -49,21 +49,21 @@ describe('ServiceAssets', function () {
|
|
|
49
49
|
await assets.loginButtonGetMessages();
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
it('.get() returns all assets', async () => {
|
|
52
|
+
it('[ASTD] .get() returns all assets', async () => {
|
|
53
53
|
const pryvService = new pryv.Service(null, testData.serviceInfo);
|
|
54
54
|
const assets = await pryvService.assets();
|
|
55
55
|
const allAssets = await assets.get();
|
|
56
56
|
expect(allAssets.favicon.default.url).to.eql('favicon.ico');
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
it('.get(keyPath) ', async () => {
|
|
59
|
+
it('[ASTE] .get(keyPath) ', async () => {
|
|
60
60
|
const pryvService = new pryv.Service(null, testData.serviceInfo);
|
|
61
61
|
const assets = await pryvService.assets();
|
|
62
62
|
const faviconUrl = await assets.get('favicon:default:url');
|
|
63
63
|
expect(faviconUrl).to.eql('favicon.ico');
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
it('.getUrl(keyPath) ', async () => {
|
|
66
|
+
it('[ASTF] .getUrl(keyPath) ', async () => {
|
|
67
67
|
const pryvService = new pryv.Service(null, testData.serviceInfo);
|
|
68
68
|
const assets = await pryvService.assets();
|
|
69
69
|
const faviconUrl = await assets.getUrl('favicon:default:url');
|
|
@@ -0,0 +1,135 @@
|
|
|
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 suffix = cuid().slice(0, 8);
|
|
11
|
+
const testStreamId = 'str-' + suffix;
|
|
12
|
+
const childStreamId = 'str-child-' + suffix;
|
|
13
|
+
const testStreamName = 'Test Stream ' + suffix;
|
|
14
|
+
const childStreamName = 'Child Stream ' + suffix;
|
|
15
|
+
|
|
16
|
+
describe('[STRX] Streams', () => {
|
|
17
|
+
before(async function () {
|
|
18
|
+
this.timeout(15000);
|
|
19
|
+
await testData.prepare();
|
|
20
|
+
conn = new pryv.Connection(testData.apiEndpointWithToken);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('[SCRX] streams.create', function () {
|
|
24
|
+
it('[SCRA] create a root stream', async () => {
|
|
25
|
+
const res = await conn.api([{
|
|
26
|
+
method: 'streams.create',
|
|
27
|
+
params: { id: testStreamId, name: testStreamName }
|
|
28
|
+
}]);
|
|
29
|
+
expect(res[0]).to.exist;
|
|
30
|
+
expect(res[0].stream).to.exist;
|
|
31
|
+
expect(res[0].stream.id).to.equal(testStreamId);
|
|
32
|
+
expect(res[0].stream.name).to.equal(testStreamName);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('[SCRB] create a child stream', async () => {
|
|
36
|
+
const res = await conn.api([{
|
|
37
|
+
method: 'streams.create',
|
|
38
|
+
params: { id: childStreamId, name: childStreamName, parentId: testStreamId }
|
|
39
|
+
}]);
|
|
40
|
+
expect(res[0]).to.exist;
|
|
41
|
+
expect(res[0].stream).to.exist;
|
|
42
|
+
expect(res[0].stream.parentId).to.equal(testStreamId);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('[SCRC] reject duplicate stream id', async () => {
|
|
46
|
+
const res = await conn.api([{
|
|
47
|
+
method: 'streams.create',
|
|
48
|
+
params: { id: testStreamId, name: 'Duplicate ' + suffix }
|
|
49
|
+
}]);
|
|
50
|
+
expect(res[0]).to.exist;
|
|
51
|
+
expect(res[0].error).to.exist;
|
|
52
|
+
expect(res[0].error.id).to.equal('item-already-exists');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('[SGTX] streams.get', function () {
|
|
57
|
+
it('[SGTA] get all streams', async () => {
|
|
58
|
+
const res = await conn.api([{
|
|
59
|
+
method: 'streams.get',
|
|
60
|
+
params: {}
|
|
61
|
+
}]);
|
|
62
|
+
expect(res[0]).to.exist;
|
|
63
|
+
expect(res[0].streams).to.exist;
|
|
64
|
+
expect(Array.isArray(res[0].streams)).to.equal(true);
|
|
65
|
+
expect(res[0].streams.length).to.be.gt(0);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('[SGTB] get stream tree includes parent and child', async () => {
|
|
69
|
+
const res = await conn.api([{
|
|
70
|
+
method: 'streams.get',
|
|
71
|
+
params: {}
|
|
72
|
+
}]);
|
|
73
|
+
const streams = res[0].streams;
|
|
74
|
+
const parent = findStream(streams, testStreamId);
|
|
75
|
+
expect(parent).to.exist;
|
|
76
|
+
expect(parent.children).to.exist;
|
|
77
|
+
const child = parent.children.find(s => s.id === childStreamId);
|
|
78
|
+
expect(child).to.exist;
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('[SUPX] streams.update', function () {
|
|
83
|
+
it('[SUPA] rename a stream', async () => {
|
|
84
|
+
const res = await conn.api([{
|
|
85
|
+
method: 'streams.update',
|
|
86
|
+
params: { id: childStreamId, update: { name: 'Renamed ' + suffix } }
|
|
87
|
+
}]);
|
|
88
|
+
expect(res[0]).to.exist;
|
|
89
|
+
expect(res[0].stream).to.exist;
|
|
90
|
+
expect(res[0].stream.name).to.equal('Renamed ' + suffix);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('[SDLX] streams.delete', function () {
|
|
95
|
+
it('[SDLA] trash a stream (first delete)', async () => {
|
|
96
|
+
const res = await conn.api([{
|
|
97
|
+
method: 'streams.delete',
|
|
98
|
+
params: { id: childStreamId }
|
|
99
|
+
}]);
|
|
100
|
+
expect(res[0]).to.exist;
|
|
101
|
+
expect(res[0].stream).to.exist;
|
|
102
|
+
expect(res[0].stream.trashed).to.equal(true);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('[SDLB] delete a trashed stream (second delete)', async () => {
|
|
106
|
+
const res = await conn.api([{
|
|
107
|
+
method: 'streams.delete',
|
|
108
|
+
params: { id: childStreamId }
|
|
109
|
+
}]);
|
|
110
|
+
expect(res[0]).to.exist;
|
|
111
|
+
// After second delete, stream is gone
|
|
112
|
+
expect(res[0].streamDeletion).to.exist;
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Cleanup parent stream
|
|
117
|
+
after(async () => {
|
|
118
|
+
if (!conn) return;
|
|
119
|
+
await conn.api([
|
|
120
|
+
{ method: 'streams.delete', params: { id: testStreamId } },
|
|
121
|
+
{ method: 'streams.delete', params: { id: testStreamId } }
|
|
122
|
+
]);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
function findStream (streams, id) {
|
|
127
|
+
for (const s of streams) {
|
|
128
|
+
if (s.id === id) return s;
|
|
129
|
+
if (s.children) {
|
|
130
|
+
const found = findStream(s.children, id);
|
|
131
|
+
if (found) return found;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
|
|
4
|
+
*/
|
|
5
|
+
/* global describe, it, expect */
|
|
6
|
+
|
|
7
|
+
const buildSearchParams = require('../src/lib/buildSearchParams');
|
|
8
|
+
|
|
9
|
+
describe('[BSPX] buildSearchParams', function () {
|
|
10
|
+
it('[BSPA] builds params from simple object', function () {
|
|
11
|
+
const result = buildSearchParams({ foo: 'bar', num: 123 });
|
|
12
|
+
expect(result).to.equal('foo=bar&num=123');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('[BSPB] handles arrays as repeated keys', function () {
|
|
16
|
+
const result = buildSearchParams({ tags: ['a', 'b', 'c'] });
|
|
17
|
+
expect(result).to.equal('tags=a&tags=b&tags=c');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('[BSPC] handles mixed arrays and values', function () {
|
|
21
|
+
const result = buildSearchParams({
|
|
22
|
+
name: 'test',
|
|
23
|
+
ids: ['id1', 'id2'],
|
|
24
|
+
limit: 10
|
|
25
|
+
});
|
|
26
|
+
expect(result).to.include('name=test');
|
|
27
|
+
expect(result).to.include('ids=id1');
|
|
28
|
+
expect(result).to.include('ids=id2');
|
|
29
|
+
expect(result).to.include('limit=10');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('[BSPD] ignores null and undefined values', function () {
|
|
33
|
+
const result = buildSearchParams({
|
|
34
|
+
valid: 'yes',
|
|
35
|
+
nullVal: null,
|
|
36
|
+
undefVal: undefined
|
|
37
|
+
});
|
|
38
|
+
expect(result).to.equal('valid=yes');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('[BSPE] handles empty object', function () {
|
|
42
|
+
const result = buildSearchParams({});
|
|
43
|
+
expect(result).to.equal('');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('[BSPF] encodes special characters', function () {
|
|
47
|
+
const result = buildSearchParams({ query: 'hello world', special: 'a=b&c=d' });
|
|
48
|
+
expect(result).to.include('query=hello+world');
|
|
49
|
+
expect(result).to.include('special=a%3Db%26c%3Dd');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('[BSPG] handles boolean values', function () {
|
|
53
|
+
const result = buildSearchParams({ active: true, disabled: false });
|
|
54
|
+
expect(result).to.equal('active=true&disabled=false');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('[BSPH] handles empty arrays', function () {
|
|
58
|
+
const result = buildSearchParams({ tags: [], name: 'test' });
|
|
59
|
+
expect(result).to.equal('name=test');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
|
|
4
|
+
*/
|
|
5
|
+
/* global describe, it, expect */
|
|
6
|
+
|
|
7
|
+
const jsonParser = require('../src/lib/json-parser');
|
|
8
|
+
const { EventEmitter } = require('events');
|
|
9
|
+
|
|
10
|
+
// Helper to create a mock response stream
|
|
11
|
+
function createMockResponse (chunks) {
|
|
12
|
+
const emitter = new EventEmitter();
|
|
13
|
+
emitter.setEncoding = function () {};
|
|
14
|
+
|
|
15
|
+
// Emit chunks asynchronously
|
|
16
|
+
setTimeout(() => {
|
|
17
|
+
chunks.forEach(chunk => emitter.emit('data', chunk));
|
|
18
|
+
emitter.emit('end');
|
|
19
|
+
}, 0);
|
|
20
|
+
|
|
21
|
+
return emitter;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe('[JPSX] json-parser', function () {
|
|
25
|
+
it('[JPSA] parses single event correctly', function (done) {
|
|
26
|
+
const events = [];
|
|
27
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
28
|
+
|
|
29
|
+
const jsonData = '{"events":[{"id":"evt1","type":"note/txt"}],"meta":{"serverTime":1234567890}}';
|
|
30
|
+
const mockRes = createMockResponse([jsonData]);
|
|
31
|
+
mockRes.statusCode = 200;
|
|
32
|
+
|
|
33
|
+
parser(mockRes, (err, body) => {
|
|
34
|
+
expect(err).to.be.undefined;
|
|
35
|
+
expect(events).to.have.lengthOf(1);
|
|
36
|
+
expect(events[0].id).to.equal('evt1');
|
|
37
|
+
expect(body.eventsCount).to.equal(1);
|
|
38
|
+
done();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('[JPSB] parses multiple events', function (done) {
|
|
43
|
+
const events = [];
|
|
44
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
45
|
+
|
|
46
|
+
const jsonData = '{"events":[{"id":"e1"},{"id":"e2"},{"id":"e3"}],"meta":{"serverTime":123}}';
|
|
47
|
+
const mockRes = createMockResponse([jsonData]);
|
|
48
|
+
mockRes.statusCode = 200;
|
|
49
|
+
|
|
50
|
+
parser(mockRes, (err, body) => {
|
|
51
|
+
expect(err).to.be.undefined;
|
|
52
|
+
expect(events).to.have.lengthOf(3);
|
|
53
|
+
expect(body.eventsCount).to.equal(3);
|
|
54
|
+
done();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('[JPSC] handles chunked data', function (done) {
|
|
59
|
+
const events = [];
|
|
60
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
61
|
+
|
|
62
|
+
// Split JSON across multiple chunks
|
|
63
|
+
const chunks = [
|
|
64
|
+
'{"events":[{"id":"ev',
|
|
65
|
+
'1","type":"test"},{"i',
|
|
66
|
+
'd":"ev2"}],"meta":{"serverTime":1}}'
|
|
67
|
+
];
|
|
68
|
+
const mockRes = createMockResponse(chunks);
|
|
69
|
+
mockRes.statusCode = 200;
|
|
70
|
+
|
|
71
|
+
parser(mockRes, (err, body) => {
|
|
72
|
+
expect(err).to.be.undefined;
|
|
73
|
+
expect(events).to.have.lengthOf(2);
|
|
74
|
+
expect(events[0].id).to.equal('ev1');
|
|
75
|
+
expect(events[1].id).to.equal('ev2');
|
|
76
|
+
done();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('[JPSD] handles empty events array', function (done) {
|
|
81
|
+
const events = [];
|
|
82
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
83
|
+
|
|
84
|
+
const jsonData = '{"events":[],"meta":{"serverTime":123}}';
|
|
85
|
+
const mockRes = createMockResponse([jsonData]);
|
|
86
|
+
mockRes.statusCode = 200;
|
|
87
|
+
|
|
88
|
+
parser(mockRes, (err, body) => {
|
|
89
|
+
expect(err).to.be.undefined;
|
|
90
|
+
expect(events).to.have.lengthOf(0);
|
|
91
|
+
expect(body.eventsCount).to.equal(0);
|
|
92
|
+
done();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('[JPSE] handles events with nested objects', function (done) {
|
|
97
|
+
const events = [];
|
|
98
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
99
|
+
|
|
100
|
+
const jsonData = '{"events":[{"id":"e1","content":{"nested":{"deep":"value"}}}],"meta":{"serverTime":1}}';
|
|
101
|
+
const mockRes = createMockResponse([jsonData]);
|
|
102
|
+
mockRes.statusCode = 200;
|
|
103
|
+
|
|
104
|
+
parser(mockRes, (err, body) => {
|
|
105
|
+
expect(err).to.be.undefined;
|
|
106
|
+
expect(events).to.have.lengthOf(1);
|
|
107
|
+
expect(events[0].content.nested.deep).to.equal('value');
|
|
108
|
+
done();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('[JPSF] handles events with strings containing special chars', function (done) {
|
|
113
|
+
const events = [];
|
|
114
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
115
|
+
|
|
116
|
+
const jsonData = '{"events":[{"id":"e1","content":"line1\\nline2\\twith\\\\backslash"}],"meta":{"serverTime":1}}';
|
|
117
|
+
const mockRes = createMockResponse([jsonData]);
|
|
118
|
+
mockRes.statusCode = 200;
|
|
119
|
+
|
|
120
|
+
parser(mockRes, (err, body) => {
|
|
121
|
+
expect(err).to.be.undefined;
|
|
122
|
+
expect(events).to.have.lengthOf(1);
|
|
123
|
+
expect(events[0].content).to.include('line1');
|
|
124
|
+
done();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('[JPSG] includes eventDeletions when includeDeletions is true', function (done) {
|
|
129
|
+
const events = [];
|
|
130
|
+
const parser = jsonParser((event) => events.push(event), true);
|
|
131
|
+
|
|
132
|
+
// Split data into chunks to simulate real HTTP streaming
|
|
133
|
+
// The parser needs multiple data events to process state transitions correctly
|
|
134
|
+
const chunks = [
|
|
135
|
+
'{"events":[{"id":"e1"}]',
|
|
136
|
+
',"eventDeletions":[{"id":"del1"}]',
|
|
137
|
+
',"meta":{"serverTime":1}}'
|
|
138
|
+
];
|
|
139
|
+
const mockRes = createMockResponse(chunks);
|
|
140
|
+
mockRes.statusCode = 200;
|
|
141
|
+
|
|
142
|
+
parser(mockRes, (err, body) => {
|
|
143
|
+
expect(err).to.be.undefined;
|
|
144
|
+
expect(events).to.have.lengthOf(2);
|
|
145
|
+
expect(body.eventsCount).to.equal(1);
|
|
146
|
+
expect(body.eventDeletionsCount).to.equal(1);
|
|
147
|
+
done();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('[JPSH] handles invalid JSON gracefully', function (done) {
|
|
152
|
+
const events = [];
|
|
153
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
154
|
+
|
|
155
|
+
const jsonData = 'not valid json';
|
|
156
|
+
const mockRes = createMockResponse([jsonData]);
|
|
157
|
+
mockRes.statusCode = 200;
|
|
158
|
+
|
|
159
|
+
parser(mockRes, (err, body) => {
|
|
160
|
+
expect(err).to.exist;
|
|
161
|
+
expect(err.rawResponse).to.exist;
|
|
162
|
+
expect(err.statusCode).to.equal(200);
|
|
163
|
+
done();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('[JPSI] handles events with quoted strings containing brackets', function (done) {
|
|
168
|
+
const events = [];
|
|
169
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
170
|
+
|
|
171
|
+
const jsonData = '{"events":[{"id":"e1","content":"text with {braces} and [brackets]"}],"meta":{"serverTime":1}}';
|
|
172
|
+
const mockRes = createMockResponse([jsonData]);
|
|
173
|
+
mockRes.statusCode = 200;
|
|
174
|
+
|
|
175
|
+
parser(mockRes, (err, body) => {
|
|
176
|
+
expect(err).to.be.undefined;
|
|
177
|
+
expect(events).to.have.lengthOf(1);
|
|
178
|
+
expect(events[0].content).to.include('{braces}');
|
|
179
|
+
done();
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('[JPSJ] preserves meta and other root properties', function (done) {
|
|
184
|
+
const events = [];
|
|
185
|
+
const parser = jsonParser((event) => events.push(event), false);
|
|
186
|
+
|
|
187
|
+
const jsonData = '{"someProperty":"value","events":[{"id":"e1"}],"meta":{"serverTime":123,"apiVersion":"1.2.3"}}';
|
|
188
|
+
const mockRes = createMockResponse([jsonData]);
|
|
189
|
+
mockRes.statusCode = 200;
|
|
190
|
+
|
|
191
|
+
parser(mockRes, (err, body) => {
|
|
192
|
+
expect(err).to.be.undefined;
|
|
193
|
+
expect(body.someProperty).to.equal('value');
|
|
194
|
+
expect(body.meta.apiVersion).to.equal('1.2.3');
|
|
195
|
+
done();
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
package/test/utils.test.js
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/* global describe, it, before, expect, pryv, testData */
|
|
6
6
|
|
|
7
|
-
describe('utils', function () {
|
|
7
|
+
describe('[UTLX] utils', function () {
|
|
8
8
|
before(async function () {
|
|
9
9
|
this.timeout(15000);
|
|
10
10
|
await testData.prepare();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
it('extractTokenAndAPIEndpoint', function (done) {
|
|
13
|
+
it('[UTLA] extractTokenAndAPIEndpoint', function (done) {
|
|
14
14
|
const tokenAndAPI = pryv.utils
|
|
15
15
|
.extractTokenAndAPIEndpoint(testData.apiEndpointWithToken);
|
|
16
16
|
expect(testData.token).to.equal(tokenAndAPI.token);
|
|
@@ -19,7 +19,7 @@ describe('utils', function () {
|
|
|
19
19
|
done();
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
it('extractTokenAndAPIEndpoint should work without token', function (done) {
|
|
22
|
+
it('[UTLB] extractTokenAndAPIEndpoint should work without token', function (done) {
|
|
23
23
|
const tokenAndAPI = pryv.utils
|
|
24
24
|
.extractTokenAndAPIEndpoint(testData.apiEndpoint);
|
|
25
25
|
|
|
@@ -29,7 +29,7 @@ describe('utils', function () {
|
|
|
29
29
|
done();
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
it('extractTokenAndAPIEndpoint should fail on invalid url', function (done) {
|
|
32
|
+
it('[UTLC] extractTokenAndAPIEndpoint should fail on invalid url', function (done) {
|
|
33
33
|
let error = null;
|
|
34
34
|
try {
|
|
35
35
|
pryv.utils.extractTokenAndAPIEndpoint('blip');
|
|
@@ -40,7 +40,7 @@ describe('utils', function () {
|
|
|
40
40
|
expect(error).to.exist;
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
it('buildAPIEndpoint with token', function (done) {
|
|
43
|
+
it('[UTLD] buildAPIEndpoint with token', function (done) {
|
|
44
44
|
const apiEndpoint = pryv.utils
|
|
45
45
|
.buildAPIEndpoint({
|
|
46
46
|
token: testData.token,
|
|
@@ -50,7 +50,7 @@ describe('utils', function () {
|
|
|
50
50
|
done();
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
it('buildAPIEndpoint without token', function (done) {
|
|
53
|
+
it('[UTLE] buildAPIEndpoint without token', function (done) {
|
|
54
54
|
const apiEndpoint = pryv.utils
|
|
55
55
|
.buildAPIEndpoint({
|
|
56
56
|
token: null,
|