-
- {helperText}
+
+ {!isInvalid ? helperText : null}
-
- {errorText}
+
+ {isInvalid ? errorText : null}
);
@@ -278,13 +336,17 @@ export class Checkbox implements ComponentInterface {
-
diff --git a/core/src/components/checkbox/test/a11y/checkbox.e2e.ts-snapshots/checkbox-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/checkbox/test/a11y/checkbox.e2e.ts-snapshots/checkbox-scale-md-ltr-Mobile-Chrome-linux.png
index fbede37e147..90d597d391b 100644
Binary files a/core/src/components/checkbox/test/a11y/checkbox.e2e.ts-snapshots/checkbox-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/checkbox/test/a11y/checkbox.e2e.ts-snapshots/checkbox-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/checkbox/test/basic/checkbox.e2e.ts b/core/src/components/checkbox/test/basic/checkbox.e2e.ts
index 159e86f9a30..733f229e4b6 100644
--- a/core/src/components/checkbox/test/basic/checkbox.e2e.ts
+++ b/core/src/components/checkbox/test/basic/checkbox.e2e.ts
@@ -44,7 +44,10 @@ configs().forEach(({ title, screenshot, config }) => {
});
});
-configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
+/**
+ * This behavior does not vary across modes/directions
+ */
+configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('checkbox: ionChange'), () => {
test('should fire ionChange when interacting with checkbox', async ({ page }) => {
await page.setContent(
@@ -133,4 +136,195 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
expect(clickCount).toBe(1);
});
});
+
+ test.describe(title('checkbox: ionFocus'), () => {
+ test('should not have visual regressions', async ({ page, pageUtils }) => {
+ await page.setContent(
+ `
+
+
+
+ Unchecked
+
+ `,
+ config
+ );
+
+ await pageUtils.pressKeys('Tab');
+
+ const container = page.locator('#container');
+
+ await expect(container).toHaveScreenshot(screenshot(`checkbox-focus`));
+ });
+
+ test('should not have visual regressions when interacting with checkbox in item', async ({ page, pageUtils }) => {
+ await page.setContent(
+ `
+
+ Unchecked
+
+ `,
+ config
+ );
+
+ // Test focus with keyboard navigation
+ await pageUtils.pressKeys('Tab');
+
+ const item = page.locator('ion-item');
+
+ await expect(item).toHaveScreenshot(screenshot(`checkbox-in-item-focus`));
+ });
+
+ test('should fire ionFocus when checkbox is focused', async ({ page, pageUtils }) => {
+ await page.setContent(
+ `
+
+ `,
+ config
+ );
+
+ const ionFocus = await page.spyOnEvent('ionFocus');
+
+ // Test focus with keyboard navigation
+ await pageUtils.pressKeys('Tab');
+
+ expect(ionFocus).toHaveReceivedEventTimes(1);
+
+ // Reset focus
+ const checkbox = page.locator('ion-checkbox');
+ const checkboxBoundingBox = (await checkbox.boundingBox())!;
+ await page.mouse.click(0, checkboxBoundingBox.height + 1);
+
+ // Test focus with click
+ await checkbox.click();
+
+ expect(ionFocus).toHaveReceivedEventTimes(2);
+ });
+
+ test('should fire ionFocus when interacting with checkbox in item', async ({ page, pageUtils }) => {
+ await page.setContent(
+ `
+
+
+
+ `,
+ config
+ );
+
+ const ionFocus = await page.spyOnEvent('ionFocus');
+
+ // Test focus with keyboard navigation
+ await pageUtils.pressKeys('Tab');
+
+ expect(ionFocus).toHaveReceivedEventTimes(1);
+
+ // Verify that the event target is the checkbox and not the item
+ const eventByKeyboard = ionFocus.events[0];
+ expect((eventByKeyboard.target as HTMLElement).tagName.toLowerCase()).toBe('ion-checkbox');
+
+ // Reset focus
+ const checkbox = page.locator('ion-checkbox');
+ const checkboxBoundingBox = (await checkbox.boundingBox())!;
+ await page.mouse.click(0, checkboxBoundingBox.height + 1);
+
+ // Test focus with click
+ const item = page.locator('ion-item');
+ await item.click();
+
+ expect(ionFocus).toHaveReceivedEventTimes(2);
+
+ // Verify that the event target is the checkbox and not the item
+ const eventByClick = ionFocus.events[0];
+ expect((eventByClick.target as HTMLElement).tagName.toLowerCase()).toBe('ion-checkbox');
+ });
+
+ test('should not fire when programmatically setting a value', async ({ page }) => {
+ await page.setContent(
+ `
+
+ `,
+ config
+ );
+
+ const ionFocus = await page.spyOnEvent('ionFocus');
+ const checkbox = page.locator('ion-checkbox');
+
+ await checkbox.evaluate((el: HTMLIonCheckboxElement) => (el.checked = true));
+ expect(ionFocus).not.toHaveReceivedEvent();
+ });
+ });
+
+ test.describe(title('checkbox: ionBlur'), () => {
+ test('should fire ionBlur when checkbox is blurred', async ({ page, pageUtils }) => {
+ await page.setContent(
+ `
+
+ `,
+ config
+ );
+
+ const ionBlur = await page.spyOnEvent('ionBlur');
+
+ // Test blur with keyboard navigation
+ // Focus the checkbox
+ await pageUtils.pressKeys('Tab');
+ // Blur the checkbox
+ await pageUtils.pressKeys('Tab');
+
+ expect(ionBlur).toHaveReceivedEventTimes(1);
+
+ // Test blur with click
+ const checkbox = page.locator('ion-checkbox');
+ // Focus the checkbox
+ await checkbox.click();
+ // Blur the checkbox by clicking outside of it
+ const checkboxBoundingBox = (await checkbox.boundingBox())!;
+ await page.mouse.click(0, checkboxBoundingBox.height + 1);
+
+ expect(ionBlur).toHaveReceivedEventTimes(2);
+ });
+
+ test('should fire ionBlur after interacting with checkbox in item', async ({ page, pageUtils }) => {
+ await page.setContent(
+ `
+
+
+
+ `,
+ config
+ );
+
+ const ionBlur = await page.spyOnEvent('ionBlur');
+
+ // Test blur with keyboard navigation
+ // Focus the checkbox
+ await pageUtils.pressKeys('Tab');
+ // Blur the checkbox
+ await pageUtils.pressKeys('Tab');
+
+ expect(ionBlur).toHaveReceivedEventTimes(1);
+
+ // Verify that the event target is the checkbox and not the item
+ const event = ionBlur.events[0];
+ expect((event.target as HTMLElement).tagName.toLowerCase()).toBe('ion-checkbox');
+
+ // Test blur with click
+ const item = page.locator('ion-item');
+ await item.click();
+ // Blur the checkbox by clicking outside of it
+ const itemBoundingBox = (await item.boundingBox())!;
+ await page.mouse.click(0, itemBoundingBox.height + 1);
+
+ expect(ionBlur).toHaveReceivedEventTimes(2);
+
+ // Verify that the event target is the checkbox and not the item
+ const eventByClick = ionBlur.events[0];
+ expect((eventByClick.target as HTMLElement).tagName.toLowerCase()).toBe('ion-checkbox');
+ });
+ });
});
diff --git a/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..45885364c12
Binary files /dev/null and b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..305f4d89e1b
Binary files /dev/null and b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Safari-linux.png b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..23f542f7ec4
Binary files /dev/null and b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-focus-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..2c0dcdc0baa
Binary files /dev/null and b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..9a511961639
Binary files /dev/null and b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Safari-linux.png b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..8b59702aa81
Binary files /dev/null and b/core/src/components/checkbox/test/basic/checkbox.e2e.ts-snapshots/checkbox-in-item-focus-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/checkbox/test/basic/index.html b/core/src/components/checkbox/test/basic/index.html
index 3380f82ddd1..54bc33c3db2 100644
--- a/core/src/components/checkbox/test/basic/index.html
+++ b/core/src/components/checkbox/test/basic/index.html
@@ -50,6 +50,20 @@
Specified width
Full-width
+
+