Skip to content

feat: App layout global drawers #2596

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 152 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
dab6ac4
feat: Global drawers for app-layout component (refresh-toolbar theme)
georgylobko Aug 19, 2024
e22dda6
feat: Set sizes for global drawers, make them resizable
georgylobko Aug 19, 2024
61c82e2
feat: Set max sizes for global drawers
georgylobko Aug 20, 2024
442c01d
chore: Small refactoring
georgylobko Aug 20, 2024
3247981
feat: Focus control for global drawers
georgylobko Aug 20, 2024
f74c66f
chore: Remove todo comment that has already resolved
georgylobko Aug 20, 2024
9abcc38
feat: Focus on global drawers / trigger buttons on open / close events
georgylobko Aug 20, 2024
81bd0b6
chore: Removed a resolved todo item
georgylobko Aug 20, 2024
f02174d
feat: Persist global drawers' state between toggles
georgylobko Aug 20, 2024
9117d4c
fix: Prevent inactive global drawers from being displayed in mobile view
georgylobko Aug 21, 2024
67c4717
chore: limit drawers size on desktop view
georgylobko Aug 21, 2024
cb4dec4
fix: global drawers mobile view
georgylobko Aug 21, 2024
0ced26f
fix: minor issue
georgylobko Aug 21, 2024
0b24414
feat: Introduce openDrawer method for widget api
georgylobko Aug 21, 2024
cb75bb7
chore: Prevent openDrawer from toggling a drawer if it's already open
georgylobko Aug 22, 2024
7bef7b1
feat: Separator for local / global drawers
georgylobko Aug 22, 2024
314178f
fix: Focus behavior for global drawers
georgylobko Aug 22, 2024
91530e7
feat: Put overflown global drawers in the top menu and separate them …
georgylobko Aug 23, 2024
1ac4cc9
feat: Close first opened drawer when open a new one if it does not fi…
georgylobko Aug 26, 2024
c74f617
chore: Small refactoring
georgylobko Aug 26, 2024
0dae27f
chore: Small refactoring
georgylobko Aug 26, 2024
016ffb4
chore: Assign z-index for individual drawers rather than a whole group
georgylobko Aug 27, 2024
d77ac6c
chore: Describe drawersOpenQueue
georgylobko Aug 27, 2024
78bcaba
feat: Set higher z-index for last opened drawer to show it on top of …
georgylobko Aug 27, 2024
936aa79
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Aug 27, 2024
3b18c6d
chore: Introduce a separate component for global drawers
georgylobko Aug 27, 2024
2a63c21
chore: Introduce basic u test for global drawers along with new metho…
georgylobko Aug 28, 2024
86cd673
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Aug 28, 2024
3569634
chore: Test global drawers replace behavior
georgylobko Aug 28, 2024
72ea706
chore: Test global drawers open order
georgylobko Aug 28, 2024
be4ee53
chore: Unmount global drawers DOM nodes on close
georgylobko Aug 28, 2024
3fc6279
fix: use describeEachAppLayout to test VR toolbar only features
georgylobko Aug 28, 2024
d0b59c9
chore: Check if separator between local and global drawers is rendered
georgylobko Aug 28, 2024
7a58b8d
chore: Test registerDrawer behavior if type is not specified (should …
georgylobko Aug 28, 2024
95d2134
chore: Test openDrawer api method
georgylobko Aug 28, 2024
c747995
chore: Test the behavior of active drawers when resizing from desktop…
georgylobko Aug 29, 2024
548617b
chore: Test the behavior of active drawers take up all available spac…
georgylobko Aug 29, 2024
e138c02
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Aug 29, 2024
4ca4c4d
fix: skeleton styles
georgylobko Aug 29, 2024
69b7c99
chore: Test a behavior when first opened drawer should be closed when…
georgylobko Aug 29, 2024
9b701f9
chore: Update test snapshots
georgylobko Aug 29, 2024
7588faa
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Aug 29, 2024
994911b
chore: Test a behavior when close opened global drawer by clicking on…
georgylobko Aug 29, 2024
614982d
chore: Replace separator with group-divider to align the vertical lin…
georgylobko Aug 30, 2024
323d395
chore: Test behavior when first opened drawer should be closed when a…
georgylobko Aug 30, 2024
e168a07
chore: Test behavior when first opened (both global and local) drawer…
georgylobko Aug 30, 2024
a29733b
chore: Test behavior when renders resize handle for a global drawer w…
georgylobko Aug 30, 2024
8e53ab8
chore: Test closing active global drawer
georgylobko Aug 30, 2024
0ce4c45
fix: Small refactoring
georgylobko Aug 30, 2024
87690fb
chore: Pass global drawers focus controlls to useMultiAppLayout
georgylobko Aug 30, 2024
f57fdc6
chore: Test focus restore for global drawers
georgylobko Aug 30, 2024
affb46e
feat: onResize for global drawers
georgylobko Aug 30, 2024
4b7138c
feat: keep non-active drawers in the dom when keepContentMounted is p…
georgylobko Aug 30, 2024
30ef382
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 9, 2024
6b10050
feat: Rename keepContentMounted to preserveInactiveContent. Introduce…
georgylobko Sep 9, 2024
7f578ab
chore: Non-null assertion for global drawers' selectors in integ tests
georgylobko Sep 9, 2024
5edefbe
chore: Replace getLogicalBoundingClientRect mock with computeHorizont…
georgylobko Sep 9, 2024
6927176
chore: Move out global drawers test-utils to "internal" test-utils
georgylobko Sep 9, 2024
dcd1867
chore: Update test snapshots
georgylobko Sep 9, 2024
56ae740
fix: Import in an integ test
georgylobko Sep 9, 2024
3a8b4bc
fix: z indexes for drawers
georgylobko Sep 9, 2024
2d4628e
feat: State management for runtime drawers
georgylobko Sep 10, 2024
5b7bd06
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 10, 2024
3bd0d48
chore: Move layout related tests for runtime drawers to a separate te…
georgylobko Sep 10, 2024
520af02
fix: Remove unnecessary ref in the runtime-drawers.test.tsx
georgylobko Sep 10, 2024
fa84a6a
chore: Move onDrawerOpened listener to use-drawers handler and introd…
georgylobko Sep 10, 2024
f6954ae
chore: Remove onDrawerOpened from index file
georgylobko Sep 10, 2024
e6ab611
chore: Refactor runtime global drawers parsing rules (get rid of befo…
georgylobko Sep 10, 2024
0dbe0d7
chore: Small refactoring
georgylobko Sep 10, 2024
af49dab
fix: Minor review comments
georgylobko Sep 10, 2024
78d4963
fix: Minor review comments
georgylobko Sep 11, 2024
3f8ea62
chore: Separate local and global drawers into different files
georgylobko Sep 11, 2024
e438d6d
fix: Remove unnecessary props (related to global drawers) from the us…
georgylobko Sep 11, 2024
2b80141
feat: closeDrawer method in awsui plugin
georgylobko Sep 11, 2024
4e720fb
feat: Make drawer's props `trigger` optional and introduce u tests fo…
georgylobko Sep 11, 2024
a1fa637
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 11, 2024
b775055
feat: Closing first opened drawer if it does not fit on the screen si…
georgylobko Sep 12, 2024
bb25ecc
chore: Introduce integ tests for content resizing behavior
georgylobko Sep 12, 2024
206ef43
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 12, 2024
6393caa
chore: Drawers trigger filter refactoring
georgylobko Sep 12, 2024
7189cbe
chore: Small refactoring
georgylobko Sep 12, 2024
b9478c0
chore: Simplify global drawers' visibility management
georgylobko Sep 13, 2024
1b5649c
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 13, 2024
d223834
chore: Refactor visibility management for global drawers
georgylobko Sep 13, 2024
ef5aae7
chore: Cleanup app-layout test-utils file
georgylobko Sep 13, 2024
0b10c09
chore: Cleanup compact mode for resize handler
georgylobko Sep 13, 2024
3e249b5
chore: Small refactoring
georgylobko Sep 13, 2024
56d7e32
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 13, 2024
df392a7
fix: Typo
georgylobko Sep 13, 2024
78be266
fix: Remove drawers' close on resize event
georgylobko Sep 13, 2024
45c4ffe
fix: Small cleanup
georgylobko Sep 13, 2024
22d1606
chore: Global drawers' border color
georgylobko Sep 13, 2024
fa87d08
fix: Global drawers layout and z-indexes
georgylobko Sep 13, 2024
76a9fd4
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 16, 2024
c625bef
chore: Small refactoring
georgylobko Sep 16, 2024
d87f7a2
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 16, 2024
1767d63
chore: Small refactoring
georgylobko Sep 16, 2024
6cbbbc7
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 16, 2024
cf35615
fix: Navigation panel z-index
georgylobko Sep 16, 2024
25cc236
Merge remote-tracking branch 'origin/feat/app-layout-global-drawers' …
georgylobko Sep 16, 2024
e0ce5d9
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 17, 2024
658fb47
chore: Limit local drawer width (same way as for global drawers)
georgylobko Sep 17, 2024
52dbdf3
fix: Global drawers positioning on mobile
georgylobko Sep 17, 2024
4ed701b
fix: Drawers' close on resize
georgylobko Sep 18, 2024
69019ca
chore: Refactoring (part 1)
georgylobko Sep 19, 2024
ba328d7
chore: Turn drawersOpenQueue into ref
georgylobko Sep 19, 2024
a089e0b
chore: Simplify the useRuntimeDrawers defaultActive condition
georgylobko Sep 19, 2024
9fb682f
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 19, 2024
b27ecc7
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 19, 2024
7c553dc
chore: Refactor multiple focus control hook
georgylobko Sep 19, 2024
6d9582b
feat: Enable tooltips for global drawers
georgylobko Sep 19, 2024
2a83730
fix: Drawers' queue
georgylobko Sep 19, 2024
bc5570e
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 19, 2024
2b9ddf3
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 19, 2024
3cd9b6a
chore: Suppress global drawers' tooltips on close
georgylobko Sep 20, 2024
0725e9e
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 20, 2024
375057c
feat: Focus on trigger button as a fallback in multiple focus control
georgylobko Sep 20, 2024
f5c973c
feat: Mark overflown trigger items as active
georgylobko Sep 20, 2024
e1c92f4
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 23, 2024
3105c4b
feat: Mark overflown trigger items as active
georgylobko Sep 23, 2024
5c939ba
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 23, 2024
4fd5846
chore: Clean up runtime drawer visibility callback
georgylobko Sep 23, 2024
70f867b
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 23, 2024
db63af9
chore: Test case for closeDrawer api for global drawer
georgylobko Sep 23, 2024
ac0bc40
chore: Hide preserveInactiveContent drawers and actually preserve the…
georgylobko Sep 23, 2024
f0d770d
feat: Animations for drawers
georgylobko Sep 24, 2024
cd37d49
chore: Add test case with resizable drawer
georgylobko Sep 25, 2024
ee72d15
fix: Drawers trigger empty render condition
georgylobko Sep 25, 2024
70ec5cf
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 25, 2024
34957b8
chore: Small fix
georgylobko Sep 25, 2024
d51aa8a
chore: Export AppLayoutGlobalDrawer
georgylobko Sep 25, 2024
6d554a7
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 25, 2024
b564633
chore: Turn isPaused in auto incrementing counter to ref
georgylobko Sep 26, 2024
e3f244b
chore: Remove drawers' trigger condition for classic and VR themes
georgylobko Sep 26, 2024
d5f7499
chore: Rename setActiveGlobalDrawersIds to onActiveGlobalDrawersChang…
georgylobko Sep 26, 2024
e7bcf57
chore: Small fix
georgylobko Sep 26, 2024
3f7f140
chore: Remove eslint-disable for useMultipleFocusControl
georgylobko Sep 26, 2024
8170d5e
fix: Local drawer size calculation
georgylobko Sep 26, 2024
cb83a1b
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 26, 2024
a16f768
feat: Replace AppLayoutGlobalDrawer with AppLayoutGlobalDrawers widget
georgylobko Sep 26, 2024
71f66d2
chore: Remove motion styles from global-drawers wrapper
georgylobko Sep 26, 2024
e01bd5f
chore: Make MountContentContext prop for runtime drawers required
georgylobko Sep 26, 2024
93cc4d6
Merge remote-tracking branch 'origin/main' into feat/app-layout-globa…
georgylobko Sep 26, 2024
5f0d423
fix: Local drawer visibility
georgylobko Sep 26, 2024
5b34d2d
fix: Remove drawers' triggers filtering
georgylobko Sep 26, 2024
e59b89f
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 26, 2024
e478053
fix: Default drawersOpenQueue to []
georgylobko Sep 26, 2024
99f2770
fix: Screenshot tests
georgylobko Sep 27, 2024
765a163
fix: Integration test for resizing local drawer
georgylobko Sep 27, 2024
fad8352
fix: Integration test for app layout content width
georgylobko Sep 27, 2024
d847e28
chore: Handle legacy behavior for local drawers
georgylobko Sep 27, 2024
50e9879
Merge branch 'main' into feat/app-layout-global-drawers
georgylobko Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion pages/app-layout/runtime-drawers-with-updates.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import React, { useContext, useEffect, useState } from 'react';

import { AppLayout, ContentLayout, Header, HelpPanel, Link, SpaceBetween, Toggle } from '~components';
import { AppLayout, Button, ContentLayout, Header, HelpPanel, Link, SpaceBetween, Toggle } from '~components';
import { AppLayoutProps } from '~components/app-layout';
import awsuiPlugins from '~components/internal/plugins';

Expand Down Expand Up @@ -69,6 +69,14 @@ export default function WithDrawers() {
Use Tools
</Toggle>

<Button
onClick={() => {
awsuiPlugins.appLayout.openDrawer('circle-global');
}}
>
Open runtime drawer
</Button>

<Header variant="h2">Security Drawer Updates</Header>
<Toggle
data-testid="show-badge-toggle"
Expand Down
9 changes: 9 additions & 0 deletions pages/app-layout/runtime-drawers.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React, { useContext, useRef, useState } from 'react';

import {
AppLayout,
Button,
ContentLayout,
Drawer,
Header,
Expand All @@ -14,6 +15,7 @@ import {
Toggle,
} from '~components';
import { AppLayoutProps } from '~components/app-layout';
import awsuiPlugins from '~components/internal/plugins';

import './utils/external-widget';
import AppContext, { AppContextType } from '../app/app-context';
Expand Down Expand Up @@ -99,6 +101,13 @@ export default function WithDrawers() {
<Toggle checked={hasDrawers} onChange={({ detail }) => setUrlParams({ hasDrawers: detail.checked })}>
Use Drawers
</Toggle>

<Button onClick={() => awsuiPlugins.appLayout.openDrawer('circle4-global')}>
Open a drawer without a trigger
</Button>
<Button onClick={() => awsuiPlugins.appLayout.closeDrawer('circle4-global')}>
Close a drawer without a trigger
</Button>
</SpaceBetween>
</SpaceBetween>
}
Expand Down
158 changes: 157 additions & 1 deletion pages/app-layout/utils/external-widget.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useEffect, useImperativeHandle, useState } from 'react';
import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';
import ReactDOM, { unmountComponentAtNode } from 'react-dom';

import Drawer from '~components/drawer';
Expand Down Expand Up @@ -81,3 +81,159 @@ awsuiPlugins.appLayout.registerDrawer({
},
unmountContent: container => unmountComponentAtNode(container),
});

const Counter: React.FC = ({ children }) => {
const [count, setCount] = useState(0);

return (
<div>
<span data-testid="count">{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
{children}
</div>
);
};

const AutoIncrementCounter: React.FC<{
onVisibilityChange?: (callback: (isVisible: boolean) => void) => void;
}> = ({ children, onVisibilityChange }) => {
const [count, setCount] = useState(0);
const isPaused = useRef(false);

useEffect(() => {
const interval = setInterval(() => {
if (!isPaused.current) {
setCount(prevCount => prevCount + 1);
}
}, 1000);

return () => clearInterval(interval);
}, []);

useEffect(() => {
if (onVisibilityChange) {
onVisibilityChange((isVisible: boolean) => {
isPaused.current = !isVisible;
});
}
}, [onVisibilityChange]);

return (
<div>
<h3>Auto Increment Counter</h3>
<div>Count: {count}</div>
{children}
</div>
);
};

awsuiPlugins.appLayout.registerDrawer({
id: 'circle-global',
type: 'global',
defaultActive: false,
resizable: true,
defaultSize: 350,
preserveInactiveContent: true,

ariaLabels: {
closeButton: 'Close button',
content: 'Content',
triggerButton: 'Trigger button',
resizeHandle: 'Resize handle',
},

trigger: {
iconSvg: `<svg viewBox="0 0 16 16" focusable="false">
<circle stroke-width="2" stroke="currentColor" fill="none" cx="8" cy="8" r="7" />
<circle stroke-width="2" stroke="currentColor" fill="none" cx="8" cy="8" r="3" />
</svg>`,
},

onResize: event => {
console.log('resize', event.detail);
},

mountContent: (container, mountContext) => {
ReactDOM.render(
<AutoIncrementCounter onVisibilityChange={mountContext?.onVisibilityChange}>
global widget content circle 1
</AutoIncrementCounter>,
container
);
},
unmountContent: container => unmountComponentAtNode(container),
});

awsuiPlugins.appLayout.registerDrawer({
id: 'circle2-global',
type: 'global',
defaultActive: false,
resizable: true,
defaultSize: 320,

ariaLabels: {
closeButton: 'Close button',
content: 'Content',
triggerButton: 'Trigger button',
resizeHandle: 'Resize handle',
},

trigger: {
iconSvg: `<svg viewBox="0 0 16 16" focusable="false">
<circle stroke-width="2" stroke="currentColor" fill="none" cx="8" cy="8" r="7" />
<circle stroke-width="2" stroke="currentColor" fill="none" cx="8" cy="8" r="3" />
</svg>`,
},

mountContent: container => {
ReactDOM.render(<Counter>global widget content circle 2</Counter>, container);
},
unmountContent: container => unmountComponentAtNode(container),
});

awsuiPlugins.appLayout.registerDrawer({
id: 'circle3-global',
type: 'global',
defaultActive: false,
resizable: true,
defaultSize: 320,

ariaLabels: {
closeButton: 'Close button',
content: 'Content',
triggerButton: 'Trigger button',
resizeHandle: 'Resize handle',
},

trigger: {
iconSvg: `<svg viewBox="0 0 16 16" focusable="false">
<circle stroke-width="2" stroke="currentColor" fill="none" cx="8" cy="8" r="7" />
<circle stroke-width="2" stroke="currentColor" fill="none" cx="8" cy="8" r="3" />
</svg>`,
},

mountContent: container => {
ReactDOM.render(<Counter>global widget content circle 3</Counter>, container);
},
unmountContent: container => unmountComponentAtNode(container),
});

awsuiPlugins.appLayout.registerDrawer({
id: 'circle4-global',
type: 'global',
defaultActive: false,
resizable: true,
defaultSize: 320,

ariaLabels: {
closeButton: 'Close button',
content: 'Content',
triggerButton: 'Trigger button',
resizeHandle: 'Resize handle',
},

mountContent: container => {
ReactDOM.render(<div>global widget content circle 3 (without trigger button)</div>, container);
},
unmountContent: container => unmountComponentAtNode(container),
});
4 changes: 2 additions & 2 deletions src/app-layout/__integ__/app-layout-drawers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,13 @@ describe.each(['classic', 'visual-refresh', 'visual-refresh-toolbar'] as const)(
await page.dragResizerTo({ x: width, y: 0 });
// there are different layouts between these two designs
await expect(page.getActiveDrawerWidth()).resolves.toEqual(
theme === 'visual-refresh-toolbar' ? 290 : 290 + vrBorderOffset
theme === 'visual-refresh-toolbar' ? 291 : 290 + vrBorderOffset
);
await page.dragResizerTo({ x: 0, y: 0 });
const expectedWidths = {
['classic']: 520,
['visual-refresh']: 447,
['visual-refresh-toolbar']: 592,
['visual-refresh-toolbar']: 593,
};
await expect(page.getActiveDrawerWidth()).resolves.toEqual(expectedWidths[theme]);
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ describe.each(['refresh', 'refresh-toolbar'] as Theme[])('%s', theme => {
});
}

const vrBorderOffset = theme === 'refresh' ? 1 : 0;
const drawerBorderOffset = 1;
const navigationBorderOffset = theme === 'refresh' ? 1 : 0;

describe('Default width per contentType', () => {
const testCases = [
Expand All @@ -66,8 +67,8 @@ describe.each(['refresh', 'refresh-toolbar'] as Theme[])('%s', theme => {

// Open the drawers and check their width
await page.setDrawersOpen();
await expect(page.getNavigationWidth()).resolves.toBe(navigationWidth + vrBorderOffset);
await expect(page.getToolsWidth()).resolves.toBe(toolsWidth + vrBorderOffset);
await expect(page.getNavigationWidth()).resolves.toBe(navigationWidth + navigationBorderOffset);
await expect(page.getToolsWidth()).resolves.toBe(toolsWidth + drawerBorderOffset);
})
);
}
Expand Down
113 changes: 112 additions & 1 deletion src/app-layout/__integ__/runtime-drawers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
import { BasePageObject } from '@cloudscape-design/browser-test-tools/page-objects';
import useBrowser from '@cloudscape-design/browser-test-tools/use-browser';

import createWrapper from '../../../lib/components/test-utils/selectors';
import createWrapper, { AppLayoutWrapper } from '../../../lib/components/test-utils/selectors';
import { viewports } from './constants';

const wrapper = createWrapper().findAppLayout();
const findDrawerById = (wrapper: AppLayoutWrapper, id: string) => {
return wrapper.find(`[data-testid="awsui-app-layout-drawer-${id}"]`);
};

describe.each(['classic', 'visual-refresh', 'visual-refresh-toolbar'] as const)('%s', theme => {
function setupTest(testFn: (page: BasePageObject) => Promise<void>) {
Expand Down Expand Up @@ -72,3 +75,111 @@ describe.each(['classic', 'visual-refresh', 'visual-refresh-toolbar'] as const)(
);
});
});

describe('Visual refresh toolbar only', () => {
function setupTest(testFn: (page: BasePageObject) => Promise<void>) {
return useBrowser(async browser => {
const page = new BasePageObject(browser);

await browser.url(
`#/light/app-layout/runtime-drawers?${new URLSearchParams({
hasDrawers: 'false',
hasTools: 'true',
splitPanelPosition: 'side',
visualRefresh: 'true',
appLayoutToolbar: 'true',
}).toString()}`
);
await page.waitForVisible(wrapper.findDrawerTriggerById('security').toSelector(), true);
await testFn(page);
});
}

test(
'displays only the most recently opened drawer in a full-width popup on mobile view (global drawer on top of the local one)',
setupTest(async page => {
await page.click(wrapper.findDrawerTriggerById('security').toSelector());
await page.click(wrapper.findDrawerTriggerById('circle-global').toSelector());

await page.setWindowSize(viewports.mobile);
// technically, both drawers are present in the DOM tree, but only one is visible.
// the isClickable check ensures that the drawer is actually visible
await expect(page.isClickable(findDrawerById(wrapper, 'circle-global')!.toSelector())).resolves.toBe(true);
})
);

test(
'displays only the most recently opened drawer in a full-width popup on mobile view (local drawer on top of the global one)',
setupTest(async page => {
await page.click(wrapper.findDrawerTriggerById('circle-global').toSelector());
await page.click(wrapper.findDrawerTriggerById('security').toSelector());

await page.setWindowSize(viewports.mobile);
// technically, both drawers are present in the DOM tree, but only one is visible.
// the isClickable check ensures that the drawer is actually visible
await expect(page.isClickable(findDrawerById(wrapper, 'security')!.toSelector())).resolves.toBe(true);
})
);

test(
'should open 3 drawers (1 local and 2 global) if the screen size permits',
setupTest(async page => {
await page.setWindowSize({ ...viewports.desktop, width: 1700 });
await page.click(wrapper.findDrawerTriggerById('security').toSelector());
await page.click(wrapper.findDrawerTriggerById('circle-global').toSelector());
await page.click(wrapper.findDrawerTriggerById('circle2-global').toSelector());

await expect(page.isClickable(findDrawerById(wrapper, 'security')!.toSelector())).resolves.toBe(true);
await expect(page.isClickable(findDrawerById(wrapper, 'circle-global')!.toSelector())).resolves.toBe(true);
await expect(page.isClickable(findDrawerById(wrapper, 'circle2-global')!.toSelector())).resolves.toBe(true);
})
);

describe('active drawers take up all available space on the page and a third drawer is opened', () => {
test(
'active drawers can be shrunk to accommodate a third drawer',
setupTest(async page => {
await page.setWindowSize({ ...viewports.desktop, width: 1600 });
await page.click(wrapper.findDrawerTriggerById('circle-global').toSelector());
await page.click(wrapper.findDrawerTriggerById('circle2-global').toSelector());

// resize an active drawer to take up all available space
await page.dragAndDrop(wrapper.findActiveDrawerResizeHandle().toSelector(), -600);

await page.click(wrapper.findDrawerTriggerById('security').toSelector());

await expect(page.isClickable(findDrawerById(wrapper, 'security')!.toSelector())).resolves.toBe(true);
await expect(page.isClickable(findDrawerById(wrapper, 'circle-global')!.toSelector())).resolves.toBe(true);
await expect(page.isClickable(findDrawerById(wrapper, 'circle2-global')!.toSelector())).resolves.toBe(true);
})
);

test('first opened drawer should be closed when active drawers can not be shrunk to accommodate it (1400px)', () => {
setupTest(async page => {
await page.setWindowSize({ ...viewports.desktop, width: 1400 });
await page.click(wrapper.findDrawerTriggerById('circle-global').toSelector());
await page.click(wrapper.findDrawerTriggerById('circle2-global').toSelector());
await page.click(wrapper.findDrawerTriggerById('security').toSelector());

await expect(page.isClickable(findDrawerById(wrapper, 'circle-global')!.toSelector())).resolves.toBe(false);
await expect(page.isClickable(findDrawerById(wrapper, 'security')!.toSelector())).resolves.toBe(true);
await expect(page.isClickable(findDrawerById(wrapper, 'circle2-global')!.toSelector())).resolves.toBe(true);
});
});

test('first opened drawer should be closed when active drawers can not be shrunk to accommodate it (1200px)', () => {
setupTest(async page => {
await page.setWindowSize({ ...viewports.desktop, width: 1200 });
await page.click(wrapper.findDrawerTriggerById('circle').toSelector());
await page.click(wrapper.findDrawerTriggerById('security').toSelector());
await page.click(wrapper.findDrawerTriggerById('circle-global').toSelector());
await page.click(wrapper.findDrawerTriggerById('circle2-global').toSelector());

await expect(page.isClickable(findDrawerById(wrapper, 'circle')!.toSelector())).resolves.toBe(false);
await expect(page.isClickable(findDrawerById(wrapper, 'security')!.toSelector())).resolves.toBe(false);
await expect(page.isClickable(findDrawerById(wrapper, 'circle-global')!.toSelector())).resolves.toBe(true);
await expect(page.isClickable(findDrawerById(wrapper, 'circle2-global')!.toSelector())).resolves.toBe(true);
});
});
});
});
Loading
Loading