quiq-chat
Advanced tools
Comparing version 1.45.0 to 1.46.0
{ | ||
"name": "quiq-chat", | ||
"version": "1.45.0", | ||
"version": "1.46.0", | ||
"descri1tion": | ||
@@ -5,0 +5,0 @@ "Library to help with network requests to create a webchat client for Quiq Messaging", |
// @flow | ||
jest.mock('../logging'); | ||
jest.mock('../Utils/utils.js'); | ||
@@ -5,0 +6,0 @@ import * as Globals from '../globals'; |
// @flow | ||
import {formatQueryParams, burnItDown, createGuid} from './Utils/utils'; | ||
import {formatQueryParams, burnItDown, createGuid, onceAtATime} from './Utils/utils'; | ||
import { | ||
@@ -128,6 +128,8 @@ getUrlForContactPoint, | ||
* Creates a new session and tracking ID | ||
* NOTE: We ensure that this function is never invoked simultaneously, so as to prevent multiple trackingID related race conditions | ||
* | ||
* @param host - Host against which to call /generate | ||
* @param sessionChange - Indicates whether this is being called to replace old session. Results in newSession callback being fired. | ||
*/ | ||
export const login = (host?: string) => | ||
export const login = onceAtATime((host?: string) => | ||
quiqFetch( | ||
@@ -164,4 +166,5 @@ getGenerateUrl(host), | ||
return trackingId; | ||
}); | ||
}), | ||
); | ||
export const logout = () => quiqFetch(getSessionApiUrl(), {method: 'DELETE'}); |
jest.mock('../../logging'); | ||
jest.mock('../../Utils/utils.js'); | ||
@@ -3,0 +4,0 @@ import {isStorageEnabled} from '../index'; |
@@ -10,1 +10,2 @@ export const formatQueryParams = (url: string) => url; | ||
export const createGuid = () => 'imALittleGuidShortAndStout'; | ||
export const onceAtATime = f => f; |
@@ -71,2 +71,44 @@ // @flow | ||
}); | ||
describe('onceAtATime', () => { | ||
const f = jest.fn( | ||
(n: number) => new Promise(resolve => setTimeout(resolve(`Seahawks ${n}`), 2000)), | ||
); | ||
const f1 = Utils.onceAtATime(f); | ||
afterEach(() => { | ||
f.mockClear(); | ||
}); | ||
it('only runs the fucntions once at a time', () => { | ||
f1(); | ||
f1(); | ||
f1(); | ||
f1(); | ||
expect(f.mock.calls.length).toBe(1); | ||
}); | ||
it('only returns the result of the original call to all subsequent calls made while original is running', async () => { | ||
expect.assertions(4); | ||
const values = await Promise.all([f1(1), f1(2), f1(3)]); | ||
values.forEach(v => { | ||
expect(v).toBe('Seahawks 1'); | ||
}); | ||
expect(f.mock.calls.length).toBe(1); | ||
}); | ||
it('invokes the function again once first invocation is completed', async () => { | ||
expect.assertions(7); | ||
let values = await Promise.all([f1(1), f1(2), f1(3)]); | ||
values.forEach(v => { | ||
expect(v).toBe('Seahawks 1'); | ||
}); | ||
values = await Promise.all([f1(3), f1(4), f1(5)]); | ||
values.forEach(v => { | ||
expect(v).toBe('Seahawks 3'); | ||
}); | ||
expect(f.mock.calls.length).toBe(2); | ||
}); | ||
}); | ||
}); |
@@ -5,3 +5,2 @@ // @flow | ||
import QuiqSocket from 'QuiqSockets/quiqSockets'; | ||
import {disconnectSocket} from 'websockets'; | ||
import qs from 'qs'; | ||
@@ -62,3 +61,2 @@ import logger from 'logging'; | ||
QuiqSocket.disconnect(); | ||
disconnectSocket(); | ||
@@ -95,1 +93,27 @@ if (_onBurn) _onBurn(); | ||
}; | ||
/** | ||
* Creates a function that is restricted to allow only one invocation at a time. That is, if a function f is called while | ||
* a previous call to f is already running, the return value of the first invocation will be used as the return value for the second as well. | ||
* This is similar to throttling, except that we don't care about time between calls, only that the function never runs simultaneously. | ||
* @param f | ||
*/ | ||
export const onceAtATime = <A, T>(f: A => Promise<T>): (A => Promise<T>) => { | ||
let currentPromise: Promise<T> | null = null; | ||
let promisePending = false; | ||
return (...args) => { | ||
if (promisePending && currentPromise) { | ||
return currentPromise; | ||
} | ||
currentPromise = f.apply(this, args); | ||
promisePending = true; | ||
currentPromise | ||
.then(() => { | ||
promisePending = false; | ||
}) | ||
.catch(() => { | ||
promisePending = false; | ||
}); | ||
return currentPromise; | ||
}; | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2013345
12246