feat(checkbox): component can be used outside ion-item (#26518)
17
core/src/components/checkbox/test/a11y/checkbox.e2e.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import AxeBuilder from '@axe-core/playwright';
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('checkbox: a11y', () => {
|
||||
test.beforeEach(async ({ skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('md');
|
||||
});
|
||||
|
||||
test('should not have accessibility violations', async ({ page }) => {
|
||||
await page.goto(`/src/components/checkbox/test/a11y`);
|
||||
|
||||
const results = await new AxeBuilder({ page }).analyze();
|
||||
expect(results.violations).toEqual([]);
|
||||
});
|
||||
});
|
||||
25
core/src/components/checkbox/test/a11y/index.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Checkbox - a11y</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<h1>Checkbox - a11y</h1>
|
||||
|
||||
<ion-checkbox>Label</ion-checkbox><br />
|
||||
<ion-checkbox aria-label="my aria label"></ion-checkbox><br />
|
||||
<ion-item>
|
||||
<ion-checkbox>Checkbox in item</ion-checkbox>
|
||||
</ion-item>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,39 +1,78 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('checkbox: basic', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/checkbox/test/basic`);
|
||||
test.describe('checkbox: basic visual tests', () => {
|
||||
test('should render unchecked checkbox correctly', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox>Unchecked</ion-checkbox>
|
||||
`);
|
||||
|
||||
await page.setIonViewport();
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-unchecked-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`checkbox-basic-${page.getSnapshotSettings()}.png`);
|
||||
test('should render checked checkbox correctly', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox checked>Checked</ion-checkbox>
|
||||
`);
|
||||
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-checked-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
|
||||
test('should render disabled checkbox correctly', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox checked disabled>Disabled</ion-checkbox>
|
||||
`);
|
||||
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-disabled-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
|
||||
test('should render custom checkmark-width correctly', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox checked style="--checkmark-width: 7">Checkmark Width</ion-checkbox>
|
||||
`);
|
||||
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-checkmark-width-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
|
||||
test('should render custom size correctly', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox checked style="--size: 100px">Size</ion-checkbox>
|
||||
`);
|
||||
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-size-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('checkbox: ionChange', () => {
|
||||
test.beforeEach(({ skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('ios');
|
||||
});
|
||||
|
||||
test('should fire ionChange when interacting with checkbox', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox value="my-checkbox"></ion-checkbox>
|
||||
<ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
|
||||
`);
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
|
||||
await checkbox.click();
|
||||
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
|
||||
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
|
||||
|
||||
await checkbox.click();
|
||||
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
|
||||
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
|
||||
});
|
||||
|
||||
test('should fire ionChange when interacting with checkbox in item', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-item>
|
||||
<ion-checkbox value="my-checkbox"></ion-checkbox>
|
||||
<ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
|
||||
</ion-item>
|
||||
`);
|
||||
|
||||
@ -41,21 +80,21 @@ test.describe('checkbox: ionChange', () => {
|
||||
const item = page.locator('ion-item');
|
||||
|
||||
await item.click();
|
||||
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
|
||||
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: true });
|
||||
|
||||
await item.click();
|
||||
await expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
|
||||
expect(ionChange).toHaveReceivedEventDetail({ value: 'my-checkbox', checked: false });
|
||||
});
|
||||
|
||||
test('should not fire when programmatically setting a value', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox value="my-checkbox"></ion-checkbox>
|
||||
<ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
|
||||
`);
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
|
||||
await checkbox.evaluate((el: HTMLIonCheckboxElement) => (el.checked = true));
|
||||
await expect(ionChange).not.toHaveReceivedEvent();
|
||||
expect(ionChange).not.toHaveReceivedEvent();
|
||||
});
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
@ -14,6 +14,11 @@
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
ion-checkbox {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
ion-checkbox.checkbox-part::part(mark) {
|
||||
transform: scale(0.5);
|
||||
transform-origin: center;
|
||||
@ -27,81 +32,16 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content id="content">
|
||||
<ion-item onClick="clickItem()">
|
||||
<ion-label>Clickable Item</ion-label>
|
||||
<ion-checkbox></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Default</ion-label>
|
||||
<ion-checkbox checked></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Primary</ion-label>
|
||||
<ion-checkbox checked color="primary" slot="end"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Secondary, disabled</ion-label>
|
||||
<ion-checkbox disabled checked color="secondary"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Tertiary</ion-label>
|
||||
<ion-checkbox checked color="tertiary"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Success</ion-label>
|
||||
<ion-checkbox checked color="success"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Warning</ion-label>
|
||||
<ion-checkbox checked color="warning"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Dark, --size</ion-label>
|
||||
<ion-checkbox checked color="dark" style="--size: 100px"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Danger</ion-label>
|
||||
<ion-checkbox checked color="danger" slot="start"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Light</ion-label>
|
||||
<ion-checkbox checked color="light" slot="start"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Medium</ion-label>
|
||||
<ion-checkbox checked color="medium" slot="start"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Checkmark width</ion-label>
|
||||
<ion-checkbox checked color="dark" slot="start" style="--checkmark-width: 7"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Checkmark ::part</ion-label>
|
||||
<ion-checkbox checked color="dark" slot="start" class="checkbox-part"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Unchecked by Default</ion-label>
|
||||
<ion-checkbox></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Disabled</ion-label>
|
||||
<ion-checkbox disabled></ion-checkbox>
|
||||
</ion-item>
|
||||
<ion-content class="ion-padding">
|
||||
<div id="checkboxes">
|
||||
<ion-checkbox justify="start">Unchecked</ion-checkbox>
|
||||
<ion-checkbox justify="start" checked>Checked</ion-checkbox>
|
||||
<ion-checkbox justify="start" disabled>Disabled</ion-checkbox>
|
||||
<ion-checkbox justify="start" disabled checked>Disabled, Checked</ion-checkbox>
|
||||
<ion-checkbox justify="start" checked style="--checkmark-width: 7">Checkmark Width</ion-checkbox>
|
||||
<ion-checkbox justify="start" checked class="checkbox-part">Checkmark Shadow Part</ion-checkbox>
|
||||
<ion-checkbox justify="start" checked style="--size: 100px">--size</ion-checkbox>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
||||
26
core/src/components/checkbox/test/color/checkbox.e2e.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('checkbox: color', () => {
|
||||
test.beforeEach(({ skip }) => {
|
||||
skip.rtl();
|
||||
});
|
||||
|
||||
test('should apply color when checked', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox color="danger" checked="true">Label</ion-checkbox>
|
||||
`);
|
||||
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-color-checked-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
|
||||
test('should not apply color when unchecked', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-checkbox color="danger">Label</ion-checkbox>
|
||||
`);
|
||||
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-color-unchecked-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 865 B |
|
After Width: | Height: | Size: 2.7 KiB |
@ -2,11 +2,12 @@ import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('checkbox: indeterminate', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
test('should not have visual regressions', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
|
||||
await page.goto(`/src/components/checkbox/test/indeterminate`);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`checkbox-indeterminate-${page.getSnapshotSettings()}.png`);
|
||||
const checkbox = page.locator('ion-checkbox:first-child');
|
||||
expect(await checkbox.screenshot()).toMatchSnapshot(`checkbox-indeterminate-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 61 KiB |