Skip to content

Commit f27c734

Browse files
committed
Throttle last visited calls.
1 parent ac37a38 commit f27c734

File tree

5 files changed

+32
-21
lines changed

5 files changed

+32
-21
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/chrome/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
"url": "https://github.com/RedHatInsights/frontend-components/issues"
2626
},
2727
"homepage": "https://github.com/RedHatInsights/frontend-components/tree/master/packages/chrome#readme",
28+
"dependencies": {
29+
"lodash": "^4.17.21"
30+
},
2831
"peerDependencies": {
2932
"@scalprum/react-core": "^0.5.1",
3033
"react": "^18.2.0",

packages/chrome/src/ChromeProvider/ChromeProvider.test.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { PluginStore } from '@openshift/dynamic-plugin-sdk';
88
import ChromeProvider from './ChromeProvider';
99
import * as fetch from '../utils/fetch';
1010

11-
const flushPromises = () => new Promise(setImmediate);
12-
1311
describe('ChromeProvider', () => {
1412
const getSpy = jest.spyOn(fetch, 'get');
1513
const postSpy = jest.spyOn(fetch, 'post');
@@ -34,6 +32,7 @@ describe('ChromeProvider', () => {
3432
});
3533

3634
test('should post new data on title change', async () => {
35+
jest.useFakeTimers();
3736
getSpy.mockResolvedValueOnce([]);
3837
postSpy.mockResolvedValue(['/', '/bar']);
3938
const DocumentMutator = () => {
@@ -75,17 +74,19 @@ describe('ChromeProvider', () => {
7574
screen.getByText('/foo/bar').click();
7675
});
7776

77+
// debounce timer
7878
// wait for calls to be finished
7979
await act(async () => {
80-
await flushPromises();
80+
await jest.advanceTimersByTime(5001);
8181
});
82-
expect(postSpy).toHaveBeenCalledTimes(2);
82+
// should be called anly once because of the debounce
83+
expect(postSpy).toHaveBeenCalledTimes(1);
8384
expect(postSpy).toHaveBeenLastCalledWith('/api/chrome-service/v1/last-visited', {
8485
pathname: '/foo/bar',
8586
title: 'Foo title',
8687
bundle: 'bundle-title',
8788
});
88-
});
89+
}, 10000);
8990

9091
test('should not update state on mount if received error response', async () => {
9192
const errorResponse = { errors: [{ status: 404, meta: { response_by: 'gateway' }, detail: 'Undefined Insights application' }] };
@@ -116,11 +117,8 @@ describe('ChromeProvider', () => {
116117
);
117118
});
118119

119-
expect(consoleSpy).toHaveBeenCalledTimes(2);
120-
expect(consoleSpy.mock.calls).toEqual([
121-
['Unable to update last visited pages!', errorResponse],
122-
['Unable to initialize ChromeProvider!', errorResponse],
123-
]);
120+
expect(consoleSpy).toHaveBeenCalledTimes(1);
121+
expect(consoleSpy.mock.calls).toEqual([['Unable to initialize ChromeProvider!', errorResponse]]);
124122
consoleSpy.mockRestore();
125123
});
126124
});

packages/chrome/src/ChromeProvider/ChromeProvider.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,33 @@ import React, { useEffect, useRef, useState } from 'react';
22
import { useScalprum } from '@scalprum/react-core';
33
import { ChromeAPI } from '@redhat-cloud-services/types';
44
import { useLocation } from 'react-router-dom';
5+
import debounce from 'lodash/debounce';
56

67
import { ChromeContext } from '../ChromeContext';
78
import chromeState, { LastVisitedPage, UserIdentity } from './chromeState';
89
import { IDENTITY_URL, LAST_VISITED_URL, get, post } from '../utils/fetch';
910

1011
const getUserIdentity = () => get<UserIdentity>(IDENTITY_URL);
12+
const postDataDebounced = debounce(async (pathname: string, title: string, bundle: string) => {
13+
const data = await post<LastVisitedPage[], { pathname: string; title: string; bundle: string }>(LAST_VISITED_URL, {
14+
pathname,
15+
title,
16+
bundle,
17+
});
18+
return data;
19+
// count page as visited after 5 second of being on the page
20+
// should help limit number of API calls
21+
}, 5000);
1122

1223
const useLastPageVisitedUploader = (providerState: ReturnType<typeof chromeState>) => {
1324
const scalprum = useScalprum<{ initialized: boolean; api: { chrome: ChromeAPI } }>();
1425
const { pathname } = useLocation();
1526
const postData = async (pathname: string, title: string, bundle: string) => {
1627
try {
17-
const data = await post<LastVisitedPage[], { pathname: string; title: string; bundle: string }>(LAST_VISITED_URL, {
18-
pathname,
19-
title,
20-
bundle,
21-
});
22-
providerState.setLastVisited(data);
28+
const data = await postDataDebounced(pathname, title, bundle);
29+
if (data) {
30+
providerState.setLastVisited(data);
31+
}
2332
} catch (error) {
2433
console.error('Unable to update last visited pages!', error);
2534
}
@@ -59,6 +68,7 @@ const useLastPageVisitedUploader = (providerState: ReturnType<typeof chromeState
5968
}
6069
return () => {
6170
titleObserver?.disconnect();
71+
postDataDebounced?.cancel();
6272
};
6373
}, [pathname]);
6474
};

packages/chrome/src/ChromeProvider/chromeState.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ describe('chromeState', () => {
3535
expect(state.getState().lastVisitedPages).toEqual(lastVisitedPayload);
3636
});
3737

38-
test('should correctly update favrite pages data via dedicated callback', () => {
38+
test('should correctly update favorite pages data via dedicated callback', () => {
3939
state.setFavoritePages([{ pathname: 'favorite', favorite: true }]);
4040
expect(state.getState().favoritePages).toEqual([{ pathname: 'favorite', favorite: true }]);
4141
});

0 commit comments

Comments
 (0)