-
github-automation-metabase authored
backported "fix(sdk): migrate to custom redux context to allow using the sdk on host apps that use redux" (#51414) * step1: add MetabaseReduxProvider and make our hooks + connect fn use it step1: add MetabaseReduxProvider and make our hooks + connect fn use it * step 2: codemod * step 3: manual fixes * step 4: e2e test for sdk --------- Co-authored-by:Nicolò Pretto <info@npretto.com>
github-automation-metabase authored backported "fix(sdk): migrate to custom redux context to allow using the sdk on host apps that use redux" (#51414) * step1: add MetabaseReduxProvider and make our hooks + connect fn use it step1: add MetabaseReduxProvider and make our hooks + connect fn use it * step 2: codemod * step 3: manual fixes * step 4: e2e test for sdk --------- Co-authored-by:Nicolò Pretto <info@npretto.com>
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
redux-provider-clash.cy.spec.tsx 2.97 KiB
import {
MetabaseProvider,
StaticDashboard,
} from "@metabase/embedding-sdk-react";
import { configureStore, createSlice } from "@reduxjs/toolkit";
import { Provider, useDispatch, useSelector } from "react-redux";
import { ORDERS_DASHBOARD_ID } from "e2e/support/cypress_sample_instance_data";
import { describeEE } from "e2e/support/helpers";
import {
AUTH_PROVIDER_URL,
METABASE_INSTANCE_URL,
mockAuthProviderAndJwtSignIn,
signInAsAdminAndEnableEmbeddingSdk,
} from "e2e/support/helpers/component-testing-sdk";
import { getSdkRoot } from "e2e/support/helpers/e2e-embedding-sdk-helpers";
describeEE(
"scenarios > embedding-sdk > the redux provider context should not clash with the host app",
() => {
beforeEach(() => {
signInAsAdminAndEnableEmbeddingSdk();
cy.signOut();
mockAuthProviderAndJwtSignIn();
});
it("the host app redux logic should work normally even inside MetabaseProvider", () => {
cy.mount(
<Provider store={customerStore}>
<div data-testid="outside-metabase-provider">
<CounterButton />
</div>
<MetabaseProvider
authConfig={{
authProviderUri: AUTH_PROVIDER_URL,
metabaseInstanceUrl: METABASE_INSTANCE_URL,
}}
>
<div data-testid="inside-metabase-provider">
<CounterButton />
</div>
<StaticDashboard dashboardId={ORDERS_DASHBOARD_ID} withDownloads />
</MetabaseProvider>
</Provider>,
);
// the button should render and access the correct redux state both inside and outside the MetabaseProvider
cy.findByTestId("outside-metabase-provider")
.findByText("0")
.should("exist");
cy.findByTestId("inside-metabase-provider")
.findByText("0")
.should("exist");
// sanity check that it's actually working and actions work
cy.findByTestId("inside-metabase-provider").findByText("0").click();
cy.findByTestId("outside-metabase-provider")
.findByText("1")
.should("exist");
cy.findByTestId("inside-metabase-provider")
.findByText("1")
.should("exist");
// also make sure the sdk is working, most data goes through redux so if it renders
// it means it's working
getSdkRoot().findByText("Orders in a dashboard").should("exist");
getSdkRoot().findByText("Product ID").should("exist");
});
},
);
// sample code for customer app
const slice = createSlice({
name: "counter",
initialState: {
value: 0,
},
reducers: {
increment: state => {
state.value += 1;
},
},
});
const { increment } = slice.actions;
const customerStore = configureStore({
reducer: {
counter: slice.reducer,
},
});
const CounterButton = () => {
const count = useSelector(
(state: { counter: { value: number } }) => state.counter.value,
);
const dispatch = useDispatch();
return <button onClick={() => dispatch(increment())}>{count}</button>;
};