pryv 3.5.0 → 3.6.1
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/README.md +9 -1
- package/package.json +1 -1
- package/src/Browser/LoginButton.js +5 -0
- package/src/Connection.js +39 -0
- package/src/Service.js +17 -4
- package/src/index.d.ts +29 -14
- package/src/lib/buildSearchParams.js +14 -4
- package/src/lib/getEventStreamed.js +1 -0
- package/src/lib/resolveDotPath.js +25 -0
- package/test/ContentQueries.test.js +95 -0
- package/test/LoginButton.urlCleanup.test.js +44 -0
package/README.md
CHANGED
|
@@ -733,7 +733,15 @@ Assuming browser files are built and everything is up-to-date, including the REA
|
|
|
733
733
|
```
|
|
734
734
|
just version <version>
|
|
735
735
|
```
|
|
736
|
-
to update the version number of the lib and add-ons in lockstep
|
|
736
|
+
to update the version number of the lib and add-ons in lockstep. This only edits the `package.json` files — **commit and tag manually**:
|
|
737
|
+
|
|
738
|
+
```
|
|
739
|
+
git commit -am "<version>"
|
|
740
|
+
git tag -a <version> -m "<version>"
|
|
741
|
+
git push && git push --tags
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
Tags are bare version numbers (e.g. `3.6.0`, no `v` prefix); every npm publish must have a matching pushed tag so npm, `package.json` and GitHub stay cross-checkable.
|
|
737
745
|
|
|
738
746
|
```
|
|
739
747
|
just publish-npm
|
package/package.json
CHANGED
|
@@ -126,6 +126,11 @@ class LoginButton {
|
|
|
126
126
|
error: e
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
|
+
// The prYv* params are one-shot; leaving them in the visible URL
|
|
130
|
+
// puts stale auth state into bookmarks / copied links.
|
|
131
|
+
if (window.history && typeof window.history.replaceState === 'function') {
|
|
132
|
+
window.history.replaceState(null, '', utils.cleanURLFromPrYvParams(url));
|
|
133
|
+
}
|
|
129
134
|
}
|
|
130
135
|
|
|
131
136
|
function retrievePollUrl (url) {
|
package/src/Connection.js
CHANGED
|
@@ -8,6 +8,7 @@ const libGetEventStreamed = require('./lib/getEventStreamed');
|
|
|
8
8
|
const PryvError = require('./lib/PryvError');
|
|
9
9
|
const StaleAccessIdError = require('./lib/StaleAccessIdError');
|
|
10
10
|
const buildSearchParams = require('./lib/buildSearchParams');
|
|
11
|
+
const resolveDotPath = require('./lib/resolveDotPath');
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @class Connection
|
|
@@ -350,6 +351,44 @@ class Connection {
|
|
|
350
351
|
return res.body;
|
|
351
352
|
}
|
|
352
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Get the latest event per value for a content path — typical form-prefill
|
|
356
|
+
* lookup ("latest assertion per code"). Queries `events.get` with a
|
|
357
|
+
* `content` condition `{ path, in: values }` (server must support content
|
|
358
|
+
* queries — see `Service.supportsContentQueries()`), pages through the
|
|
359
|
+
* time-descending result and keeps the first (= latest) event per value.
|
|
360
|
+
* Handles paging internally, so the result is correct regardless of the
|
|
361
|
+
* default `events.get` page size.
|
|
362
|
+
* @param {string} path - dot-path into `content` (or `$` for the root value)
|
|
363
|
+
* @param {Array<string|number|boolean>} values - values to look up (one Map entry max per value)
|
|
364
|
+
* @param {Object} [baseQuery] - additional `events.get` params (e.g. `streams`, `types`, `fromTime`); passed through
|
|
365
|
+
* @returns {Promise<Map<string|number|boolean, Object>>} value → latest matching event; values with no match are absent
|
|
366
|
+
*/
|
|
367
|
+
async getLatestByContent (path, values, baseQuery = {}) {
|
|
368
|
+
const PAGE_LIMIT = 1000;
|
|
369
|
+
const lookup = new Set(values);
|
|
370
|
+
const found = new Map();
|
|
371
|
+
const condition = { path, in: [...lookup] };
|
|
372
|
+
const content = (baseQuery.content || []).concat([condition]);
|
|
373
|
+
let skip = 0;
|
|
374
|
+
while (found.size < lookup.size) {
|
|
375
|
+
const params = Object.assign({}, baseQuery, {
|
|
376
|
+
content,
|
|
377
|
+
sortAscending: false,
|
|
378
|
+
skip,
|
|
379
|
+
limit: PAGE_LIMIT
|
|
380
|
+
});
|
|
381
|
+
const events = await this.apiOne('events.get', params, 'events');
|
|
382
|
+
for (const event of events) {
|
|
383
|
+
const value = resolveDotPath(event.content, path);
|
|
384
|
+
if (lookup.has(value) && !found.has(value)) found.set(value, event);
|
|
385
|
+
}
|
|
386
|
+
if (events.length < PAGE_LIMIT) break;
|
|
387
|
+
skip += events.length;
|
|
388
|
+
}
|
|
389
|
+
return found;
|
|
390
|
+
}
|
|
391
|
+
|
|
353
392
|
/**
|
|
354
393
|
* Create an event with attached file
|
|
355
394
|
* NODE.jS ONLY
|
package/src/Service.js
CHANGED
|
@@ -80,6 +80,17 @@ class Service {
|
|
|
80
80
|
return (infos.features == null || infos.features.noHF !== true);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Whether the platform supports `events.get` content/clientData query
|
|
85
|
+
* conditions (`features.contentQueries` in service info). Older platforms
|
|
86
|
+
* reject the parameters with a 400 — use this to pick a fallback path.
|
|
87
|
+
* @returns {Promise<boolean>}
|
|
88
|
+
*/
|
|
89
|
+
async supportsContentQueries () {
|
|
90
|
+
const infos = await this.info();
|
|
91
|
+
return infos.features != null && infos.features.contentQueries === true;
|
|
92
|
+
}
|
|
93
|
+
|
|
83
94
|
/**
|
|
84
95
|
* Check if a service has username in the hostname or in the path of the API.
|
|
85
96
|
* @returns {Promise<boolean>} Promise resolving to true if the service does not rely on DNS to find a host related to a username
|
|
@@ -395,9 +406,9 @@ class Service {
|
|
|
395
406
|
email: opts.email,
|
|
396
407
|
hosting,
|
|
397
408
|
language,
|
|
398
|
-
invitationToken
|
|
409
|
+
invitationToken,
|
|
410
|
+
...(opts.referer != null && { referer: opts.referer })
|
|
399
411
|
};
|
|
400
|
-
if (opts.referer != null) payload.referer = opts.referer;
|
|
401
412
|
} else {
|
|
402
413
|
url = serviceInfo.register + 'user';
|
|
403
414
|
payload = {
|
|
@@ -407,9 +418,9 @@ class Service {
|
|
|
407
418
|
email: opts.email,
|
|
408
419
|
hosting,
|
|
409
420
|
languageCode: language,
|
|
410
|
-
invitationtoken: invitationToken
|
|
421
|
+
invitationtoken: invitationToken,
|
|
422
|
+
...(opts.referer != null && { referer: opts.referer })
|
|
411
423
|
};
|
|
412
|
-
if (opts.referer != null) payload.referer = opts.referer;
|
|
413
424
|
}
|
|
414
425
|
const { response, body } = await utils.fetchPost(url, payload);
|
|
415
426
|
if (!response.ok) throw PryvError.fromApiResponse(response, body);
|
|
@@ -618,8 +629,10 @@ const Connection = require('./Connection');
|
|
|
618
629
|
* @property {string} support The email or URL of the support page.
|
|
619
630
|
* @property {string} terms The terms and conditions, in plain text or the URL displaying them.
|
|
620
631
|
* @property {string} eventTypes The URL of the list of validated event types.
|
|
632
|
+
* @property {string} [version] The platform version.
|
|
621
633
|
* @property {Object} [assets] Holder for service specific Assets (icons, css, ...)
|
|
622
634
|
* @property {string} [assets.definitions] URL to json object with assets definitions
|
|
623
635
|
* @property {Object} [features] Platform feature flags
|
|
624
636
|
* @property {boolean} [features.noHF] True if HF data is not supported
|
|
637
|
+
* @property {boolean} [features.contentQueries] True if events.get content/clientData query conditions are supported
|
|
625
638
|
*/
|
package/src/index.d.ts
CHANGED
|
@@ -100,20 +100,6 @@ declare module 'pryv' {
|
|
|
100
100
|
};
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
// HTTP only
|
|
104
|
-
type AuditLog = {
|
|
105
|
-
id: Identifier;
|
|
106
|
-
type: string;
|
|
107
|
-
time: Timestamp;
|
|
108
|
-
forwardedFor: string;
|
|
109
|
-
action: string;
|
|
110
|
-
query: string;
|
|
111
|
-
accessId: string;
|
|
112
|
-
status: number;
|
|
113
|
-
errorMessage?: string;
|
|
114
|
-
errorId?: string;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
103
|
export type HFSeries = {
|
|
118
104
|
format: 'flatJSON';
|
|
119
105
|
fields: string[];
|
|
@@ -267,6 +253,22 @@ declare module 'pryv' {
|
|
|
267
253
|
not?: Identifier[];
|
|
268
254
|
};
|
|
269
255
|
|
|
256
|
+
/**
|
|
257
|
+
* Condition on a JSON path of events' `content` or `clientData`.
|
|
258
|
+
* `path` is a dot-path (segments: [a-zA-Z0-9_:-]) or `$` for the root
|
|
259
|
+
* value; exactly one operator per condition. Conditions AND together.
|
|
260
|
+
* Server support is advertised by `features.contentQueries` (see
|
|
261
|
+
* `Service.supportsContentQueries()`).
|
|
262
|
+
*/
|
|
263
|
+
export type ContentQueryCondition = { path: string } & (
|
|
264
|
+
| { eq: string | number | boolean }
|
|
265
|
+
| { neq: string | number | boolean }
|
|
266
|
+
| { in: Array<string | number | boolean> }
|
|
267
|
+
| { exists: boolean }
|
|
268
|
+
| { gt: number } | { gte: number } | { lt: number } | { lte: number }
|
|
269
|
+
| { prefix: string }
|
|
270
|
+
);
|
|
271
|
+
|
|
270
272
|
export type EventQueryParams = {
|
|
271
273
|
fromTime: Timestamp;
|
|
272
274
|
toTime: Timestamp;
|
|
@@ -280,6 +282,8 @@ declare module 'pryv' {
|
|
|
280
282
|
state: 'default' | 'trashed' | 'all';
|
|
281
283
|
modifiedSince: Timestamp;
|
|
282
284
|
includeDeletion: boolean;
|
|
285
|
+
content: ContentQueryCondition[];
|
|
286
|
+
clientData: ContentQueryCondition[];
|
|
283
287
|
};
|
|
284
288
|
|
|
285
289
|
export type EventQueryParamsStreamQuery = Omit<EventQueryParams, 'streams'> & {
|
|
@@ -705,6 +709,15 @@ declare module 'pryv' {
|
|
|
705
709
|
queryParams: Partial<EventQueryParamsStreamQuery>,
|
|
706
710
|
forEachEvent: StreamedEventsHandler,
|
|
707
711
|
): Promise<StreamedEventsResult>;
|
|
712
|
+
/**
|
|
713
|
+
* Latest event per value for a content path (form-prefill lookup).
|
|
714
|
+
* Pages internally; requires server content-query support.
|
|
715
|
+
*/
|
|
716
|
+
getLatestByContent(
|
|
717
|
+
path: string,
|
|
718
|
+
values: Array<string | number | boolean>,
|
|
719
|
+
baseQuery?: Partial<EventQueryParamsStreamQuery>,
|
|
720
|
+
): Promise<Map<string | number | boolean, Event>>;
|
|
708
721
|
createEventWithFile(
|
|
709
722
|
params: EventFileCreationParams,
|
|
710
723
|
filePath: string | Buffer | Blob,
|
|
@@ -826,6 +839,8 @@ declare module 'pryv' {
|
|
|
826
839
|
): Promise<Connection>;
|
|
827
840
|
|
|
828
841
|
supportsHF(): Promise<boolean>;
|
|
842
|
+
/** Whether the platform supports events.get content/clientData query conditions. */
|
|
843
|
+
supportsContentQueries(): Promise<boolean>;
|
|
829
844
|
isDnsLess(): Promise<boolean>;
|
|
830
845
|
|
|
831
846
|
userExists(userId: string): Promise<boolean>;
|
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Build URL search params string from an object, properly handling arrays
|
|
8
|
-
*
|
|
7
|
+
* Build URL search params string from an object, properly handling arrays
|
|
8
|
+
* and structured values.
|
|
9
|
+
* - Arrays of scalars are expanded as repeated keys: { a: ['x', 'y'] } => 'a=x&a=y'
|
|
10
|
+
* - Arrays containing objects (e.g. `content` / `clientData` conditions,
|
|
11
|
+
* rich `streams` queries) and plain objects are sent as one
|
|
12
|
+
* JSON-encoded parameter, which the API parses back.
|
|
9
13
|
* @param {Object} params - Query parameters object
|
|
10
14
|
* @returns {string} - URL encoded query string
|
|
11
15
|
*/
|
|
@@ -13,9 +17,15 @@ function buildSearchParams (params) {
|
|
|
13
17
|
const searchParams = new URLSearchParams();
|
|
14
18
|
for (const [key, value] of Object.entries(params)) {
|
|
15
19
|
if (Array.isArray(value)) {
|
|
16
|
-
|
|
17
|
-
searchParams.append(key,
|
|
20
|
+
if (value.some((item) => item !== null && typeof item === 'object')) {
|
|
21
|
+
searchParams.append(key, JSON.stringify(value));
|
|
22
|
+
} else {
|
|
23
|
+
for (const item of value) {
|
|
24
|
+
searchParams.append(key, item);
|
|
25
|
+
}
|
|
18
26
|
}
|
|
27
|
+
} else if (value !== null && typeof value === 'object') {
|
|
28
|
+
searchParams.append(key, JSON.stringify(value));
|
|
19
29
|
} else if (value !== undefined && value !== null) {
|
|
20
30
|
searchParams.append(key, value);
|
|
21
31
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a content-query dot-path against a JSON value.
|
|
8
|
+
* `$` addresses the root value itself. Returns `undefined` when the path
|
|
9
|
+
* does not lead to a value.
|
|
10
|
+
* @param {*} root - The JSON value (typically an event's `content`)
|
|
11
|
+
* @param {string} path - Dot-path (e.g. 'drug.codes.atc') or '$'
|
|
12
|
+
* @returns {*} The value at the path, or undefined
|
|
13
|
+
*/
|
|
14
|
+
function resolveDotPath (root, path) {
|
|
15
|
+
if (path === '$') return root;
|
|
16
|
+
let current = root;
|
|
17
|
+
for (const segment of path.split('.')) {
|
|
18
|
+
if (current == null || typeof current !== 'object' || Array.isArray(current)) return undefined;
|
|
19
|
+
if (!Object.prototype.hasOwnProperty.call(current, segment)) return undefined;
|
|
20
|
+
current = current[segment];
|
|
21
|
+
}
|
|
22
|
+
return current;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = resolveDotPath;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
|
|
4
|
+
*/
|
|
5
|
+
/* global describe, it, before, expect, pryv */
|
|
6
|
+
|
|
7
|
+
const { createId: cuid } = require('@paralleldrive/cuid2');
|
|
8
|
+
const testData = require('../../../test/test-data');
|
|
9
|
+
|
|
10
|
+
const buildSearchParams = require('../src/lib/buildSearchParams');
|
|
11
|
+
const resolveDotPath = require('../src/lib/resolveDotPath');
|
|
12
|
+
|
|
13
|
+
describe('[CQLJ] Content queries', () => {
|
|
14
|
+
describe('[CQLU] buildSearchParams structured values', () => {
|
|
15
|
+
it('[LU01] keeps scalar arrays as repeated keys', () => {
|
|
16
|
+
expect(buildSearchParams({ a: ['x', 'y'], b: 1 })).to.equal('a=x&a=y&b=1');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('[LU02] JSON-encodes arrays of objects (conditions) as one parameter', () => {
|
|
20
|
+
const conditions = [{ path: 'drug.codes.atc', eq: 'G03DA04' }];
|
|
21
|
+
const out = buildSearchParams({ content: conditions });
|
|
22
|
+
expect(decodeURIComponent(out)).to.equal('content=' + JSON.stringify(conditions));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('[LU03] JSON-encodes plain object values', () => {
|
|
26
|
+
const out = buildSearchParams({ streams: { any: ['a'] } });
|
|
27
|
+
expect(decodeURIComponent(out.replace(/\+/g, ' '))).to.equal('streams=' + JSON.stringify({ any: ['a'] }));
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('[CQLR] resolveDotPath', () => {
|
|
32
|
+
it('[LR01] resolves nested paths, root $ and misses', () => {
|
|
33
|
+
const content = { drug: { codes: { atc: 'G03DA04' } }, taken: true };
|
|
34
|
+
expect(resolveDotPath(content, 'drug.codes.atc')).to.equal('G03DA04');
|
|
35
|
+
expect(resolveDotPath(content, 'taken')).to.equal(true);
|
|
36
|
+
expect(resolveDotPath(content, 'drug.codes.snomed')).to.equal(undefined);
|
|
37
|
+
expect(resolveDotPath(14.2, '$')).to.equal(14.2);
|
|
38
|
+
expect(resolveDotPath(undefined, 'a.b')).to.equal(undefined);
|
|
39
|
+
expect(resolveDotPath({ a: [1] }, 'a.0')).to.equal(undefined); // no array indices
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('[CQLI] against a live platform (skipped when unsupported)', () => {
|
|
44
|
+
let conn, supported, streamId;
|
|
45
|
+
const codes = { progesterone: 'G03DA04', aspirin: 'B01AC06', missing: 'N02BE01' };
|
|
46
|
+
|
|
47
|
+
before(async function () {
|
|
48
|
+
this.timeout(15000);
|
|
49
|
+
await testData.prepare();
|
|
50
|
+
conn = new pryv.Connection(testData.apiEndpointWithToken);
|
|
51
|
+
supported = await conn.service.supportsContentQueries();
|
|
52
|
+
if (!supported) return;
|
|
53
|
+
|
|
54
|
+
streamId = 'cq-' + cuid().substring(0, 8);
|
|
55
|
+
const calls = [{ method: 'streams.create', params: { id: streamId, name: 'CQ ' + streamId, parentId: 'data' } }];
|
|
56
|
+
// two assertions per drug — older taken:false, newer taken:true — to verify "latest"
|
|
57
|
+
let time = 1700000000;
|
|
58
|
+
for (const code of [codes.progesterone, codes.aspirin]) {
|
|
59
|
+
calls.push({ method: 'events.create', params: { streamIds: [streamId], type: 'medication/exposure-assertion-v1', time: time++, content: { drug: { codes: { atc: code } }, taken: false } } });
|
|
60
|
+
calls.push({ method: 'events.create', params: { streamIds: [streamId], type: 'medication/exposure-assertion-v1', time: time++, content: { drug: { codes: { atc: code } }, taken: true } } });
|
|
61
|
+
}
|
|
62
|
+
const res = await conn.api(calls);
|
|
63
|
+
for (const r of res) expect(r.error).to.be.undefined;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('[LI01] supportsContentQueries returns a boolean', async () => {
|
|
67
|
+
expect(typeof supported).to.equal('boolean');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('[LI02] events.get accepts content conditions via GET (streamed)', async function () {
|
|
71
|
+
if (!supported) this.skip();
|
|
72
|
+
const collected = [];
|
|
73
|
+
await conn.getEventsStreamed(
|
|
74
|
+
{ streams: [streamId], content: [{ path: 'drug.codes.atc', eq: codes.progesterone }, { path: 'taken', eq: true }] },
|
|
75
|
+
(event) => collected.push(event)
|
|
76
|
+
);
|
|
77
|
+
expect(collected.length).to.equal(1);
|
|
78
|
+
expect(collected[0].content.taken).to.equal(true);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('[LI03] getLatestByContent returns the latest event per value', async function () {
|
|
82
|
+
if (!supported) this.skip();
|
|
83
|
+
const byCode = await conn.getLatestByContent(
|
|
84
|
+
'drug.codes.atc',
|
|
85
|
+
[codes.progesterone, codes.aspirin, codes.missing],
|
|
86
|
+
{ streams: [streamId] }
|
|
87
|
+
);
|
|
88
|
+
expect(byCode.size).to.equal(2);
|
|
89
|
+
expect(byCode.get(codes.missing)).to.be.undefined;
|
|
90
|
+
// latest per code is the taken:true one (created later)
|
|
91
|
+
expect(byCode.get(codes.progesterone).content.taken).to.equal(true);
|
|
92
|
+
expect(byCode.get(codes.aspirin).content.taken).to.equal(true);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
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 */
|
|
6
|
+
|
|
7
|
+
const LoginButton = require('../src/Browser/LoginButton');
|
|
8
|
+
const utils = require('../src/utils');
|
|
9
|
+
|
|
10
|
+
describe('[LBRU] LoginButton URL cleanup after redirect', function () {
|
|
11
|
+
const PAGE_URL = 'http://localhost/app?x=1&prYvpoll=http%3A%2F%2Flocalhost%2Fpoll%2Fkey123&prYvstatus=ACCEPTED';
|
|
12
|
+
let dom;
|
|
13
|
+
let cleanupDom = false;
|
|
14
|
+
let originalFetchGet;
|
|
15
|
+
|
|
16
|
+
before(() => {
|
|
17
|
+
if (typeof document === 'undefined') {
|
|
18
|
+
cleanupDom = true;
|
|
19
|
+
dom = new JSDOM('<!DOCTYPE html><body></body>', { url: PAGE_URL });
|
|
20
|
+
global.document = dom.window.document;
|
|
21
|
+
global.window = dom.window;
|
|
22
|
+
global.location = dom.window.location;
|
|
23
|
+
global.navigator = { userAgent: 'Safari' };
|
|
24
|
+
}
|
|
25
|
+
originalFetchGet = utils.fetchGet;
|
|
26
|
+
utils.fetchGet = async () => ({ body: { status: 'ACCEPTED' } });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
after(() => {
|
|
30
|
+
utils.fetchGet = originalFetchGet;
|
|
31
|
+
if (!cleanupDom) return;
|
|
32
|
+
delete global.document;
|
|
33
|
+
delete global.window;
|
|
34
|
+
delete global.location;
|
|
35
|
+
delete global.navigator;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('[LBR1] strips consumed prYv* params from the visible URL', async () => {
|
|
39
|
+
const authController = { serviceInfo: {} };
|
|
40
|
+
await LoginButton.prototype.finishAuthProcessAfterRedirection.call({}, authController);
|
|
41
|
+
expect(authController.state).to.eql({ status: 'ACCEPTED' });
|
|
42
|
+
expect(global.window.location.href).to.equal('http://localhost/app?x=1');
|
|
43
|
+
});
|
|
44
|
+
});
|