test(action-sheet): improve test performance (#27336)

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. -->

I noticed some test slowdowns with the introduction of action sheet
tests, so I wanted to try and find a way to speed these tests up.

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

- htmlAttributes test was ported to a spec test
- the functionality/behavioral tests were being run per-mode when they
did not need to be, so I removed the per-mode checks
- Moved screenshot tests to a separate file so they can be better
paralellelized

## 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-05 11:52:43 -04:00
committed by GitHub
parent 154aa1dbf6
commit 1be73330ca
64 changed files with 116 additions and 94 deletions

View File

@ -0,0 +1,42 @@
import { configs, test } from '@utils/test/playwright';
import { ActionSheetFixture } from './fixture';
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('action sheet: variant rendering'), () => {
let actionSheetFixture!: ActionSheetFixture;
test.beforeEach(async ({ page }) => {
actionSheetFixture = new ActionSheetFixture(page, screenshot);
await page.goto(`/src/components/action-sheet/test/basic`, config);
});
test('should open basic action sheet', async () => {
await actionSheetFixture.open('#basic');
await actionSheetFixture.screenshot('basic');
/**
* We want to test that the dismiss method
* actually works, but we do not need to test
* it every time. As a result, we only
* call dismiss in this test.
*/
await actionSheetFixture.dismiss();
});
test('should open cancel only action sheet', async () => {
await actionSheetFixture.open('#cancelOnly');
await actionSheetFixture.screenshot('cancel-only');
});
test('should open custom action sheet', async () => {
await actionSheetFixture.open('#custom');
await actionSheetFixture.screenshot('custom');
});
test('should open scrollable action sheet', async () => {
await actionSheetFixture.open('#scrollableOptions');
await actionSheetFixture.screenshot('scrollable-options');
});
test('should open scrollable action sheet without cancel', async () => {
await actionSheetFixture.open('#scrollWithoutCancel');
await actionSheetFixture.screenshot('scroll-without-cancel');
});
});
});

View File

@ -1,9 +1,12 @@
import { expect } from '@playwright/test'; import { expect } from '@playwright/test';
import type { Locator } from '@playwright/test';
import { configs, test } from '@utils/test/playwright'; import { configs, test } from '@utils/test/playwright';
import type { E2EPage } from '@utils/test/playwright';
configs({ directions: ['ltr'] }).forEach(({ config, title }) => { import { ActionSheetFixture } from './fixture';
/**
* This behavior does not vary across modes/directions
*/
configs({ mode: ['ios'], directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: data'), () => { test.describe(title('action sheet: data'), () => {
let actionSheetFixture!: ActionSheetFixture; let actionSheetFixture!: ActionSheetFixture;
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
@ -35,58 +38,11 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
}); });
}); });
}); });
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: attributes'), () => {
test('should set htmlAttributes', async ({ page }) => {
await page.goto(`/src/components/action-sheet/test/basic`, config);
const actionSheetFixture = new ActionSheetFixture(page);
await actionSheetFixture.open('#basic'); /**
* This behavior does not vary across modes/directions
const actionSheet = page.locator('ion-action-sheet'); */
await expect(actionSheet).toHaveAttribute('data-testid', 'basic-action-sheet'); configs({ mode: ['ios'], directions: ['ltr'] }).forEach(({ config, title }) => {
});
});
});
configs().forEach(({ config, screenshot, title }) => {
test.describe(title('action sheet: variant rendering'), () => {
let actionSheetFixture!: ActionSheetFixture;
test.beforeEach(async ({ page }) => {
actionSheetFixture = new ActionSheetFixture(page, screenshot);
await page.goto(`/src/components/action-sheet/test/basic`, config);
});
test('should open basic action sheet', async () => {
await actionSheetFixture.open('#basic');
await actionSheetFixture.screenshot('basic');
/**
* We want to test that the dismiss method
* actually works, but we do not need to test
* it every time. As a result, we only
* call dismiss in this test.
*/
await actionSheetFixture.dismiss();
});
test('should open cancel only action sheet', async () => {
await actionSheetFixture.open('#cancelOnly');
await actionSheetFixture.screenshot('cancel-only');
});
test('should open custom action sheet', async () => {
await actionSheetFixture.open('#custom');
await actionSheetFixture.screenshot('custom');
});
test('should open scrollable action sheet', async () => {
await actionSheetFixture.open('#scrollableOptions');
await actionSheetFixture.screenshot('scrollable-options');
});
test('should open scrollable action sheet without cancel', async () => {
await actionSheetFixture.open('#scrollWithoutCancel');
await actionSheetFixture.screenshot('scroll-without-cancel');
});
});
});
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: variant functionality'), () => { test.describe(title('action sheet: variant functionality'), () => {
let actionSheetFixture!: ActionSheetFixture; let actionSheetFixture!: ActionSheetFixture;
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
@ -118,7 +74,11 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
}); });
}); });
}); });
configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
/**
* This behavior does not vary across modes/directions
*/
configs({ mode: ['ios'], directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('action sheet: focus trap'), () => { test.describe(title('action sheet: focus trap'), () => {
test('it should trap focus in action sheet', async ({ page, browserName }) => { test('it should trap focus in action sheet', async ({ page, browserName }) => {
await page.goto(`/src/components/action-sheet/test/basic`, config); await page.goto(`/src/components/action-sheet/test/basic`, config);
@ -140,42 +100,3 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
}); });
}); });
}); });
class ActionSheetFixture {
readonly page: E2EPage;
readonly screenshotFn?: (file: string) => string;
private actionSheet!: Locator;
constructor(page: E2EPage, screenshot?: (file: string) => string) {
this.page = page;
this.screenshotFn = screenshot;
}
async open(selector: string) {
const ionActionSheetDidPresent = await this.page.spyOnEvent('ionActionSheetDidPresent');
await this.page.locator(selector).click();
await ionActionSheetDidPresent.next();
this.actionSheet = this.page.locator('ion-action-sheet');
await expect(this.actionSheet).toBeVisible();
}
async dismiss() {
const ionActionSheetDidDismiss = await this.page.spyOnEvent('ionActionSheetDidDismiss');
await this.actionSheet.evaluate((el: HTMLIonActionSheetElement) => el.dismiss());
await ionActionSheetDidDismiss.next();
await expect(this.actionSheet).not.toBeVisible();
}
async screenshot(modifier: string) {
const { screenshotFn } = this;
if (!screenshotFn) {
throw new Error(
'A screenshot function is required to take a screenshot. Pass one in when creating ActionSheetFixture.'
);
}
await expect(this.actionSheet).toHaveScreenshot(screenshotFn(`action-sheet-${modifier}-diff`));
}
}

View File

@ -0,0 +1,17 @@
import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { ActionSheet } from '../../action-sheet';
describe('action sheet: htmlAttributes inheritance', () => {
it('should correctly inherit attributes on host', async () => {
const page = await newSpecPage({
components: [ActionSheet],
template: () => <ion-action-sheet htmlAttributes={{ 'data-testid': 'basic-action-sheet' }}></ion-action-sheet>,
});
const actionSheet = page.body.querySelector('ion-action-sheet');
await expect(actionSheet.getAttribute('data-testid')).toBe('basic-action-sheet');
});
});

View File

@ -0,0 +1,42 @@
import type { Locator } from '@playwright/test';
import { expect } from '@playwright/test';
import type { E2EPage } from '@utils/test/playwright';
export class ActionSheetFixture {
readonly page: E2EPage;
readonly screenshotFn?: (file: string) => string;
private actionSheet!: Locator;
constructor(page: E2EPage, screenshot?: (file: string) => string) {
this.page = page;
this.screenshotFn = screenshot;
}
async open(selector: string) {
const ionActionSheetDidPresent = await this.page.spyOnEvent('ionActionSheetDidPresent');
await this.page.locator(selector).click();
await ionActionSheetDidPresent.next();
this.actionSheet = this.page.locator('ion-action-sheet');
await expect(this.actionSheet).toBeVisible();
}
async dismiss() {
const ionActionSheetDidDismiss = await this.page.spyOnEvent('ionActionSheetDidDismiss');
await this.actionSheet.evaluate((el: HTMLIonActionSheetElement) => el.dismiss());
await ionActionSheetDidDismiss.next();
await expect(this.actionSheet).not.toBeVisible();
}
async screenshot(modifier: string) {
const { screenshotFn } = this;
if (!screenshotFn) {
throw new Error(
'A screenshot function is required to take a screenshot. Pass one in when creating ActionSheetFixture.'
);
}
await expect(this.actionSheet).toHaveScreenshot(screenshotFn(`action-sheet-${modifier}-diff`));
}
}