test(picker-internal, picker-column-internal): migrate to generators (#27354)

Issue number: N/A

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Picker internal and picker column internal tests are using legacy
syntax.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Picker internal and picker column internal tests use generator syntax.


38187b744c

I updated these tests to disable multi-mode and direction testing since
the behaviors this file is testing do not vary across modes/directions.


89436784b0

- I removed the RTL screenshots here because the disabled state does not
vary across directions.


8d31eba5f2

- I removed the RTL screenshots here because the overlay rendering
behavior does not vary across directions. There is RTL behavior that we
need to test, but that is already captured in the screenshots in
`picker-internal/basic`.


d2a1531e6a

- Removed the mode and direction tests because this behavior does not
vary across modes/directions.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
This commit is contained in:
Liam DeBeasi
2023-05-03 11:22:39 -04:00
committed by GitHub
parent c98ad6f16a
commit b1369a94ae
57 changed files with 474 additions and 407 deletions

View File

@@ -1,76 +0,0 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
test.describe('picker-column-internal', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/picker-column-internal/test/basic');
});
test('should render a picker item for each item', async ({ page }) => {
const columns = page.locator('ion-picker-column-internal .picker-item:not(.picker-item-empty)');
await expect(columns).toHaveCount(24);
});
test('should render 6 empty picker items', async ({ page }) => {
const columns = page.locator('ion-picker-column-internal .picker-item-empty');
await expect(columns).toHaveCount(6);
});
test('should not have an active item when value is not set', async ({ page }) => {
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
await expect(activeColumn).toHaveCount(0);
});
test('should have an active item when value is set', async ({ page }) => {
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
el.value = '12';
});
await page.waitForChanges();
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
expect(activeColumn).not.toBeNull();
});
// TODO FW-3616
test.skip('scrolling should change the active item', async ({ page, skip }) => {
skip.browser('firefox', 'https://bugzilla.mozilla.org/show_bug.cgi?id=1766890');
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
el.scrollTop = 801;
});
await page.waitForChanges();
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
expect(await activeColumn?.innerText()).toEqual('23');
});
test('should not emit ionChange when the value is modified externally', async ({ page, skip }) => {
skip.browser('firefox', 'https://bugzilla.mozilla.org/show_bug.cgi?id=1766890');
const ionChangeSpy = await page.spyOnEvent('ionChange');
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
el.value = '12';
});
expect(ionChangeSpy).not.toHaveReceivedEvent();
});
// TODO FW-3616
test.skip('should emit ionChange when the picker is scrolled', async ({ page, skip }) => {
skip.browser('firefox', 'https://bugzilla.mozilla.org/show_bug.cgi?id=1766890');
const ionChangeSpy = await page.spyOnEvent('ionChange');
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
el.scrollTo(0, el.scrollHeight);
});
await page.waitForChanges();
await ionChangeSpy.next();
expect(ionChangeSpy).toHaveReceivedEvent();
});
});

View File

@@ -0,0 +1,81 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('picker-column-internal'), () => {
test.beforeEach(async ({ page }) => {
await page.goto('/src/components/picker-column-internal/test/basic', config);
});
test('should render a picker item for each item', async ({ page }) => {
const columns = page.locator('ion-picker-column-internal .picker-item:not(.picker-item-empty)');
await expect(columns).toHaveCount(24);
});
test('should render 6 empty picker items', async ({ page }) => {
const columns = page.locator('ion-picker-column-internal .picker-item-empty');
await expect(columns).toHaveCount(6);
});
test('should not have an active item when value is not set', async ({ page }) => {
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
await expect(activeColumn).toHaveCount(0);
});
test('should have an active item when value is set', async ({ page }) => {
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
el.value = '12';
});
await page.waitForChanges();
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
expect(activeColumn).not.toBeNull();
});
// TODO FW-3616
test.skip('scrolling should change the active item', async ({ page, skip }) => {
skip.browser('firefox', 'https://bugzilla.mozilla.org/show_bug.cgi?id=1766890');
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
el.scrollTop = 801;
});
await page.waitForChanges();
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
expect(await activeColumn?.innerText()).toEqual('23');
});
test('should not emit ionChange when the value is modified externally', async ({ page, skip }) => {
skip.browser('firefox', 'https://bugzilla.mozilla.org/show_bug.cgi?id=1766890');
const ionChangeSpy = await page.spyOnEvent('ionChange');
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
el.value = '12';
});
expect(ionChangeSpy).not.toHaveReceivedEvent();
});
// TODO FW-3616
test.skip('should emit ionChange when the picker is scrolled', async ({ page, skip }) => {
skip.browser('firefox', 'https://bugzilla.mozilla.org/show_bug.cgi?id=1766890');
const ionChangeSpy = await page.spyOnEvent('ionChange');
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
el.scrollTo(0, el.scrollHeight);
});
await page.waitForChanges();
await ionChangeSpy.next();
expect(ionChangeSpy).toHaveReceivedEvent();
});
});
});

View File

@@ -1,130 +0,0 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
test.describe('picker-column-internal: disabled', () => {
test('should not have visual regressions', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal value="b"></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a', disabled: true },
{ text: 'B', value: 'b' },
{ text: 'C', value: 'c', disabled: true }
]
</script>
`);
const picker = page.locator('ion-picker-internal');
await expect(picker).toHaveScreenshot(`picker-internal-disabled-${page.getSnapshotSettings()}.png`);
});
test('all picker items should be enabled by default', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b' },
{ text: 'C', value: 'c' }
]
</script>
`);
const pickerItems = page.locator(
'ion-picker-column-internal .picker-item:not(.picker-item-empty, .picker-item-disabled)'
);
expect(await pickerItems.count()).toBe(3);
});
test('disabled picker item should not be interactive', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b', disabled: true },
{ text: 'C', value: 'c' }
]
</script>
`);
const disabledItem = page.locator('ion-picker-column-internal .picker-item.picker-item-disabled');
await expect(disabledItem).not.toBeEnabled();
});
test('disabled picker item should not be considered active', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal value="b"></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b', disabled: true },
{ text: 'C', value: 'c' }
]
</script>
`);
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
});
test('setting the value to a disabled item should not cause that item to be active', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b', disabled: true },
{ text: 'C', value: 'c' }
]
</script>
`);
const pickerColumn = page.locator('ion-picker-column-internal');
await pickerColumn.evaluate((el: HTMLIonPickerColumnInternalElement) => (el.value = 'b'));
await page.waitForChanges();
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
await expect(disabledItem).toHaveClass(/picker-item-disabled/);
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
});
test('defaulting the value to a disabled item should not cause that item to be active', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b', disabled: true },
{ text: 'C', value: 'c' }
]
column.value = 'b'
</script>
`);
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
await expect(disabledItem).toHaveClass(/picker-item-disabled/);
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
});
});

View File

@@ -0,0 +1,161 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
/**
* This behavior does not vary across directions.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('picker-column-internal: disabled rendering'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal value="b"></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a', disabled: true },
{ text: 'B', value: 'b' },
{ text: 'C', value: 'c', disabled: true }
]
</script>
`,
config
);
const picker = page.locator('ion-picker-internal');
await expect(picker).toHaveScreenshot(screenshot(`picker-internal-disabled`));
});
});
});
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('picker-column-internal: disabled'), () => {
test('all picker items should be enabled by default', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b' },
{ text: 'C', value: 'c' }
]
</script>
`,
config
);
const pickerItems = page.locator(
'ion-picker-column-internal .picker-item:not(.picker-item-empty, .picker-item-disabled)'
);
expect(await pickerItems.count()).toBe(3);
});
test('disabled picker item should not be interactive', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b', disabled: true },
{ text: 'C', value: 'c' }
]
</script>
`,
config
);
const disabledItem = page.locator('ion-picker-column-internal .picker-item.picker-item-disabled');
await expect(disabledItem).not.toBeEnabled();
});
test('disabled picker item should not be considered active', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal value="b"></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b', disabled: true },
{ text: 'C', value: 'c' }
]
</script>
`,
config
);
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
});
test('setting the value to a disabled item should not cause that item to be active', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b', disabled: true },
{ text: 'C', value: 'c' }
]
</script>
`,
config
);
const pickerColumn = page.locator('ion-picker-column-internal');
await pickerColumn.evaluate((el: HTMLIonPickerColumnInternalElement) => (el.value = 'b'));
await page.waitForChanges();
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
await expect(disabledItem).toHaveClass(/picker-item-disabled/);
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
});
test('defaulting the value to a disabled item should not cause that item to be active', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b', disabled: true },
{ text: 'C', value: 'c' }
]
column.value = 'b'
</script>
`,
config
);
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
await expect(disabledItem).toHaveClass(/picker-item-disabled/);
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
});
});
});

View File

@@ -1,13 +0,0 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
test.describe('picker-internal: a11y', () => {
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/picker-internal/test/a11y`);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
});

View File

@@ -0,0 +1,15 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs().forEach(({ title, config }) => {
test.describe(title('picker-internal: a11y'), () => {
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/picker-internal/test/a11y`, config);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
});
});

View File

@@ -1,21 +1,88 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('picker-internal', () => {
// TODO: FW-3020
test.skip('inline pickers should not have visual regression', async ({ page }) => {
await page.goto(`/src/components/picker-internal/test/basic`);
// TODO: FW-3020
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('picker-internal: rendering'), () => {
test.skip('inline pickers should not have visual regression', async ({ page }) => {
await page.goto(`/src/components/picker-internal/test/basic`, config);
await page.setIonViewport();
await page.setIonViewport();
await expect(page).toHaveScreenshot(`picker-internal-inline-diff-${page.getSnapshotSettings()}.png`, {
fullPage: true,
await expect(page).toHaveScreenshot(screenshot(`picker-internal-inline-diff`), {
fullPage: true,
});
});
});
});
test.describe('picker-internal: focus', () => {
/**
* This behavior does not vary across modes.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('picker-internal: overlay rendering'), () => {
test('popover: should not have visual regression', async ({ page }) => {
await page.goto(`/src/components/picker-internal/test/basic`, config);
const button = page.locator('#popover');
const didPresent = await page.spyOnEvent('ionPopoverDidPresent');
const pickerInternal = page.locator('ion-popover ion-picker-internal');
await button.click();
await didPresent.next();
await expect(pickerInternal).toBeVisible();
const popoverContent = page.locator('ion-popover .ion-delegate-host');
await expect(popoverContent).toHaveScreenshot(screenshot(`picker-internal-popover-diff`), {
/**
* Animations must be enabled to capture the screenshot.
* By default, animations are disabled with toHaveScreenshot,
* and when capturing the screenshot will call animation.finish().
* This will cause the popover to close and the screenshot capture
* to be invalid.
*/
animations: 'allow',
});
});
test('modal: should not have visual regression', async ({ page }) => {
await page.goto('/src/components/picker-internal/test/basic', config);
const button = page.locator('#modal');
const didPresent = await page.spyOnEvent('ionModalDidPresent');
const pickerInternal = page.locator('ion-modal ion-picker-internal');
await button.click();
await didPresent.next();
await expect(pickerInternal).toBeVisible();
const modalContent = page.locator('ion-modal .ion-delegate-host');
await expect(modalContent).toHaveScreenshot(screenshot(`picker-internal-modal-diff`), {
/**
* Animations must be enabled to capture the screenshot.
* By default, animations are disabled with toHaveScreenshot,
* and when capturing the screenshot will call animation.finish().
* This will cause the modal to close and the screenshot capture
* to be invalid.
*/
animations: 'allow',
});
});
});
});
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('picker-internal: focus'), () => {
test.beforeEach(async ({ page }) => {
await page.setContent(`
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal value="full-stack" id="first"></ion-picker-column-internal>
<ion-picker-column-internal value="onion" id="second"></ion-picker-column-internal>
@@ -39,7 +106,9 @@ test.describe('picker-internal', () => {
{ text: 'Artichoke', value: 'artichoke' },
];
</script>
`);
`,
config
);
});
test('tabbing should correctly move focus between columns', async ({ page }) => {
@@ -71,58 +140,4 @@ test.describe('picker-internal', () => {
await expect(firstColumn).toBeFocused();
});
});
test.describe('within overlay:', () => {
test('popover: should not have visual regression', async ({ page }) => {
await page.goto(`/src/components/picker-internal/test/basic`);
const button = page.locator('#popover');
const didPresent = await page.spyOnEvent('ionPopoverDidPresent');
const pickerInternal = page.locator('ion-popover ion-picker-internal');
await button.click();
await didPresent.next();
await expect(pickerInternal).toBeVisible();
const popoverContent = page.locator('ion-popover .ion-delegate-host');
await expect(popoverContent).toHaveScreenshot(`picker-internal-popover-diff-${page.getSnapshotSettings()}.png`, {
/**
* Animations must be enabled to capture the screenshot.
* By default, animations are disabled with toHaveScreenshot,
* and when capturing the screenshot will call animation.finish().
* This will cause the popover to close and the screenshot capture
* to be invalid.
*/
animations: 'allow',
});
});
test('modal: should not have visual regression', async ({ page }) => {
await page.goto('/src/components/picker-internal/test/basic');
const button = page.locator('#modal');
const didPresent = await page.spyOnEvent('ionModalDidPresent');
const pickerInternal = page.locator('ion-modal ion-picker-internal');
await button.click();
await didPresent.next();
await expect(pickerInternal).toBeVisible();
const modalContent = page.locator('ion-modal .ion-delegate-host');
await expect(modalContent).toHaveScreenshot(`picker-internal-modal-diff-${page.getSnapshotSettings()}.png`, {
/**
* Animations must be enabled to capture the screenshot.
* By default, animations are disabled with toHaveScreenshot,
* and when capturing the screenshot will call animation.finish().
* This will cause the modal to close and the screenshot capture
* to be invalid.
*/
animations: 'allow',
});
});
});
});

View File

@@ -1,123 +0,0 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import type { E2ELocator } from '@utils/test/playwright/page/utils/locator';
test.describe('picker-internal: keyboard entry', () => {
test('should scroll to and update the value prop for a single column', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: '01', value: 1 },
{ text: '02', value: 2 },
{ text: '03', value: 3 },
{ text: '04', value: 4 },
{ text: '05', value: 5 }
];
column.value = 5;
column.numericInput = true;
</script>
`);
const column = page.locator('ion-picker-column-internal');
const ionChange = await page.spyOnEvent('ionChange');
await column.focus();
await page.keyboard.press('Digit2');
await expect(ionChange).toHaveReceivedEventDetail({ text: '02', value: 2 });
await expect(column).toHaveJSProperty('value', 2);
});
test('should scroll to and update the value prop for multiple columns', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal id="first"></ion-picker-column-internal>
<ion-picker-column-internal id="second"></ion-picker-column-internal>
</ion-picker-internal>
<script>
const firstColumn = document.querySelector('ion-picker-column-internal#first');
firstColumn.items = [
{ text: '01', value: 1 },
{ text: '02', value: 2 },
{ text: '03', value: 3 },
{ text: '04', value: 4 },
{ text: '05', value: 5 }
];
firstColumn.value = 5;
firstColumn.numericInput = true;
const secondColumn = document.querySelector('ion-picker-column-internal#second');
secondColumn.items = [
{ text: '20', value: 20 },
{ text: '21', value: 21 },
{ text: '22', value: 22 },
{ text: '23', value: 23 },
{ text: '24', value: 24 }
];
secondColumn.value = 22;
secondColumn.numericInput = true;
</script>
`);
const firstColumn = page.locator('ion-picker-column-internal#first');
const secondColumn = page.locator('ion-picker-column-internal#second');
const highlight = page.locator('ion-picker-internal .picker-highlight');
const firstIonChange = await (firstColumn as E2ELocator).spyOnEvent('ionChange');
const secondIonChange = await (secondColumn as E2ELocator).spyOnEvent('ionChange');
const box = await highlight.boundingBox();
if (box !== null) {
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
}
await expect(firstColumn).toHaveClass(/picker-column-active/);
await expect(secondColumn).toHaveClass(/picker-column-active/);
await page.keyboard.press('Digit2');
await expect(firstIonChange).toHaveReceivedEventDetail({ text: '02', value: 2 });
await expect(firstColumn).toHaveJSProperty('value', 2);
await page.keyboard.press('Digit2+Digit4');
await expect(secondIonChange).toHaveReceivedEventDetail({ text: '24', value: 24 });
await expect(secondColumn).toHaveJSProperty('value', 24);
});
test('should select 00', async ({ page }) => {
await page.setContent(`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: '00', value: 12 },
{ text: '01', value: 1 },
{ text: '02', value: 2 },
{ text: '03', value: 3 },
{ text: '04', value: 4 },
{ text: '05', value: 5 }
];
column.value = 5;
column.numericInput = true;
</script>
`);
const column = page.locator('ion-picker-column-internal');
const ionChange = await page.spyOnEvent('ionChange');
await column.focus();
await page.keyboard.press('Digit0');
await expect(ionChange).toHaveReceivedEventDetail({ text: '00', value: 12 });
await expect(column).toHaveJSProperty('value', 12);
});
});

View File

@@ -0,0 +1,137 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
import type { E2ELocator } from '@utils/test/playwright/page/utils/locator';
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('picker-internal: keyboard entry'), () => {
test('should scroll to and update the value prop for a single column', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: '01', value: 1 },
{ text: '02', value: 2 },
{ text: '03', value: 3 },
{ text: '04', value: 4 },
{ text: '05', value: 5 }
];
column.value = 5;
column.numericInput = true;
</script>
`,
config
);
const column = page.locator('ion-picker-column-internal');
const ionChange = await page.spyOnEvent('ionChange');
await column.focus();
await page.keyboard.press('Digit2');
await expect(ionChange).toHaveReceivedEventDetail({ text: '02', value: 2 });
await expect(column).toHaveJSProperty('value', 2);
});
test('should scroll to and update the value prop for multiple columns', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal id="first"></ion-picker-column-internal>
<ion-picker-column-internal id="second"></ion-picker-column-internal>
</ion-picker-internal>
<script>
const firstColumn = document.querySelector('ion-picker-column-internal#first');
firstColumn.items = [
{ text: '01', value: 1 },
{ text: '02', value: 2 },
{ text: '03', value: 3 },
{ text: '04', value: 4 },
{ text: '05', value: 5 }
];
firstColumn.value = 5;
firstColumn.numericInput = true;
const secondColumn = document.querySelector('ion-picker-column-internal#second');
secondColumn.items = [
{ text: '20', value: 20 },
{ text: '21', value: 21 },
{ text: '22', value: 22 },
{ text: '23', value: 23 },
{ text: '24', value: 24 }
];
secondColumn.value = 22;
secondColumn.numericInput = true;
</script>
`,
config
);
const firstColumn = page.locator('ion-picker-column-internal#first');
const secondColumn = page.locator('ion-picker-column-internal#second');
const highlight = page.locator('ion-picker-internal .picker-highlight');
const firstIonChange = await (firstColumn as E2ELocator).spyOnEvent('ionChange');
const secondIonChange = await (secondColumn as E2ELocator).spyOnEvent('ionChange');
const box = await highlight.boundingBox();
if (box !== null) {
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
}
await expect(firstColumn).toHaveClass(/picker-column-active/);
await expect(secondColumn).toHaveClass(/picker-column-active/);
await page.keyboard.press('Digit2');
await expect(firstIonChange).toHaveReceivedEventDetail({ text: '02', value: 2 });
await expect(firstColumn).toHaveJSProperty('value', 2);
await page.keyboard.press('Digit2+Digit4');
await expect(secondIonChange).toHaveReceivedEventDetail({ text: '24', value: 24 });
await expect(secondColumn).toHaveJSProperty('value', 24);
});
test('should select 00', async ({ page }) => {
await page.setContent(
`
<ion-picker-internal>
<ion-picker-column-internal></ion-picker-column-internal>
</ion-picker-internal>
<script>
const column = document.querySelector('ion-picker-column-internal');
column.items = [
{ text: '00', value: 12 },
{ text: '01', value: 1 },
{ text: '02', value: 2 },
{ text: '03', value: 3 },
{ text: '04', value: 4 },
{ text: '05', value: 5 }
];
column.value = 5;
column.numericInput = true;
</script>
`,
config
);
const column = page.locator('ion-picker-column-internal');
const ionChange = await page.spyOnEvent('ionChange');
await column.focus();
await page.keyboard.press('Digit0');
await expect(ionChange).toHaveReceivedEventDetail({ text: '00', value: 12 });
await expect(column).toHaveJSProperty('value', 12);
});
});
});