refactor: use broadcast channel again
Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
@@ -16,12 +16,8 @@
|
||||
|
||||
import React from 'react';
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import {
|
||||
fetchApiRef,
|
||||
discoveryApiRef,
|
||||
storageApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { MockStorageApi, TestApiProvider } from '@backstage/test-utils';
|
||||
import { fetchApiRef, discoveryApiRef } from '@backstage/core-plugin-api';
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { useCookieAuthRefresh } from './useCookieAuthRefresh';
|
||||
|
||||
describe('useCookieAuthRefresh', () => {
|
||||
@@ -43,8 +39,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
}),
|
||||
};
|
||||
|
||||
const storageApiMock = MockStorageApi.create();
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers({ now });
|
||||
jest.clearAllMocks();
|
||||
@@ -69,7 +63,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
fetch: jest.fn().mockRejectedValue(error),
|
||||
},
|
||||
],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
]}
|
||||
>
|
||||
@@ -100,7 +93,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
.mockReturnValue(new Promise(() => {})),
|
||||
},
|
||||
],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
]}
|
||||
>
|
||||
@@ -153,7 +145,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
.mockReturnValue(new Promise(() => {})),
|
||||
},
|
||||
],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
]}
|
||||
>
|
||||
@@ -208,7 +199,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
fetch: jest.fn().mockRejectedValue(error),
|
||||
},
|
||||
],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
]}
|
||||
>
|
||||
@@ -235,7 +225,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[fetchApiRef, fetchApiMock],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
]}
|
||||
>
|
||||
@@ -268,7 +257,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[fetchApiRef, fetchApiMock],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
]}
|
||||
>
|
||||
@@ -281,12 +269,14 @@ describe('useCookieAuthRefresh', () => {
|
||||
now + 2 * tenMinutesInMilliseconds;
|
||||
|
||||
// simulating other tab refreshing the cookie
|
||||
storageApiMock
|
||||
.forBucket(`${pluginId}-auth-cookie-storage`)
|
||||
.set(
|
||||
'expiresAt',
|
||||
new Date(twentyMinutesFromNowInMilliseconds).toISOString(),
|
||||
);
|
||||
new global.BroadcastChannel(
|
||||
`${pluginId}-auth-cookie-expires-at`,
|
||||
).postMessage({
|
||||
action: 'COOKIE_REFRESH_SUCCESS',
|
||||
payload: {
|
||||
expiresAt: new Date(twentyMinutesFromNowInMilliseconds).toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
// advance the timers in 10 minutes to match the old expires at
|
||||
jest.advanceTimersByTime(tenMinutesInMilliseconds);
|
||||
@@ -309,7 +299,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[fetchApiRef, fetchApiMock],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
]}
|
||||
>
|
||||
@@ -345,7 +334,6 @@ describe('useCookieAuthRefresh', () => {
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[fetchApiRef, fetchApiMock],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
]}
|
||||
>
|
||||
|
||||
@@ -14,11 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import { useEffect, useCallback, useMemo } from 'react';
|
||||
import {
|
||||
discoveryApiRef,
|
||||
fetchApiRef,
|
||||
storageApiRef,
|
||||
useApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { useAsync, useMountEffect } from '@react-hookz/web';
|
||||
@@ -40,10 +39,13 @@ export function useCookieAuthRefresh(options: {
|
||||
| { status: 'success'; data: { expiresAt: string } } {
|
||||
const { pluginId, path = '/cookie' } = options ?? {};
|
||||
const fetchApi = useApi(fetchApiRef);
|
||||
const storageApi = useApi(storageApiRef);
|
||||
const discoveryApi = useApi(discoveryApiRef);
|
||||
|
||||
const store = storageApi.forBucket(`${pluginId}-auth-cookie-storage`);
|
||||
const channel = useMemo(() => {
|
||||
return 'BroadcastChannel' in window
|
||||
? new BroadcastChannel(`${pluginId}-auth-cookie-expires-at`)
|
||||
: null;
|
||||
}, [pluginId]);
|
||||
|
||||
const [state, actions] = useAsync<{ expiresAt: string }>(async () => {
|
||||
const apiOrigin = await discoveryApi.getBaseUrl(pluginId);
|
||||
@@ -84,21 +86,26 @@ export function useCookieAuthRefresh(options: {
|
||||
if (state.status !== 'success' || !state.result) {
|
||||
return () => {};
|
||||
}
|
||||
const expiresAt = state.result.expiresAt;
|
||||
store.set('expiresAt', expiresAt);
|
||||
let cancel = refresh({ expiresAt });
|
||||
const subscription = store
|
||||
.observe$<string>('expiresAt')
|
||||
.subscribe(({ value }) => {
|
||||
if (!value) return;
|
||||
channel?.postMessage({
|
||||
action: 'COOKIE_REFRESH_SUCCESS',
|
||||
payload: state.result,
|
||||
});
|
||||
let cancel = refresh(state.result);
|
||||
const listener = (
|
||||
event: MessageEvent<{ action: string; payload: { expiresAt: string } }>,
|
||||
) => {
|
||||
const { action, payload } = event.data;
|
||||
if (action === 'COOKIE_REFRESH_SUCCESS') {
|
||||
cancel();
|
||||
cancel = refresh({ expiresAt: value });
|
||||
});
|
||||
cancel = refresh(payload);
|
||||
}
|
||||
};
|
||||
channel?.addEventListener('message', listener);
|
||||
return () => {
|
||||
cancel();
|
||||
subscription.unsubscribe();
|
||||
channel?.removeEventListener('message', listener);
|
||||
};
|
||||
}, [state, refresh, store]);
|
||||
}, [state, refresh, channel]);
|
||||
|
||||
// Initialising
|
||||
if (state.status === 'not-executed') {
|
||||
|
||||
@@ -14,3 +14,36 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
global.BroadcastChannel = jest
|
||||
.fn()
|
||||
.mockImplementation((_channelName: string) => {
|
||||
const listeners: ((event: { data: any }) => void)[] = [];
|
||||
|
||||
return {
|
||||
addEventListener: (
|
||||
type: string,
|
||||
listener: (event: { data: any }) => void,
|
||||
) => {
|
||||
if (type === 'message') {
|
||||
listeners.push(listener);
|
||||
}
|
||||
},
|
||||
removeEventListener: (
|
||||
type: string,
|
||||
listener: (event: { data: any }) => void,
|
||||
) => {
|
||||
if (type === 'message') {
|
||||
const index = listeners.indexOf(listener);
|
||||
if (index !== -1) {
|
||||
listeners.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
postMessage: (message: any) => {
|
||||
listeners.forEach(listener => {
|
||||
listener({ data: message });
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -22,17 +22,12 @@ import { screen } from 'testing-library__dom';
|
||||
import { Route } from 'react-router-dom';
|
||||
import { act, render } from '@testing-library/react';
|
||||
|
||||
import {
|
||||
wrapInTestApp,
|
||||
TestApiProvider,
|
||||
MockStorageApi,
|
||||
} from '@backstage/test-utils';
|
||||
import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils';
|
||||
import { FlatRoutes } from '@backstage/core-app-api';
|
||||
import {
|
||||
ApiRef,
|
||||
discoveryApiRef,
|
||||
fetchApiRef,
|
||||
storageApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
import {
|
||||
@@ -78,8 +73,6 @@ const scmIntegrationsApi = {
|
||||
fromConfig: jest.fn().mockReturnValue({}),
|
||||
};
|
||||
|
||||
const storageApiMock = MockStorageApi.create();
|
||||
|
||||
const discoveryApi = {
|
||||
getBaseUrl: jest
|
||||
.fn()
|
||||
@@ -232,7 +225,6 @@ export class TechDocsAddonTester {
|
||||
build() {
|
||||
const apis: TechdocsAddonTesterApis<any[]> = [
|
||||
[fetchApiRef, fetchApi],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApi],
|
||||
[techdocsApiRef, techdocsApi],
|
||||
[techdocsStorageApiRef, techdocsStorageApi],
|
||||
|
||||
@@ -19,7 +19,6 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react';
|
||||
import { entityRouteRef } from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
MockConfigApi,
|
||||
MockStorageApi,
|
||||
renderInTestApp,
|
||||
TestApiProvider,
|
||||
} from '@backstage/test-utils';
|
||||
@@ -39,7 +38,6 @@ import {
|
||||
configApiRef,
|
||||
discoveryApiRef,
|
||||
fetchApiRef,
|
||||
storageApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
const mockEntityMetadata = {
|
||||
@@ -82,8 +80,6 @@ const techdocsStorageApiMock: jest.Mocked<typeof techdocsStorageApiRef.T> = {
|
||||
syncEntityDocs: jest.fn(),
|
||||
};
|
||||
|
||||
const storageApiMock = MockStorageApi.create();
|
||||
|
||||
const discoveryApiMock = {
|
||||
getBaseUrl: jest
|
||||
.fn()
|
||||
@@ -121,7 +117,6 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[fetchApiRef, fetchApiMock],
|
||||
[storageApiRef, storageApiMock],
|
||||
[discoveryApiRef, discoveryApiMock],
|
||||
[scmIntegrationsApiRef, {}],
|
||||
[configApiRef, configApi],
|
||||
|
||||
Reference in New Issue
Block a user