Skip to content

Commit

Permalink
test(select): add e2e test for bottom content
Browse files Browse the repository at this point in the history
  • Loading branch information
brandyscarney committed Jan 21, 2025
1 parent 5acf8ab commit d147f89
Show file tree
Hide file tree
Showing 2 changed files with 327 additions and 0 deletions.
132 changes: 132 additions & 0 deletions core/src/components/select/test/bottom-content/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Select - Bottom Content</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<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>
<style>
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-row-gap: 20px;
grid-column-gap: 20px;
}

h2 {
font-size: 12px;
font-weight: normal;

color: #6f7378;

margin-top: 10px;
}

ion-select.custom-error-color {
--highlight-color-invalid: purple;
}
</style>
</head>

<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Select - Bottom Content</ion-title>
</ion-toolbar>
</ion-header>

<ion-content id="content" class="ion-padding">
<div class="grid">
<div class="grid-item">
<h2>No Hint</h2>
<ion-select label="Label">
<ion-select-option>Option</ion-select-option>
</ion-select>
</div>

<div class="grid-item">
<h2>No Hint: Stacked</h2>
<ion-select label="Label" label-placement="stacked">
<ion-select-option>Option</ion-select-option>
</ion-select>
</div>

<div class="grid-item">
<h2>Helper Text</h2>
<ion-select label="Label" helper-text="Helper text">
<ion-select-option>Option</ion-select-option>
</ion-select>
</div>

<div class="grid-item">
<h2>Helper Text: Stacked</h2>
<ion-select label="Label" label-placement="stacked" helper-text="Helper text"
>Label
<ion-select-option>Option</ion-select-option>
</ion-select>
</div>

<div class="grid-item">
<h2>Error Text</h2>
<ion-select class="ion-touched ion-invalid" label="Label" error-text="Error text">
<ion-select-option>Option</ion-select-option></ion-select
>
</div>

<div class="grid-item">
<h2>Error Text: Stacked</h2>
<ion-select class="ion-touched ion-invalid" label="Label" label-placement="stacked" error-text="Error text">
<ion-select-option>Option</ion-select-option></ion-select
>
</div>

<div class="grid-item">
<h2>Error Text: Custom Color</h2>
<ion-select class="ion-touched ion-invalid custom-error-color" label="Label" error-text="Error text">
<ion-select-option>Option</ion-select-option></ion-select
>
</div>

<div class="grid-item">
<h2>Helper Text: Wrapping</h2>
<ion-select
label="Label"
helper-text="Helper text helper text helper text helper text helper text helper text helper text helper text helper text"
>
<ion-select-option>Option</ion-select-option>
</ion-select>
</div>
</div>

<button class="expand" onclick="toggleFill()">Toggle Fill</button>
</ion-content>
</ion-app>

<script>
const selects = document.querySelectorAll('ion-select');

function toggleFill() {
selects.forEach((select) => {
switch (select.fill) {
case 'outline':
select.fill = 'solid';
break;
case 'solid':
select.fill = undefined;
break;
default:
select.fill = 'outline';
}
});
}
</script>
</body>
</html>
195 changes: 195 additions & 0 deletions core/src/components/select/test/bottom-content/select.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';

/**
* Functionality is the same across modes & directions
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('select: bottom content functionality'), () => {
test('should not render bottom content if no hint is enabled', async ({ page }) => {
await page.setContent(`<ion-select label="Label"></ion-select>`, config);

const bottomEl = page.locator('ion-select .select-bottom');
await expect(bottomEl).toHaveCount(0);
});
test('helper text should be visible initially', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" helper-text="Helper text" error-text="Error text"></ion-select>`,
config
);

const helperText = page.locator('ion-select .helper-text');
const errorText = page.locator('ion-select .error-text');
await expect(helperText).toBeVisible();
await expect(helperText).toHaveText('Helper text');
await expect(errorText).toBeHidden();
});
test('input should have an aria-describedby attribute when helper text is present', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" helper-text="Helper text" error-text="Error text"></ion-select>`,
config
);

const input = page.locator('ion-select button');
const helperText = page.locator('ion-select .helper-text');
const helperTextId = await helperText.getAttribute('id');
const ariaDescribedBy = await input.getAttribute('aria-describedby');

expect(ariaDescribedBy).toBe(helperTextId);
});
test('error text should be visible when select is invalid', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" class="ion-invalid ion-touched" helper-text="Helper text" error-text="Error text"></ion-select>`,
config
);

const helperText = page.locator('ion-select .helper-text');
const errorText = page.locator('ion-select .error-text');
await expect(helperText).toBeHidden();
await expect(errorText).toBeVisible();
await expect(errorText).toHaveText('Error text');
});

test('input should have an aria-describedby attribute when error text is present', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" class="ion-invalid ion-touched" helper-text="Helper text" error-text="Error text"></ion-select>`,
config
);

const input = page.locator('ion-select button');
const errorText = page.locator('ion-select .error-text');
const errorTextId = await errorText.getAttribute('id');
const ariaDescribedBy = await input.getAttribute('aria-describedby');

expect(ariaDescribedBy).toBe(errorTextId);
});
test('input should have aria-invalid attribute when input is invalid', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" class="ion-invalid ion-touched" helper-text="Helper text" error-text="Error text"></ion-select>`,
config
);

const input = page.locator('ion-select button');

await expect(input).toHaveAttribute('aria-invalid');
});
test('input should not have aria-invalid attribute when input is valid', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" helper-text="Helper text" error-text="Error text"></ion-select>`,
config
);

const input = page.locator('ion-select button');

await expect(input).not.toHaveAttribute('aria-invalid');
});
test('input should not have aria-describedby attribute when no hint or error text is present', async ({ page }) => {
await page.setContent(`<ion-select label="Label"></ion-select>`, config);

const input = page.locator('ion-select button');

await expect(input).not.toHaveAttribute('aria-describedby');
});
});
});

/**
* Rendering is different across modes
*/
configs({ modes: ['ios', 'md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('select: helper text rendering'), () => {
test('should not have visual regressions when rendering helper text', async ({ page }) => {
await page.setContent(`<ion-select label="Label" helper-text="Helper text"></ion-select>`, config);

const bottomEl = page.locator('ion-select');
await expect(bottomEl).toHaveScreenshot(screenshot(`select-helper-text`));
});
test('should not have visual regressions when rendering helper text with wrapping text', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" helper-text="Helper text helper text helper text helper text helper text helper text helper text helper text helper text"></ion-select>`,
config
);

const bottomEl = page.locator('ion-select');
await expect(bottomEl).toHaveScreenshot(screenshot(`select-helper-text-wrapping`));
});
test('should not have visual regressions when rendering helper text with a stacked label', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" label-placement="stacked" helper-text="Helper text"></ion-select>`,
config
);

const bottomEl = page.locator('ion-select');
await expect(bottomEl).toHaveScreenshot(screenshot(`select-helper-text-stacked-label`));
});
});

test.describe(title('select: error text rendering'), () => {
test('should not have visual regressions when rendering error text', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" class="ion-invalid ion-touched" error-text="Error text"></ion-select>`,
config
);

const bottomEl = page.locator('ion-select');
await expect(bottomEl).toHaveScreenshot(screenshot(`select-error-text`));
});
test('should not have visual regressions when rendering error text with a stacked label', async ({ page }) => {
await page.setContent(
`<ion-select label="Label" class="ion-invalid ion-touched" error-text="Error text" label-placement="stacked"></ion-select>`,
config
);

const bottomEl = page.locator('ion-select');
await expect(bottomEl).toHaveScreenshot(screenshot(`select-error-text-stacked-label`));
});
});
});

/**
* Customizing supporting text is the same across modes and directions
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('select: supporting text customization'), () => {
test('should not have visual regressions when rendering helper text with a custom color', async ({ page }) => {
await page.setContent(
`
<style>
ion-select.custom-select::part(supporting-text) {
font-size: 20px;
}
ion-select.custom-select::part(helper-text) {
color: green;
}
</style>
<ion-select label="Label" class="custom-select" helper-text="Helper text"></ion-select>
`,
config
);

const errorText = page.locator('ion-select');
await expect(errorText).toHaveScreenshot(screenshot(`select-helper-text-custom`));
});
test('should not have visual regressions when rendering error text with a custom color', async ({ page }) => {
await page.setContent(
`
<style>
ion-select.custom-select::part(supporting-text) {
font-size: 20px;
}
ion-select.custom-select::part(error-text) {
color: purple;
}
</style>
<ion-select label="Label" class="ion-invalid ion-touched custom-select" error-text="Error text"></ion-select>
`,
config
);

const errorText = page.locator('ion-select');
await expect(errorText).toHaveScreenshot(screenshot(`select-error-text-custom`));
});
});
});

0 comments on commit d147f89

Please sign in to comment.