Skip to content

Commit

Permalink
Impl useSavedState
Browse files Browse the repository at this point in the history
  • Loading branch information
GerardasB committed Feb 6, 2025
1 parent e7bf3d8 commit 536a5fc
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from "react";
import {
Frontstage,
StagePanelState,
Widget,
WidgetState,
} from "@itwin/appui-react";
import { createTestFrontstage } from "./createTestFrontstage";

/** Used in e2e tests to test different widget configurations. */
export const createTestWidgetFrontstage = () => {
{
const urlParams = new URLSearchParams(window.location.search);
const frontstageParams = getFrontstageParams(urlParams);

const defaultState = getDefaultState(urlParams);
const useSavedState = urlParams.has("useSavedState");

const frontstage = createTestFrontstage({
id: "test-widget",
version: frontstageParams.version,
});

return {
...frontstage,
rightPanel: {
defaultState: StagePanelState.Open,
sections: {
start: [
{
id: "widget-1",
label: "Widget 1",
content: <>Widget 1 content</>,
defaultState,
useSavedState,
},
],
},
},
} satisfies Frontstage;
}
};

function getFrontstageParams(params: URLSearchParams) {
const versionParam = params.get("frontstageVersion");
const version = versionParam ? Number(versionParam) : undefined;
return { version } satisfies Partial<Frontstage>;
}

function getDefaultState(params: URLSearchParams): Widget["defaultState"] {
const param = params.get("defaultState");
if (param === "hidden") return WidgetState.Hidden;
return undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import {
StandardContentLayouts,
} from "@itwin/appui-react";

interface CreateTestFrontstageArgs {
interface CreateTestFrontstageArgs extends Partial<Frontstage> {
id: string;
}

export const createTestFrontstage = ({ id }: CreateTestFrontstageArgs) => {
export const createTestFrontstage = (
frontstageArgs: CreateTestFrontstageArgs
) => {
{
const contentGroup = new ContentGroup({
id: "test-group",
Expand All @@ -39,9 +41,9 @@ export const createTestFrontstage = ({ id }: CreateTestFrontstageArgs) => {
});

return {
id,
version: Math.random(),
contentGroup,
...frontstageArgs,
} satisfies Frontstage;
}
};
2 changes: 2 additions & 0 deletions apps/test-app/src/frontend/registerFrontstages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
createITwinUIV2Frontstage,
createITwinUIV2FrontstageProvider,
} from "./appui/frontstages/iTwinUIV2Frontstage";
import { createTestWidgetFrontstage } from "./appui/frontstages/TestWidgetFrontstage";

interface RegisterFrontstagesArgs {
iModelConnection?: IModelConnection;
Expand All @@ -74,6 +75,7 @@ export function registerFrontstages({
}),
createElementStackingFrontstage(),
createTestPanelFrontstage(),
createTestWidgetFrontstage(),
createTestPopoutFrontstage(),
createWidgetApiFrontstage(),
createCustomContentFrontstage(),
Expand Down
63 changes: 63 additions & 0 deletions e2e-tests/tests/widget-state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,66 @@ test.describe("widget lifecycle", () => {
expect(logs).toContain("Widget WL-B unmount");
});
});

test.describe("defaultState", () => {
test.describe("Hidden", () => {
test("should hide after reload", async ({ context, page }) => {
await page.goto(
"./blank?frontstageId=test-widget&frontstageVersion=1&defaultState=hidden"
);

// Hidden initially
const tab = tabLocator(page, "Widget 1");
await expect(tab).not.toBeVisible();

// Open widget
await setWidgetState(page, "widget-1", WidgetState.Open);
await expect(tab).toBeVisible();
await expectSavedFrontstageState(context, (state) => {
const widgets = Object.values(state.nineZone.widgets);
return widgets.length > 0;
});

// Should hide after reload
await page.reload();
await expectSavedFrontstageState(context, (state) => {
const widgets = Object.values(state.nineZone.widgets);
return widgets.length > 0;
});
await expect(tab).not.toBeVisible();
await expectSavedFrontstageState(context, (state) => {
const widgets = Object.values(state.nineZone.widgets);
return widgets.length === 0;
});
});

test("should persist after reload when useSavedState is enabled", async ({
context,
page,
}) => {
await page.goto(
"./blank?frontstageId=test-widget&frontstageVersion=1&defaultState=hidden&useSavedState"
);

// Hidden initially
const tab = tabLocator(page, "Widget 1");
await expect(tab).not.toBeVisible();

// Open widget
await setWidgetState(page, "widget-1", WidgetState.Open);
await expect(tab).toBeVisible();
await expectSavedFrontstageState(context, (state) => {
const widgets = Object.values(state.nineZone.widgets);
return widgets.length > 0;
});

// Should stay open after reload
await page.reload();
await expectSavedFrontstageState(context, (state) => {
const widgets = Object.values(state.nineZone.widgets);
return widgets.length > 0;
});
await expect(tab).toBeVisible();
});
});
});
2 changes: 2 additions & 0 deletions ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ function hideWidgetDefs(frontstageDef: FrontstageDef) {

/** Hide widget with `Hidden` or `Unloaded` defaultState. */
function hideWidgetDef(frontstageDef: FrontstageDef, widgetDef: WidgetDef) {
if (widgetDef.initialConfig?.useSavedState === true) return;

if (widgetDef.defaultState === WidgetState.Hidden) {
frontstageDef.dispatch({
type: "WIDGET_TAB_HIDE",
Expand Down

0 comments on commit 536a5fc

Please sign in to comment.