Skip to content
Snippets Groups Projects
Unverified Commit 8132d87e authored by Nicolò Pretto's avatar Nicolò Pretto Committed by GitHub
Browse files

skip analytics opt out step for people on cloud (#46965)

* poc of removing data usage step for the tech plan

* pretend it's not cloud if hasAddedPaidPlanInPreviousStep is true

* split the jest tests files to simulate pro cloud, pro selfhosted and starter cloud scenarios
parent 4453abb1
No related branches found
No related tags found
No related merge requests found
......@@ -44,6 +44,9 @@ export const goToNextStep = createAsyncThunk(
const state = getState() as State;
const nextStep = getNextStep(state);
dispatch(selectStep(nextStep));
if (nextStep === "completed") {
dispatch(setEmbeddingHomepageFlags());
}
},
);
......@@ -219,15 +222,6 @@ export const updateTracking = createAsyncThunk(
},
);
export const SUBMIT_SETUP = "metabase/setup/SUBMIT_SETUP";
export const submitSetup = createAsyncThunk<void, void, ThunkConfig>(
SUBMIT_SETUP,
async (_, { dispatch }) => {
dispatch(setEmbeddingHomepageFlags());
dispatch(goToNextStep());
},
);
export const setEmbeddingHomepageFlags = createAsyncThunk(
"setup/setEmbeddingHomepageFlags",
async (_, { getState, dispatch }) => {
......
......@@ -7,7 +7,7 @@ import ExternalLink from "metabase/core/components/ExternalLink";
import { useDispatch, useSelector } from "metabase/lib/redux";
import Settings from "metabase/lib/settings";
import { submitSetup, updateTracking } from "../../actions";
import { goToNextStep, updateTracking } from "../../actions";
import { getIsTrackingAllowed } from "../../selectors";
import { useStep } from "../../useStep";
import { ActiveStep } from "../ActiveStep";
......@@ -41,7 +41,7 @@ export const DataUsageStep = ({
const handleStepSubmit = async () => {
try {
await dispatch(submitSetup()).unwrap();
await dispatch(goToNextStep()).unwrap();
} catch (error) {
setErrorMessage(getSubmitError(error));
throw error;
......
......@@ -9,7 +9,6 @@ import {
skipDatabase,
submitDatabase,
submitLicenseToken,
submitSetup,
submitUsageReason,
submitUser,
submitUserInvite,
......@@ -75,7 +74,4 @@ export const reducer = createReducer(initialState, builder => {
builder.addCase(updateTracking.fulfilled, (state, { meta }) => {
state.isTrackingAllowed = meta.arg;
});
builder.addCase(submitSetup.fulfilled, state => {
state.step = "completed";
});
});
......@@ -107,6 +107,18 @@ export const getSteps = createSelector(
const shouldShowLicenseStep =
isEEBuild() && (!isPaidPlan || hasAddedPaidPlanInPreviousStep);
// note: when hosting is true, we should be on cloud and therefore not show
// the token step. There is an edge case that it's probably not possible in
// real life: somebody submitting a key with the hosting feature in the
// token step. This happens in our e2e test where we use the NO_FEATURES
// token which actually has the hosting feature so I added the
// hasAddedPaidPlanInPreviousStep check
const isHosted =
tokenFeatures &&
tokenFeatures["hosting"] &&
!hasAddedPaidPlanInPreviousStep;
const shouldShowDataUsageStep = !isHosted;
const steps: { key: SetupStep; isActiveStep: boolean }[] = [
{ key: "welcome" as const },
{ key: "language" as const },
......@@ -116,7 +128,7 @@ export const getSteps = createSelector(
key: "db_connection" as const,
},
shouldShowLicenseStep && { key: "license_token" as const },
{ key: "data_usage" as const },
shouldShowDataUsageStep ? { key: "data_usage" as const } : null,
{ key: "completed" as const },
]
.filter(isNotFalsy)
......
......@@ -17,6 +17,7 @@ import {
selectUsageReason,
setup,
skipLanguageStep,
skipTokenStep,
skipWelcomeScreen,
submitUserInfoStep,
} from "./setup";
......@@ -36,12 +37,12 @@ const setupEnterprise = (opts?: SetupOpts) => {
const sampleToken = "a".repeat(64);
const airgapToken = "airgap_toucan";
describe("setup (EE, no token)", () => {
describe("setup (EE build, but no token)", () => {
beforeEach(() => {
fetchMock.reset();
});
it("default step order should be correct, with the commercial step in place", async () => {
it("default step order should be correct, with the license step and data usage steps", async () => {
await setupEnterprise();
await skipWelcomeScreen();
expectSectionToHaveLabel("What's your preferred language?", "1");
......@@ -146,7 +147,7 @@ describe("setup (EE, no token)", () => {
it("should be possible to skip the step without a token", async () => {
await setupForLicenseStep();
await clickOnSkip();
await skipTokenStep();
expect(trackLicenseTokenStepSubmitted).toHaveBeenCalledWith(false);
......@@ -186,6 +187,3 @@ const submit = async () => {
await waitFor(() => expect(fetchMock.done(settingEndpoint)).toBe(true));
return fetchMock.lastCall(settingEndpoint);
};
const clickOnSkip = async () =>
await userEvent.click(screen.getByRole("button", { name: "Skip" }));
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectSectionToHaveLabel", "expectSectionsToHaveLabelsInOrder"] }] */
import { screen } from "@testing-library/react";
import { createMockTokenFeatures } from "metabase-types/api/mocks";
import type { SetupOpts } from "./setup";
import {
clickNextStep,
expectSectionToHaveLabel,
expectSectionsToHaveLabelsInOrder,
getLastSettingsPutPayload,
selectUsageReason,
setup,
skipLanguageStep,
skipWelcomeScreen,
submitUserInfoStep,
} from "./setup";
const setupPremium = (opts?: SetupOpts) => {
return setup({
...opts,
hasEnterprisePlugins: true,
tokenFeatures: createMockTokenFeatures({ hosting: true, embedding: true }),
});
};
describe("setup (EE build, `hosting` and `embedding` features to simulate pro on cloud)", () => {
it("default step order should be correct, without the license and data usage steps", async () => {
await setupPremium();
await skipWelcomeScreen();
expectSectionToHaveLabel("What's your preferred language?", "1");
expectSectionToHaveLabel("What should we call you?", "2");
expectSectionToHaveLabel("What will you use Metabase for?", "3");
expectSectionToHaveLabel("Add your data", "4");
// no "Activate your commercial license" as this has token-features
// no "Usage data preferences" as this is a hosted instance
expectSectionsToHaveLabelsInOrder();
});
it("should not show the analytics opt out (because of token-feature 'hosting')", async () => {
await setupPremium();
await skipWelcomeScreen();
expect(
screen.queryByText("Usage data preferences"),
).not.toBeInTheDocument();
});
it("should not render the license activation step", async () => {
await setupPremium();
await skipWelcomeScreen();
expect(
screen.queryByText("Activate your commercial license"),
).not.toBeInTheDocument();
});
it("should set 'setup-license-active-at-setup' to true", async () => {
await setupPremium();
await skipWelcomeScreen();
await skipLanguageStep();
await submitUserInfoStep();
await selectUsageReason("embedding");
await clickNextStep();
expect(await screen.findByText("Take me to Metabase")).toBeInTheDocument();
expect(await getLastSettingsPutPayload()).toEqual({
"embedding-homepage": "visible",
"enable-embedding": true,
"setup-embedding-autoenabled": true,
"setup-license-active-at-setup": true,
});
});
});
......@@ -22,23 +22,31 @@ const setupPremium = (opts?: SetupOpts) => {
return setup({
...opts,
hasEnterprisePlugins: true,
tokenFeatures: createMockTokenFeatures({ hosting: true, embedding: true }),
tokenFeatures: createMockTokenFeatures({ embedding: true }),
});
};
describe("setup (EE, hosting and embedding feature)", () => {
it("default step order should be correct, without the commercial step", async () => {
describe("setup (EE build, `embedding` feature but no `hosting` to simulate pro self-hosted)", () => {
it("default step order should be correct, without the commercial step but with the data usage step", async () => {
await setupPremium();
await skipWelcomeScreen();
expectSectionToHaveLabel("What's your preferred language?", "1");
expectSectionToHaveLabel("What should we call you?", "2");
expectSectionToHaveLabel("What will you use Metabase for?", "3");
expectSectionToHaveLabel("Add your data", "4");
// no "Activate your commercial license" as this has token-features
expectSectionToHaveLabel("Usage data preferences", "5");
expectSectionsToHaveLabelsInOrder();
});
it("should show the analytics opt out", async () => {
await setupPremium();
await skipWelcomeScreen();
expect(screen.getByText("Usage data preferences")).toBeInTheDocument();
});
it("should not render the license activation step", async () => {
await setupPremium();
await skipWelcomeScreen();
......@@ -58,6 +66,8 @@ describe("setup (EE, hosting and embedding feature)", () => {
await userEvent.click(screen.getByText("Finish"));
expect(await screen.findByText("Take me to Metabase")).toBeInTheDocument();
expect(await getLastSettingsPutPayload()).toEqual({
"embedding-homepage": "visible",
"enable-embedding": true,
......
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectSectionToHaveLabel", "expectSectionsToHaveLabelsInOrder"] }] */
import { screen } from "@testing-library/react";
import { createMockTokenFeatures } from "metabase-types/api/mocks";
import type { SetupOpts } from "./setup";
import {
clickNextStep,
expectSectionToHaveLabel,
expectSectionsToHaveLabelsInOrder,
getLastSettingsPutPayload,
selectUsageReason,
setup,
skipLanguageStep,
skipWelcomeScreen,
submitUserInfoStep,
} from "./setup";
const setupPremium = (opts?: SetupOpts) => {
return setup({
...opts,
hasEnterprisePlugins: true,
tokenFeatures: createMockTokenFeatures({ hosting: true }),
});
};
describe("setup (EE build, only `hosting` feature to simulate starter plan on cloud)", () => {
it("default step order should be correct, without the license and data usage steps", async () => {
await setupPremium();
await skipWelcomeScreen();
expectSectionToHaveLabel("What's your preferred language?", "1");
expectSectionToHaveLabel("What should we call you?", "2");
expectSectionToHaveLabel("What will you use Metabase for?", "3");
expectSectionToHaveLabel("Add your data", "4");
// no "Activate your commercial license" as this has token-features
// no "Usage data preferences" as this is a hosted instance
expectSectionsToHaveLabelsInOrder();
});
it("should not show the analytics opt out (because of token-feature 'hosting')", async () => {
await setupPremium();
await skipWelcomeScreen();
expect(
screen.queryByText("Usage data preferences"),
).not.toBeInTheDocument();
});
it("should not render the license activation step", async () => {
await setupPremium();
await skipWelcomeScreen();
expect(
screen.queryByText("Activate your commercial license"),
).not.toBeInTheDocument();
});
// `setup-license-active-at-setup` should be false if the only token feature is `hosting`
it("should set 'setup-license-active-at-setup' to false", async () => {
await setupPremium();
await skipWelcomeScreen();
await skipLanguageStep();
await submitUserInfoStep();
await selectUsageReason("embedding");
await clickNextStep();
expect(await getLastSettingsPutPayload()).toEqual({
"embedding-homepage": "visible",
"enable-embedding": true,
"setup-embedding-autoenabled": true,
"setup-license-active-at-setup": false,
});
});
});
......@@ -158,3 +158,6 @@ export const getLastSettingsPutPayload = async () => {
return JSON.parse((await lastSettingsCall![1]!.body!) as string);
};
export const skipTokenStep = async () =>
await userEvent.click(screen.getByRole("button", { name: "Skip" }));
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment