Skip to content

Commit

Permalink
Merge branch 'r/unit-tests-to-e2e' into r/overflow-container-without-…
Browse files Browse the repository at this point in the history
…new-algorithm
  • Loading branch information
r100-stack committed Sep 30, 2024
2 parents 6dedd71 + 3e82ea5 commit d615fd0
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 29 deletions.
103 changes: 81 additions & 22 deletions testing/e2e/app/routes/ComboBox/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,81 @@ import { useSearchParams } from '@remix-run/react';
import * as React from 'react';

export default function ComboBoxTest() {
const config = getConfigFromSearchParams();

if (config.exampleType === 'overflow') {
return <Overflow />;
}
return <Default config={config} />;
}

const Default = ({
config,
}: {
config: ReturnType<typeof getConfigFromSearchParams>;
}) => {
const {
initialValue,
multiple,
options,
showChangeValueButton,
virtualization,
} = config;
const [value, setValue] = React.useState(initialValue);

return (
<div data-testid='container'>
{showChangeValueButton && (
<Button
data-testid='change-value-to-first-option-button'
onClick={() => setValue(multiple ? [0] : 0)}
>
Change value to just the first option
</Button>
)}

<ComboBox
options={options}
id='test-component'
value={value as any}
multiple={multiple}
enableVirtualization={virtualization}
/>
</div>
);
};

const Overflow = () => {
const data = new Array(15).fill(0).map((_, i) => ({
label: `option ${i}`,
value: i,
}));
const widths = new Array(10).fill(0).map((_, i) => 790 + i * 3);

return (
<>
{widths.slice(0, 10).map((width) => (
<ComboBox
key={width}
style={{ width: `${width}px`, maxWidth: '80vw' }}
multiple={true}
options={data}
value={data.map((x) => x.value)}
/>
))}
</>
);
};

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

function getConfigFromSearchParams() {
const [searchParams] = useSearchParams();

const exampleType = searchParams.get('exampleType') as
| 'default'
| 'overflow'
| undefined;
const virtualization = searchParams.get('virtualization') === 'true';
const multiple = searchParams.get('multiple') === 'true';
const showChangeValueButton =
Expand All @@ -30,26 +103,12 @@ export default function ComboBoxTest() {
: (JSON.parse(initialValueSearchParam) as number | number[])
: undefined;

const [value, setValue] = React.useState(initialValue);

return (
<div data-testid='container'>
{showChangeValueButton && (
<Button
data-testid='change-value-to-first-option-button'
onClick={() => setValue(multiple ? [0] : 0)}
>
Change value to just the first option
</Button>
)}

<ComboBox
options={options}
id='test-component'
value={value as any}
multiple={multiple}
enableVirtualization={virtualization}
/>
</div>
);
return {
exampleType,
virtualization,
multiple,
showChangeValueButton,
options,
initialValue,
};
}
39 changes: 32 additions & 7 deletions testing/e2e/app/routes/ComboBox/spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test('should select multiple options', async ({ page }) => {
}

const tags = getSelectTagContainerTags(page);
expect(tags).toHaveCount(options.length);
await expect(tags).toHaveCount(options.length);

for (let i = 0; i < (await tags.count()); i++) {
await expect(tags.nth(i)).toHaveText(
Expand All @@ -44,15 +44,15 @@ test('should select multiple options', async ({ page }) => {

// Should change internal state when the value prop changes
if (multiple) {
expect(tags).toHaveCount(defaultOptions.length);
await expect(tags).toHaveCount(defaultOptions.length);

for (let i = 0; i < (await tags.count()); i++) {
await expect(tags.nth(i)).toHaveText(defaultOptions[i].label);
}

await page.getByTestId('change-value-to-first-option-button').click();

expect(tags).toHaveCount(1);
await expect(tags).toHaveCount(1);
await expect(tags.first()).toHaveText(defaultOptions[0].label);
} else {
await expect(page.locator('input')).toHaveValue('Item 11');
Expand All @@ -66,14 +66,39 @@ test('should select multiple options', async ({ page }) => {
await page.getByRole('option').nth(3).click();

if (multiple) {
expect(tags).toHaveCount(1);
await expect(tags).toHaveCount(1);
await expect(tags.first()).toHaveText(defaultOptions[0].label);
} else {
await expect(page.locator('input')).toHaveValue('Item 0');
}
});
});

test('should not have flickering tags (fixes #2112)', async ({ page }) => {
await page.goto('/ComboBox?exampleType=overflow');

const selectTagContainers = page.locator(
"[role='combobox'] + div:first-of-type",
);

// Wait for page to stabilize
await expect(selectTagContainers).toHaveCount(10);
for (let i = 0; i < 10; i++) {
await expect(selectTagContainers.nth(i).locator('> span')).toHaveCount(
i < 5 ? 6 : 7,
);
}

// The number of items should not change with time (i.e. no flickering)
for (let iteration = 0; iteration < 10; iteration++) {
for (let i = 0; i < 10; i++) {
expect(selectTagContainers.nth(i).locator('> span')).toHaveCount(
i < 5 ? 6 : 7,
);
}
}
});

test.describe('ComboBox (virtualization)', () => {
test('should support keyboard navigation when virtualization is enabled', async ({
page,
Expand Down Expand Up @@ -341,14 +366,14 @@ const expectOverflowState = async ({
expectedLastTagTextContent: string | undefined;
}) => {
const tags = getSelectTagContainerTags(page);
expect(tags).toHaveCount(expectedItemLength);
await expect(tags).toHaveCount(expectedItemLength);

const lastTag = tags.nth((await tags.count()) - 1);
const lastTag = tags.last();

if (expectedLastTagTextContent != null) {
await expect(lastTag).toHaveText(expectedLastTagTextContent);
} else {
expect(tags).toHaveCount(0);
await expect(tags).toHaveCount(0);
}
};

Expand Down

0 comments on commit d615fd0

Please sign in to comment.