Skip to content

Commit

Permalink
e2e tests for useOverflow logic (#2151)
Browse files Browse the repository at this point in the history
  • Loading branch information
r100-stack authored Oct 9, 2024
1 parent 36a8bbd commit 798272e
Show file tree
Hide file tree
Showing 13 changed files with 1,354 additions and 47 deletions.
25 changes: 25 additions & 0 deletions testing/e2e/app/routes/Breadcrumbs/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Breadcrumbs, Button } from '@itwin/itwinui-react';

export default function BreadcrumbsTest() {
const items = Array(5)
.fill(null)
.map((_, index) => (
<Breadcrumbs.Item key={index} data-testid='item'>
Item {index}
</Breadcrumbs.Item>
));

return (
<>
<div data-testid='container'>
<Breadcrumbs
overflowButton={(visibleCount: number) => {
return <Button styleType='borderless'>{visibleCount}</Button>;
}}
>
{items}
</Breadcrumbs>
</div>
</>
);
}
91 changes: 91 additions & 0 deletions testing/e2e/app/routes/Breadcrumbs/spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { test, expect, Page } from '@playwright/test';

test.describe('Breadcrumbs', () => {
test(`should overflow whenever there is not enough space`, async ({
page,
}) => {
await page.goto(`/Breadcrumbs`);

await expectOverflowState({
page,
expectedItemLength: 5,
expectedOverflowButtonVisibleCount: undefined,
});

await setContainerSize(page, '200px');

await expectOverflowState({
page,
expectedItemLength: 2,
expectedOverflowButtonVisibleCount: 2,
});

// should restore hidden items when space is available again
await setContainerSize(page, undefined);

await expectOverflowState({
page,
expectedItemLength: 5,
expectedOverflowButtonVisibleCount: undefined,
});
});

test(`should at minimum always show one overflow button and one item`, async ({
page,
}) => {
await page.goto(`/Breadcrumbs`);

await expectOverflowState({
page,
expectedItemLength: 5,
expectedOverflowButtonVisibleCount: undefined,
});

await setContainerSize(page, '10px');

await expectOverflowState({
page,
expectedItemLength: 1,
expectedOverflowButtonVisibleCount: 1,
});
});
});

// ----------------------------------------------------------------------------

const setContainerSize = async (page: Page, value: string | undefined) => {
await page.getByTestId('container').evaluate(
(element, args) => {
if (args.value != null) {
element.style.setProperty('width', args.value);
} else {
element.style.removeProperty('width');
}
},
{ value },
);
await page.waitForTimeout(200);
};

const expectOverflowState = async ({
page,
expectedItemLength,
expectedOverflowButtonVisibleCount,
}: {
page: Page;
expectedItemLength: number;
expectedOverflowButtonVisibleCount: number | undefined;
}) => {
const items = page.getByTestId('item');
expect(items).toHaveCount(expectedItemLength);

const overflowButton = page.locator('button');

if (expectedOverflowButtonVisibleCount != null) {
await expect(overflowButton).toHaveText(
`${expectedOverflowButtonVisibleCount}`,
);
} else {
await expect(overflowButton).not.toBeVisible();
}
};
132 changes: 118 additions & 14 deletions testing/e2e/app/routes/ButtonGroup/route.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,127 @@
import { ButtonGroup, IconButton } from '@itwin/itwinui-react';
import { Button, ButtonGroup, Flex, IconButton } from '@itwin/itwinui-react';
import { SvgPlaceholder } from '@itwin/itwinui-icons-react';
import { useSearchParams } from '@remix-run/react';
import * as React from 'react';

export default function ButtonGroupTest() {
const [searchParams] = useSearchParams();
const config = getConfigFromSearchParams(searchParams);
const { exampleType } = config;

const orientation = searchParams.get('orientation') || 'horizontal';
return exampleType === 'default' ? (
<Default config={config} />
) : (
<Overflow config={config} />
);
}

const getConfigFromSearchParams = (searchParams: URLSearchParams) => {
const exampleType = (searchParams.get('exampleType') ?? 'default') as
| 'default'
| 'overflow';
const initialProvideOverflowButton =
searchParams.get('provideOverflowButton') !== 'false';
const orientation =
(searchParams.get('orientation') as 'horizontal' | 'vertical') ||
'horizontal';
const overflowPlacement =
(searchParams.get('overflowPlacement') as 'start' | 'end') || undefined;
const showToggleProvideOverflowButton =
searchParams.get('showToggleProvideOverflowButton') === 'true';

return {
exampleType,
initialProvideOverflowButton,
orientation,
overflowPlacement,
showToggleProvideOverflowButton,
};
};

const Default = ({
config,
}: {
config: ReturnType<typeof getConfigFromSearchParams>;
}) => {
const {
initialProvideOverflowButton,
showToggleProvideOverflowButton,
orientation,
overflowPlacement,
} = config;

const [provideOverflowButton, setProvideOverflowButton] = React.useState(
initialProvideOverflowButton,
);

return (
<ButtonGroup role='toolbar' orientation={orientation as any}>
<IconButton label='Button 1'>
<SvgPlaceholder />
</IconButton>
<IconButton label='Button 2' isActive>
<SvgPlaceholder />
</IconButton>
<IconButton disabled label='Button 3'>
<SvgPlaceholder />
</IconButton>
</ButtonGroup>
<Flex flexDirection='column' alignItems='flex-start'>
{showToggleProvideOverflowButton && (
<Button
data-testid='toggle-provide-overflow-container'
onClick={() => setProvideOverflowButton((prev) => !prev)}
>
{`Toggle provide overflow container (current = ${provideOverflowButton})`}
</Button>
)}

<div id='container' style={{ background: 'hotpink' }}>
<ButtonGroup
role='toolbar'
orientation={orientation as any}
style={{
width: orientation === 'horizontal' ? '100%' : undefined,
height: orientation === 'vertical' ? '100%' : undefined,
}}
overflowPlacement={overflowPlacement}
overflowButton={
provideOverflowButton
? (firstOverflowingIndex) => {
return (
<IconButton data-testid='overflow-button'>
{firstOverflowingIndex}
</IconButton>
);
}
: undefined
}
>
<IconButton label='Button 1'>
<SvgPlaceholder />
</IconButton>
<IconButton label='Button 2' isActive>
<SvgPlaceholder />
</IconButton>
<IconButton disabled label='Button 3'>
<SvgPlaceholder />
</IconButton>
</ButtonGroup>
</div>
</Flex>
);
}
};

const Overflow = ({
config,
}: {
config: ReturnType<typeof getConfigFromSearchParams>;
}) => {
const { overflowPlacement } = config;

const buttons = [...Array(10)].map((_, index) => (
<IconButton key={index}>
<SvgPlaceholder />
</IconButton>
));

return (
<div id='container' style={{ background: 'hotpink' }}>
<ButtonGroup
overflowButton={(startIndex) => <IconButton>{startIndex}</IconButton>}
overflowPlacement={overflowPlacement}
>
{buttons}
</ButtonGroup>
</div>
);
};
Loading

0 comments on commit 798272e

Please sign in to comment.