Add hook that sends updated app token to the App (#3683)
* Add hook that sends updated app token to the App * Install latest app-sdk@0.39.1
This commit is contained in:
parent
16f8e0b177
commit
a86e0e6b13
6 changed files with 163 additions and 8 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -116,7 +116,7 @@
|
|||
"@percy/cli": "^1.21.0",
|
||||
"@percy/cypress": "^3.1.2",
|
||||
"@release-it/bumper": "^2.0.0",
|
||||
"@saleor/app-sdk": "0.37.3",
|
||||
"@saleor/app-sdk": "0.39.1",
|
||||
"@types/apollo-upload-client": "^17.0.2",
|
||||
"@types/color-convert": "^2.0.0",
|
||||
"@types/debug": "^4.1.7",
|
||||
|
@ -7913,9 +7913,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@saleor/app-sdk": {
|
||||
"version": "0.37.3",
|
||||
"resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.37.3.tgz",
|
||||
"integrity": "sha512-DFAjiEFBFIDWDqZvaXar8860zDgSZih2n7gT3e+aOpLIfnmMZ0nL6+aNS3A7ym2IStx8oUoPI1RFZBIeuF9+hg==",
|
||||
"version": "0.39.1",
|
||||
"resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.39.1.tgz",
|
||||
"integrity": "sha512-PBREZWwkk+DHCBhOZzsuFdp7/vLItxfAqKD+gcZ5QxzSAt82S0/FS6ii7igpW3H+bEiK4oBUjMxgUyhJMOXQHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@changesets/cli": "^2.26.0",
|
||||
|
@ -41291,9 +41291,9 @@
|
|||
}
|
||||
},
|
||||
"@saleor/app-sdk": {
|
||||
"version": "0.37.3",
|
||||
"resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.37.3.tgz",
|
||||
"integrity": "sha512-DFAjiEFBFIDWDqZvaXar8860zDgSZih2n7gT3e+aOpLIfnmMZ0nL6+aNS3A7ym2IStx8oUoPI1RFZBIeuF9+hg==",
|
||||
"version": "0.39.1",
|
||||
"resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.39.1.tgz",
|
||||
"integrity": "sha512-PBREZWwkk+DHCBhOZzsuFdp7/vLItxfAqKD+gcZ5QxzSAt82S0/FS6ii7igpW3H+bEiK4oBUjMxgUyhJMOXQHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@changesets/cli": "^2.26.0",
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
"@percy/cli": "^1.21.0",
|
||||
"@percy/cypress": "^3.1.2",
|
||||
"@release-it/bumper": "^2.0.0",
|
||||
"@saleor/app-sdk": "0.37.3",
|
||||
"@saleor/app-sdk": "0.39.1",
|
||||
"@types/apollo-upload-client": "^17.0.2",
|
||||
"@types/color-convert": "^2.0.0",
|
||||
"@types/debug": "^4.1.7",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { useAppDashboardUpdates } from "@dashboard/apps/components/AppFrame/useAppDashboardUpdates";
|
||||
import { useUpdateAppToken } from "@dashboard/apps/components/AppFrame/useUpdateAppToken";
|
||||
import {
|
||||
AppDetailsUrlQueryParams,
|
||||
prepareFeatureFlagsList,
|
||||
|
@ -76,6 +77,15 @@ export const AppFrame: React.FC<Props> = ({
|
|||
|
||||
const featureFlags = useMemo(() => prepareFeatureFlagsList(flags), [flags]);
|
||||
|
||||
useUpdateAppToken({
|
||||
postToExtension,
|
||||
appToken,
|
||||
/**
|
||||
* If app is not ready, ignore this flow
|
||||
*/
|
||||
enabled: handshakeDone,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{!handshakeDone && (
|
||||
|
|
80
src/apps/components/AppFrame/useUpdateAppToken.test.ts
Normal file
80
src/apps/components/AppFrame/useUpdateAppToken.test.ts
Normal file
|
@ -0,0 +1,80 @@
|
|||
import { useUpdateAppToken } from "@dashboard/apps/components/AppFrame/useUpdateAppToken";
|
||||
import { renderHook } from "@testing-library/react-hooks";
|
||||
|
||||
describe("useUpdateAppToken", function () {
|
||||
const postMessage = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it("Doesnt do anything if disabled", () => {
|
||||
const { waitFor } = renderHook(props => useUpdateAppToken(props), {
|
||||
initialProps: {
|
||||
enabled: true,
|
||||
appToken: "initialToken",
|
||||
postToExtension: postMessage,
|
||||
},
|
||||
});
|
||||
|
||||
return waitFor(() => {
|
||||
expect(postMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("Doesnt do anything if re-rendered, but token stays the same between renders", () => {
|
||||
const localPostMessage = jest.fn();
|
||||
|
||||
const { rerender, waitFor } = renderHook(
|
||||
props => useUpdateAppToken(props),
|
||||
{
|
||||
initialProps: {
|
||||
enabled: true,
|
||||
appToken: "initialToken",
|
||||
postToExtension: postMessage,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
rerender({
|
||||
enabled: true,
|
||||
appToken: "initialToken",
|
||||
// simulate props change due to reference change
|
||||
postToExtension: localPostMessage,
|
||||
});
|
||||
|
||||
return waitFor(() => {
|
||||
expect(postMessage).not.toHaveBeenCalled();
|
||||
expect(localPostMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("Calls postMessage if token changes in props and enabled", async () => {
|
||||
const { rerender, waitFor } = renderHook(
|
||||
props => useUpdateAppToken(props),
|
||||
{
|
||||
initialProps: {
|
||||
enabled: true,
|
||||
appToken: "initialToken",
|
||||
postToExtension: postMessage,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
rerender({
|
||||
enabled: true,
|
||||
appToken: "updatedToken",
|
||||
// simulate props change due to reference change
|
||||
postToExtension: postMessage,
|
||||
});
|
||||
|
||||
return waitFor(() => {
|
||||
expect(postMessage).toHaveBeenCalledWith({
|
||||
type: "tokenRefresh",
|
||||
payload: {
|
||||
token: "updatedToken",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
56
src/apps/components/AppFrame/useUpdateAppToken.ts
Normal file
56
src/apps/components/AppFrame/useUpdateAppToken.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { createAppsDebug } from "@dashboard/apps/apps-debug";
|
||||
import { DashboardEventFactory, Events } from "@saleor/app-sdk/app-bridge";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* https://usehooks.com/usePrevious/
|
||||
*/
|
||||
function usePreviousValue(value) {
|
||||
const ref = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
ref.current = value;
|
||||
}, [value]);
|
||||
|
||||
return ref.current;
|
||||
}
|
||||
|
||||
interface Args {
|
||||
enabled: boolean;
|
||||
appToken: string;
|
||||
postToExtension: (events: Events) => void;
|
||||
}
|
||||
|
||||
const debug = createAppsDebug("useUpdateAppToken");
|
||||
|
||||
/**
|
||||
* Listens on appToken changes and pushes it to the App if changed.
|
||||
*/
|
||||
export const useUpdateAppToken = ({
|
||||
enabled,
|
||||
appToken,
|
||||
postToExtension,
|
||||
}: Args) => {
|
||||
const cachedToken = usePreviousValue(appToken);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cachedToken) {
|
||||
/**
|
||||
* Missing cache token means its first render, so we dont want to send it to app
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (cachedToken !== appToken) {
|
||||
debug("Will send new token to the app");
|
||||
/**
|
||||
* Ensure running only when token changes. If token changes, send it to app
|
||||
*/
|
||||
postToExtension(DashboardEventFactory.createTokenRefreshEvent(appToken));
|
||||
}
|
||||
}, [enabled, appToken, cachedToken, postToExtension]);
|
||||
};
|
|
@ -31,3 +31,12 @@ window.__SALEOR_CONFIG__ = {
|
|||
process.env.TZ = "UTC";
|
||||
|
||||
configure({ testIdAttribute: "data-test-id" });
|
||||
|
||||
/**
|
||||
* https://github.com/inrupt/solid-client-authn-js/issues/1676
|
||||
*
|
||||
* Fixes (hacks) "TextEncoder is not defined" error which is likely bug in jsdom
|
||||
*/
|
||||
import { TextDecoder, TextEncoder } from "util";
|
||||
global.TextEncoder = TextEncoder;
|
||||
global.TextDecoder = TextDecoder;
|
||||
|
|
Loading…
Reference in a new issue