Merge remote-tracking branch 'origin/main' into chore/sync-with-main-5-3

This commit is contained in:
Sean Perkins
2023-05-03 13:38:03 -04:00
2722 changed files with 42605 additions and 10074 deletions

View File

@ -75,8 +75,14 @@ input {
height: 100%;
}
:host(.in-item[slot="start"]:not(.legacy-radio)),
:host(.in-item[slot="end"]:not(.legacy-radio)) {
/**
* Radio can be slotted
* in components such as item and
* toolbar which is why we do not
* limit the below behavior to just ion-item.
*/
:host([slot="start"]:not(.legacy-radio)),
:host([slot="end"]:not(.legacy-radio)) {
width: auto;
}

View File

@ -1,41 +1,97 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('radio: a11y', () => {
test.beforeEach(async ({ skip }) => {
skip.rtl();
skip.mode('md');
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('radio: a11y'), () => {
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/radio/test/a11y`, config);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
});
test('should not have accessibility violations', async ({ page }) => {
await page.goto(`/src/components/radio/test/a11y`);
// TODO: FW-4155 - Enable tests once tab behavior is fixed for modern syntax.
test.describe.skip(title('radio: keyboard navigation'), () => {
test.beforeEach(async ({ page }) => {
await page.setContent(
`
<ion-app>
<ion-content>
<ion-list>
<ion-radio-group id="first-group" value="huey">
<ion-item>
<ion-radio value="huey">Huey</ion-radio>
</ion-item>
<ion-item>
<ion-radio value="dewey">Dewey</ion-radio>
</ion-item>
<ion-item>
<ion-radio value="fooey" disabled>Fooey</ion-radio>
</ion-item>
<ion-item>
<ion-radio value="louie">Louie</ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
<ion-list>
<ion-radio-group id="second-group" value="huey">
<ion-item>
<ion-radio value="huey">Huey</ion-radio>
</ion-item>
<ion-item>
<ion-radio value="dewey">Dewey</ion-radio>
</ion-item>
<ion-item>
<ion-radio value="fooey" disabled>Fooey</ion-radio>
</ion-item>
<ion-item>
<ion-radio value="louie">Louie</ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
</ion-content>
</ion-app>
`,
config
);
});
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
test('tabbing should switch between radio groups', async ({ page, pageUtils }) => {
const firstGroupRadios = page.locator('#first-group ion-radio');
const secondGroupRadios = page.locator('#second-group ion-radio');
// TODO FW-3747
test.skip('using arrow keys should move between enabled radios within group', async ({ page, browserName }) => {
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
await page.goto(`/src/components/radio/test/a11y`);
await pageUtils.pressKeys('Tab');
await expect(firstGroupRadios.nth(0)).toBeFocused();
const firstGroupRadios = page.locator('#first-group ion-radio');
await pageUtils.pressKeys('Tab');
await expect(secondGroupRadios.nth(0)).toBeFocused();
await page.keyboard.press(tabKey);
await expect(firstGroupRadios.nth(0)).toBeFocused();
await pageUtils.pressKeys('shift+Tab');
await expect(firstGroupRadios.nth(0)).toBeFocused();
});
test('using arrow keys should move between enabled radios within group', async ({ page, pageUtils }) => {
const firstGroupRadios = page.locator('#first-group ion-radio');
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(1)).toBeFocused();
await pageUtils.pressKeys('Tab');
await expect(firstGroupRadios.nth(0)).toBeFocused();
// firstGroupRadios.nth(2) is disabled so it should not receive focus.
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(3)).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(1)).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(0)).toBeFocused();
// firstGroupRadios.nth(2) is disabled so it should not receive focus.
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(3)).toBeFocused();
await page.keyboard.press('ArrowUp');
await expect(firstGroupRadios.nth(3)).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(0)).toBeFocused();
await page.keyboard.press('ArrowUp');
await expect(firstGroupRadios.nth(3)).toBeFocused();
});
});
});

View File

@ -1,29 +1,34 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('radio: color', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('should apply color when checked', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio color="danger" value="1">Label</ion-radio>
</ion-radio-group>
`);
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('radio: color'), () => {
test('should apply color when checked', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio color="danger" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(`radio-color-checked-${page.getSnapshotSettings()}.png`);
});
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-color-checked`));
});
test('should not apply color when unchecked', async ({ page }) => {
await page.setContent(`
<ion-radio-group>
<ion-radio color="danger" value="1">Label</ion-radio>
</ion-radio-group>
`);
test('should not apply color when unchecked', async ({ page }) => {
await page.setContent(
`
<ion-radio-group>
<ion-radio color="danger" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(`radio-color-unchecked-${page.getSnapshotSettings()}.png`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-color-unchecked`));
});
});
});

View File

@ -1,31 +1,39 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('radio: item', () => {
test('should render correctly in list', async ({ page }) => {
await page.setContent(`
<ion-list>
<ion-radio-group>
<ion-item>
<ion-radio>Enable Notifications</ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
`);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(`toggle-list-${page.getSnapshotSettings()}.png`);
});
test('should render correctly in inset list', async ({ page }) => {
await page.setContent(`
<ion-list inset="true">
<ion-radio-group>
<ion-item>
<ion-radio>Enable Notifications</ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
`);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(`radio-inset-list-${page.getSnapshotSettings()}.png`);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('radio: item'), () => {
test('should render correctly in list', async ({ page }) => {
await page.setContent(
`
<ion-list>
<ion-radio-group>
<ion-item>
<ion-radio>Enable Notifications</ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
`,
config
);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(screenshot(`toggle-list`));
});
test('should render correctly in inset list', async ({ page }) => {
await page.setContent(
`
<ion-list inset="true">
<ion-radio-group>
<ion-item>
<ion-radio>Enable Notifications</ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
`,
config
);
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(screenshot(`radio-inset-list`));
});
});
});

View File

@ -1,5 +1,5 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
/**
* By default ion-radio only takes up
@ -9,119 +9,133 @@ import { test } from '@utils/test/playwright';
* we set the width of the radio so we can
* see the justification results.
*/
test.describe('radio: label', () => {
test.describe('radio: start placement', () => {
test('should render a start justification with label in the start position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="start" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(
`radio-label-start-justify-start-${page.getSnapshotSettings()}.png`
);
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('radio: label'), () => {
test.describe('radio: start placement', () => {
test('should render a start justification with label in the start position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="start" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-start-justify-start`));
});
test('should render an end justification with label in the start position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="end" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-start-justify-end`));
});
test('should render a space between justification with label in the start position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="space-between" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-start-justify-space-between`));
});
});
test('should render an end justification with label in the start position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="end" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(
`radio-label-start-justify-end-${page.getSnapshotSettings()}.png`
);
test.describe('radio: end placement', () => {
test('should render a start justification with label in the end position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="start" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-end-justify-start`));
});
test('should render an end justification with label in the end position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="end" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-end-justify-end`));
});
test('should render a space between justification with label in the end position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="space-between" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-end-justify-space-between`));
});
});
test('should render a space between justification with label in the start position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="space-between" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(
`radio-label-start-justify-space-between-${page.getSnapshotSettings()}.png`
);
});
});
test.describe('radio: fixed placement', () => {
test('should render a start justification with label in the fixed position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="start" style="width: 200px" value="1">This is a long label</ion-radio>
</ion-radio-group>
`,
config
);
test.describe('radio: end placement', () => {
test('should render a start justification with label in the end position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="start" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-fixed-justify-start`));
});
test('should render an end justification with label in the fixed position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="end" style="width: 200px" value="1">This is a long label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(
`radio-label-end-justify-start-${page.getSnapshotSettings()}.png`
);
});
test('should render an end justification with label in the end position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="end" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-fixed-justify-end`));
});
test('should render a space between justification with label in the fixed position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="space-between" style="width: 200px" value="1">This is a long label</ion-radio>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(`radio-label-end-justify-end-${page.getSnapshotSettings()}.png`);
});
test('should render a space between justification with label in the end position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="space-between" style="width: 200px" value="1">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(
`radio-label-end-justify-space-between-${page.getSnapshotSettings()}.png`
);
});
});
test.describe('radio: fixed placement', () => {
test('should render a start justification with label in the fixed position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="start" style="width: 200px" value="1">This is a long label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(
`radio-label-fixed-justify-start-${page.getSnapshotSettings()}.png`
);
});
test('should render an end justification with label in the fixed position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="end" style="width: 200px" value="1">This is a long label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(
`radio-label-fixed-justify-end-${page.getSnapshotSettings()}.png`
);
});
test('should render a space between justification with label in the fixed position', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="space-between" style="width: 200px" value="1">This is a long label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(
`radio-label-fixed-justify-space-between-${page.getSnapshotSettings()}.png`
);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-label-fixed-justify-space-between`));
});
});
});
});

View File

@ -1,47 +1,46 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
// TODO FW-3747
test.describe.skip('radio: a11y', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('tabbing should switch between radio groups', async ({ page, browserName }) => {
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
await page.goto(`/src/components/radio/test/legacy/a11y`);
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('radio: a11y'), () => {
test('tabbing should switch between radio groups', async ({ page, pageUtils }) => {
await page.goto(`/src/components/radio/test/legacy/a11y`, config);
const firstGroupRadios = page.locator('#first-group ion-radio');
const secondGroupRadios = page.locator('#second-group ion-radio');
const firstGroupRadios = page.locator('#first-group ion-radio');
const secondGroupRadios = page.locator('#second-group ion-radio');
await page.keyboard.press(tabKey);
await expect(firstGroupRadios.nth(0)).toBeFocused();
await pageUtils.pressKeys('Tab');
await expect(firstGroupRadios.nth(0)).toBeFocused();
await page.keyboard.press(tabKey);
await expect(secondGroupRadios.nth(0)).toBeFocused();
await pageUtils.pressKeys('Tab');
await expect(secondGroupRadios.nth(0)).toBeFocused();
await page.keyboard.press(`Shift+${tabKey}`);
await expect(firstGroupRadios.nth(0)).toBeFocused();
});
test('using arrow keys should move between enabled radios within group', async ({ page, browserName }) => {
const tabKey = browserName === 'webkit' ? 'Alt+Tab' : 'Tab';
await page.goto(`/src/components/radio/test/legacy/a11y`);
await pageUtils.pressKeys('shift+Tab');
await expect(firstGroupRadios.nth(0)).toBeFocused();
});
test('using arrow keys should move between enabled radios within group', async ({ page, pageUtils }) => {
await page.goto(`/src/components/radio/test/legacy/a11y`, config);
const firstGroupRadios = page.locator('#first-group ion-radio');
const firstGroupRadios = page.locator('#first-group ion-radio');
await page.keyboard.press(tabKey);
await expect(firstGroupRadios.nth(0)).toBeFocused();
await pageUtils.pressKeys('Tab');
await expect(firstGroupRadios.nth(0)).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(1)).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(1)).toBeFocused();
// firstGroupRadios.nth(2) is disabled so it should not receive focus.
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(3)).toBeFocused();
// firstGroupRadios.nth(2) is disabled so it should not receive focus.
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(3)).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(0)).toBeFocused();
await page.keyboard.press('ArrowDown');
await expect(firstGroupRadios.nth(0)).toBeFocused();
await page.keyboard.press('ArrowUp');
await expect(firstGroupRadios.nth(3)).toBeFocused();
await page.keyboard.press('ArrowUp');
await expect(firstGroupRadios.nth(3)).toBeFocused();
});
});
});

View File

@ -1,137 +1,156 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('radio: rendering', () => {
test('should correctly render an unchecked radio group', async ({ page }) => {
await page.setContent(`
<ion-radio-group>
<ion-item>
<ion-label>Pepperoni</ion-label>
<ion-radio slot="start" value="pepperoni"></ion-radio>
</ion-item>
configs().forEach(({ title, screenshot, config }) => {
test.describe(title('radio: rendering'), () => {
test('should correctly render an unchecked radio group', async ({ page }) => {
await page.setContent(
`
<ion-radio-group>
<ion-item>
<ion-label>Pepperoni</ion-label>
<ion-radio slot="start" value="pepperoni"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Sausage</ion-label>
<ion-radio slot="start" value="sausage"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Sausage</ion-label>
<ion-radio slot="start" value="sausage"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Pineapple</ion-label>
<ion-radio slot="start" value="pineapple"></ion-radio>
</ion-item>
</ion-radio-group>
`);
<ion-item>
<ion-label>Pineapple</ion-label>
<ion-radio slot="start" value="pineapple"></ion-radio>
</ion-item>
</ion-radio-group>
`,
config
);
const radioGroup = page.locator('ion-radio-group');
await expect(radioGroup).toHaveScreenshot(`radio-group-unchecked-${page.getSnapshotSettings()}.png`);
});
test('should correctly render a checked radio group', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="sausage">
<ion-item>
<ion-label>Pepperoni</ion-label>
<ion-radio slot="start" value="pepperoni"></ion-radio>
</ion-item>
const radioGroup = page.locator('ion-radio-group');
await expect(radioGroup).toHaveScreenshot(screenshot(`radio-group-unchecked`));
});
test('should correctly render a checked radio group', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="sausage">
<ion-item>
<ion-label>Pepperoni</ion-label>
<ion-radio slot="start" value="pepperoni"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Sausage</ion-label>
<ion-radio slot="start" value="sausage"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Sausage</ion-label>
<ion-radio slot="start" value="sausage"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Pineapple</ion-label>
<ion-radio slot="start" value="pineapple"></ion-radio>
</ion-item>
</ion-radio-group>
`);
<ion-item>
<ion-label>Pineapple</ion-label>
<ion-radio slot="start" value="pineapple"></ion-radio>
</ion-item>
</ion-radio-group>
`,
config
);
const radioGroup = page.locator('ion-radio-group');
await expect(radioGroup).toHaveScreenshot(`radio-group-checked-${page.getSnapshotSettings()}.png`);
});
test('should allow shadow parts to be styled', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="sausage">
<ion-item>
<ion-label>Pepperoni</ion-label>
<ion-radio slot="start" value="pepperoni"></ion-radio>
</ion-item>
const radioGroup = page.locator('ion-radio-group');
await expect(radioGroup).toHaveScreenshot(screenshot(`radio-group-checked`));
});
test('should allow shadow parts to be styled', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="sausage">
<ion-item>
<ion-label>Pepperoni</ion-label>
<ion-radio slot="start" value="pepperoni"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Sausage</ion-label>
<ion-radio slot="start" value="sausage"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Sausage</ion-label>
<ion-radio slot="start" value="sausage"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Pineapple</ion-label>
<ion-radio slot="start" value="pineapple"></ion-radio>
</ion-item>
</ion-radio-group>
<ion-item>
<ion-label>Pineapple</ion-label>
<ion-radio slot="start" value="pineapple"></ion-radio>
</ion-item>
</ion-radio-group>
<style>
ion-radio::part(container) {
background: rgba(255, 0, 0, 0.3);
border-color: darkred;
}
<style>
ion-radio::part(container) {
background: rgba(255, 0, 0, 0.3);
border-color: darkred;
}
ion-radio::part(mark) {
background: hotpink;
}
</style>
`);
ion-radio::part(mark) {
background: hotpink;
}
</style>
`,
config
);
const radioGroup = page.locator('ion-radio-group');
await expect(radioGroup).toHaveScreenshot(`radio-group-part-${page.getSnapshotSettings()}.png`);
});
test('should apply color correctly', async ({ page }) => {
await page.setContent(`
<ion-radio slot="start" value="pepperoni" color="success"></ion-radio>
`);
const radioGroup = page.locator('ion-radio-group');
await expect(radioGroup).toHaveScreenshot(screenshot(`radio-group-part`));
});
test('should apply color correctly', async ({ page }) => {
await page.setContent(
`
<ion-radio slot="start" value="pepperoni" color="success"></ion-radio>
`,
config
);
const radio = page.locator('ion-radio');
await radio.click();
await page.waitForChanges();
await expect(radio).toHaveScreenshot(`radio-color-${page.getSnapshotSettings()}.png`, { animations: 'disabled' });
const radio = page.locator('ion-radio');
await radio.click();
await page.waitForChanges();
await expect(radio).toHaveScreenshot(screenshot(`radio-color`));
});
});
});
test.describe('radio: interaction', () => {
test.beforeEach(({ skip }) => {
skip.rtl();
});
test('radio should be checked when activated', async ({ page }) => {
await page.setContent(`
<ion-radio-group>
<ion-item>
<ion-label>Pepperoni</ion-label>
<ion-radio slot="start" value="pepperoni"></ion-radio>
</ion-item>
</ion-radio-group>
`);
configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('radio: interaction'), () => {
test('radio should be checked when activated', async ({ page }) => {
await page.setContent(
`
<ion-radio-group>
<ion-item>
<ion-label>Pepperoni</ion-label>
<ion-radio slot="start" value="pepperoni"></ion-radio>
</ion-item>
</ion-radio-group>
`,
config
);
const radio = page.locator('ion-radio');
const radioGroup = page.locator('ion-radio-group');
const radio = page.locator('ion-radio');
const radioGroup = page.locator('ion-radio-group');
await expect(radio.locator('input')).toHaveJSProperty('checked', false);
await expect(radioGroup).toHaveJSProperty('value', undefined);
await expect(radio.locator('input')).toHaveJSProperty('checked', false);
await expect(radioGroup).toHaveJSProperty('value', undefined);
await radio.click();
await page.waitForChanges();
await radio.click();
await page.waitForChanges();
await expect(radio.locator('input')).toHaveJSProperty('checked', true);
await expect(radioGroup).toHaveJSProperty('value', 'pepperoni');
});
test('radio should be checked when activated even without a radio group', async ({ page }) => {
await page.setContent(`
<ion-radio slot="start" value="pepperoni"></ion-radio>
`);
await expect(radio.locator('input')).toHaveJSProperty('checked', true);
await expect(radioGroup).toHaveJSProperty('value', 'pepperoni');
});
test('radio should be checked when activated even without a radio group', async ({ page }) => {
await page.setContent(
`
<ion-radio slot="start" value="pepperoni"></ion-radio>
`,
config
);
const radio = page.locator('ion-radio');
const radio = page.locator('ion-radio');
await expect(radio.locator('input')).toHaveJSProperty('checked', false);
await expect(radio.locator('input')).toHaveJSProperty('checked', false);
await radio.click();
await page.waitForChanges();
await radio.click();
await page.waitForChanges();
await expect(radio.locator('input')).toHaveJSProperty('checked', true);
await expect(radio.locator('input')).toHaveJSProperty('checked', true);
});
});
});

View File

@ -1,39 +1,48 @@
import { expect } from '@playwright/test';
import { test } from '@utils/test/playwright';
import { configs, test } from '@utils/test/playwright';
test.describe('radio: states', () => {
test('should render disabled checked radio correctly', async ({ page, skip }) => {
skip.rtl();
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('radio: states'), () => {
test('should render disabled checked radio correctly', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio disabled="true" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
);
await page.setContent(`
<ion-radio-group value="1">
<ion-radio disabled="true" value="1">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-checked-disabled`));
});
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(`radio-checked-disabled-${page.getSnapshotSettings()}.png`);
});
test('should render checked radio correctly', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="true">
<ion-radio value="true">Label</ion-radio>
</ion-radio-group>
`,
config
);
test('should render checked radio correctly', async ({ page }) => {
await page.setContent(`
<ion-radio-group value="true">
<ion-radio value="true">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-checked`));
});
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(`radio-checked-${page.getSnapshotSettings()}.png`);
});
test('should render unchecked radio correctly', async ({ page }) => {
await page.setContent(
`
<ion-radio-group>
<ion-radio value="true">Label</ion-radio>
</ion-radio-group>
`,
config
);
test('should render unchecked radio correctly', async ({ page }) => {
await page.setContent(`
<ion-radio-group>
<ion-radio value="true">Label</ion-radio>
</ion-radio-group>
`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(`radio-unchecked-${page.getSnapshotSettings()}.png`);
const radio = page.locator('ion-radio');
expect(await radio.screenshot()).toMatchSnapshot(screenshot(`radio-unchecked`));
});
});
});