Skip to content

Commit

Permalink
chore: improve percy snapshot coverage (carbon-design-system#6520)
Browse files Browse the repository at this point in the history
* chore(storybook): open component default states

* fix(APIKeyModal): resolve focus issue

* fix(AboutModal): avt fixes

* fix(APIKeyModal): fix avt tests

* fix(CreateTearsheet): avt tests

* fix(avt): create side panel create tearsheet narrow notifications panel

* fix(SidePanel): avt tests

* fix(Tearsheet): avt tests, and minor refactor

* fix(TearsheetNarrow): avt tests

* fix(WebTerminal): avt tests

* fix(CreateTearsheet): avt test disable animations

* fix(CreateTearsheet): disable animations in avt

* fix(ImportModal): disable animations

* test: debug pageheader avt

* fix: pageheader avt

* fix: pageHeader avt

* fix: pageheader avts attempt 2

* chore: format and fix createTearsheet avt

* fix: pageHeader avt 1

* fix: pageheader refactor test case

* chore: debug pageheader

* chore: pageheader refactor tests

* fix: pageheader avt

* fix(Tearsheet): resolve initial focus issue in default open state

* fix(Tearsheet): change getFocusable() to focusableElements

* fix: include anchor tag in focusable elements list

* fix: revert useFocus hook to main state

* chore: remove console

* fix(Tearsheet): resolve initial focus issue

* test(createTearsheet): correct the avt test

* fix: createTearsheet flakiness in ci attempt 1

* refactor: pageheader avt revert

* fix(createTearsheet): include test for error state

* fix: pageheader avt add race condition

* fix: pageheader add race condition for flaky test

* fix: page header race condition and create fullpage

* fix: pageheader flakyness attempt 1

* fix(CreateTearsheet): resolve focus issue

* chore: add prop types

* fix(pageheader): flaky avt with race condition

* fix(productiveCard): flaky test case

* fix(tagset): flaky avt, added race condition

* chore: cleanup timeout

* fix(TearsheetNArrow): flaky avt, added race conditions

* fix(ProductiveCard): add await to fix flakiness

* chore: format

---------

Co-authored-by: Afsal K <[email protected]>
Co-authored-by: Sangeetha Babu <[email protected]>
  • Loading branch information
3 people authored Jan 2, 2025
1 parent 38e8c8f commit 2f7d5f1
Show file tree
Hide file tree
Showing 36 changed files with 525 additions and 476 deletions.
33 changes: 18 additions & 15 deletions e2e/components/APIKeyModal/APIKeyModal-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ test.describe('APIKeyModal @avt', () => {
},
});

await page.getByRole('button', { name: 'Generate API key' }).click();

await expect(page).toHaveNoACViolations('APIKeyModal @avt-default-state');
});

Expand All @@ -36,25 +34,15 @@ test.describe('APIKeyModal @avt', () => {
});

const modalElement = page.locator(`.${carbon.prefix}--modal.is-visible`);
const generateButton = page.getByRole('button', { name: 'Generate' });

// Focus the Generate button
await page.keyboard.press('Tab');
await expect(generateButton).toBeFocused();

await page.keyboard.press('Enter');

// Evaluate the Instant Generate Modal opening animation
await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);
await expect(modalElement).toBeInViewport();
await expect(modalElement).not.toHaveAttribute('aria-hidden', 'true');

await expect(page).toHaveNoACViolations(
'APIKeyModal @avt-instant-generate-focus-trap'
);

// Initial focus should be on first interactive element, on an open modal
const apiKeyInput = page.getByLabel('Unique API Key');
await expect(apiKeyInput).toBeFocused();

Expand All @@ -81,5 +69,20 @@ test.describe('APIKeyModal @avt', () => {
)
);
await expect(modalElement).not.toBeInViewport();

// check the focus returns to trigger button
const generateButton = page.getByRole('button', { name: 'Generate' });
await expect(generateButton).toBeFocused();

// Reopen modal from trigger button to check if first focusable element is input field
await generateButton.click();
await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);
await expect(modalElement).toBeInViewport();
await expect(modalElement).not.toHaveAttribute('aria-hidden', 'true');
await expect(apiKeyInput).toBeFocused();
});
});
72 changes: 42 additions & 30 deletions e2e/components/AboutModal/AboutModal-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,6 @@ test.describe('AboutModal @avt', () => {
},
});

const modalElement = page.locator(`.${carbon.prefix}--modal.is-visible`);
await page.getByText('Open the About modal').click();

await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);

await expect(page).toHaveNoACViolations('AboutModal @avt-default-state');
});

Expand All @@ -42,16 +33,7 @@ test.describe('AboutModal @avt', () => {
},
});

const modalElement = page.locator(`.${carbon.prefix}--modal.is-visible`);
await page.getByText('Open the About modal').click();

await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);
const closeButton = page.getByLabel('Close');

await expect(closeButton).toBeFocused();
});

Expand All @@ -65,32 +47,58 @@ test.describe('AboutModal @avt', () => {
});

const modalElement = page.locator(`.${carbon.prefix}--modal`);
const openButton = page.getByText(
'Open the About modal with all props set'
);
const closeIcon = page.getByLabel('Close');
const linkActions = page.getByText('Link action');

// Focus the open button
// Initial focus should be on close button, on an open modal
await expect(modalElement).not.toHaveAttribute('aria-hidden', 'true');
await expect(closeIcon).toBeFocused();
// Press tab to move focus to first link element
await page.keyboard.press('Tab');
await expect(linkActions.first()).toBeFocused();

// Press tab to move focus to second link element
await page.keyboard.press('Tab');
// Expect open button to be focused
await expect(openButton).toBeFocused();
// Open modal by pressing 'Enter' key
await page.keyboard.press('Enter');
await expect(linkActions.nth(1)).toBeFocused();

// Opening modal
// Press tab to move focus to last link element
await page.keyboard.press('Tab');
await expect(linkActions.last()).toBeFocused();

// Press tab to move focus back to close button
await page.keyboard.press('Tab');
await expect(closeIcon).toBeFocused();

// Press escape twice
// To close tooltip and modal
await page.keyboard.press('Escape');
await page.keyboard.press('Escape');

// Closing modal
await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);

await expect(modalElement).toHaveAttribute('aria-hidden', 'true');
await expect(page).toHaveNoACViolations(
'AboutModal @avt-open-close-with-focus-trap'
);

// Initial focus should be on close button
// Reopening modal from trigger button to check if focus trap is working
const openButton = page.getByText(
'Reopen the About modal with all props set'
);
await openButton.click();
await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);
await expect(modalElement).not.toHaveAttribute('aria-hidden', 'true');
await expect(closeIcon).toBeFocused();

// Press tab to move focus to first link element
await page.keyboard.press('Tab');
await expect(linkActions.first()).toBeFocused();
Expand All @@ -107,18 +115,22 @@ test.describe('AboutModal @avt', () => {
await page.keyboard.press('Tab');
await expect(closeIcon).toBeFocused();

// Press escape to twise
// Press escape to twice
// first to close tooltip then close modal
await page.keyboard.press('Escape');
await page.keyboard.press('Escape');

// Opening modal
// Closing modal
await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);

await expect(modalElement).toHaveAttribute('aria-hidden', 'true');

await expect(page).toHaveNoACViolations(
'AboutModal @avt-open-close-with-focus-trap'
);
});
});
108 changes: 89 additions & 19 deletions e2e/components/CreateFlows/CreateTearsheet-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,10 @@ test.describe('CreateTearsheet @avt', () => {
carbonTheme: 'white',
},
});
await page.getByRole('button', { name: 'Open CreateTearsheet' }).click();
await page.screenshot({ animations: 'disabled' });
const modalElement = page.locator(`.${carbon.prefix}--modal.is-visible`);
await expect(modalElement).toBeVisible();
await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);
await expect(modalElement).toHaveAttribute('aria-hidden', 'false');
await expect(page).toHaveNoACViolations(
'CreateTearsheet @avt-default-state'
);
Expand All @@ -41,26 +37,22 @@ test.describe('CreateTearsheet @avt', () => {
carbonTheme: 'white',
},
});

await page.screenshot({ animations: 'disabled' });
const modalElement = page.locator(`.${carbon.prefix}--modal.is-visible`);
// Pressing 'Tab' key to focus on the "Open CreateTearsheet" button in the Storybook
await page.keyboard.press('Tab');
// Pressing 'Enter' key to open the Tearsheet
await page.keyboard.press('Enter');

await expect(modalElement).toBeVisible();
await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);
await expect(modalElement).toHaveAttribute('aria-hidden', 'false');

const learnMoreAnchor = page.getByText('Learn more.');
const step1Input1 = page.locator(
'#tearsheet-multi-step-story-text-input-multi-step-1'
);
const nextButton = page.getByText('Next');
const backButton = page.getByText('Back');

// Focus learn more link
await page.keyboard.press('Shift+Tab');

// Expect the Learn More link to be focused
await expect(learnMoreAnchor).toBeVisible();
await expect(learnMoreAnchor).toBeFocused();
Expand Down Expand Up @@ -117,23 +109,101 @@ test.describe('CreateTearsheet @avt', () => {
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');

// Goto next step by pressing enter
await page.keyboard.press('Enter');
const step4Input1 = page.locator('#one-day');

// Expect the first element in the last step to be focused
await expect(step4Input1).toBeFocused();

// Switch focus to back button
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');

// Goto previous step by pressing enter
await expect(backButton).toBeFocused();
await page.keyboard.press('Enter');

// Expect the first element in the previous step to be focused
await expect(step2Input1).toBeFocused();
await expect(step3Input1).toBeFocused();

// Switch focus to next button
// Switch focus to back button
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');

// Goto previous step by pressing enter
await expect(backButton).toBeFocused();
await page.keyboard.press('Enter');

// Expect the first element in the previous step to be focused
await expect(step2Input1).toBeFocused();

// Switch focus to back button
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');

// Goto previous step by pressing enter
await expect(backButton).toBeFocused();
await page.keyboard.press('Enter');
await page.screenshot({ animations: 'disabled' });
// Expect the previous page first element to be focused
await expect(learnMoreAnchor).toBeFocused();
await expect(step1Input1).toBeVisible();
await expect(step1Input1).toBeFocused();
});

test('@avt-simulate-error-and-focus', async ({ page }) => {
await visitStory(page, {
component: 'CreateTearsheet',
id: 'ibm-products-patterns-create-flows-createtearsheet--multi-step-tearsheet',
globals: {
carbonTheme: 'white',
},
});

await page.screenshot({ animations: 'disabled' });

const modalElement = page.locator(`.${carbon.prefix}--modal.is-visible`);
await expect(modalElement).toBeVisible();

const step1Input1 = page.locator(
'#tearsheet-multi-step-story-text-input-multi-step-1'
);
const nextButton = page.getByText('Next');
const errorToggle = page.locator('#simulated-error-toggle');

// Expect the input box to be focused
await expect(step1Input1).toBeFocused();

// Type some text in the input field
await page.keyboard.type('H');
// Expect the Next button to be enabled at this moment
await expect(nextButton).toBeEnabled();

await page.keyboard.press('Tab');
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');

await expect(errorToggle).toBeFocused();
// Enable simulate error toggle
await page.keyboard.press('Enter');

// Navigate to next button
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');

// Press on Next button
await page.keyboard.press('Enter');

await page.waitForSelector('#step-submit-error', { visible: true });
const errorNotification = page.locator('#step-submit-error');
await expect(errorNotification).toBeVisible();

// Expect the focus returned to first element
await expect(step1Input1).toBeFocused();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ test.describe('CreateSidePanel @avt', () => {
},
});

await page.getByText('Open side panel').click();
await page
.locator(`#${pkg.prefix}--side-panel`)
.screenshot({ animations: 'disabled' });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ test.describe('CreateTearsheetNarrow @avt', () => {
},
});

await page.getByText('Open CreateTearsheetNarrow').click();

await page
.locator(`.${pkg.prefix}--create-tearsheet-narrow`)
.screenshot({ animations: 'disabled' });
Expand Down
7 changes: 1 addition & 6 deletions e2e/components/ImportModal/ImportModal-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,9 @@ test.describe('ImportModal @avt', () => {
carbonTheme: 'white',
},
});
await page.getByText('Launch modal').click();
await page.screenshot({ animations: 'disabled' });
const modalElement = page.locator(`.${carbon.prefix}--modal.is-visible`);
await expect(modalElement).toBeVisible();
await modalElement.evaluate((element) =>
Promise.all(
element.getAnimations().map((animation) => animation.finished)
)
);
await expect(page).toHaveNoACViolations('ImportModal @avt-default-state');
});
});
Loading

0 comments on commit 2f7d5f1

Please sign in to comment.