Skip to content

refactor(testing): add stable Playwright test hooks#1048

Open
german664 wants to merge 4 commits intodevelopfrom
refactor/playwright-test-hooks
Open

refactor(testing): add stable Playwright test hooks#1048
german664 wants to merge 4 commits intodevelopfrom
refactor/playwright-test-hooks

Conversation

@german664
Copy link
Contributor

Summary

Adds framework-agnostic test hooks to shared UI primitives and updates shared Playwright helpers/models to consume them.

Why

The current integration tests rely on framework-coupled selectors in several shared paths. This PR introduces stable data-testid and accessible hook points so tests can target component behavior rather than implementation details.

Included

  • stable test hooks in shared/internal components
  • targeted test hooks in shared external components used by tests
  • helper/model updates in tests/utils and tests/models

Validation

  • pnpm run types:check
  • targeted Playwright coverage for updated shared paths

Expose framework-agnostic test ids in shared UI primitives and update common Playwright helpers to use them.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@german664 german664 requested a review from a team as a code owner March 13, 2026 09:11
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the stability and maintainability of integration tests by refactoring UI components to include explicit data-testid attributes. This change decouples tests from internal component structure, making them more resilient to UI changes. Corresponding Playwright models and utilities have been updated to consume these new test hooks, ensuring that tests target intended component functionality rather than relying on brittle selectors.

Highlights

  • Stable Test Hooks Introduction: Introduced data-testid attributes across numerous shared UI components, including form fields, alerts, calendars, data grids, and structured lists, to provide stable and framework-agnostic selectors for Playwright tests.
  • Playwright Model Updates: Refactored Playwright models and utility functions to leverage the newly added data-testid attributes, enhancing test robustness by targeting component behavior rather than fragile implementation details like CSS classes.
  • Component Root Standardization: Standardized the root element for many components with a data-testid="component-root", allowing Playwright models to default to this stable selector when a specific root element is not provided.
  • Error Field Testability: Enhanced error message fields (FieldError and InputBase's internal error handling) with dedicated errorTestId props, making it easier to test error states in forms.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/components/external/PaymentLinkCreation/components/Form/CustomerDetailsForm/Fields/ShopperPhoneField.tsx
    • Added testId prop to FormField component.
    • Added errorTestId prop to InputBase component for error messages.
  • src/components/external/PaymentLinkCreation/components/Form/PaymentDetailsForm/Fields/AmountField.tsx
    • Added testId prop to FormField component.
    • Added testId prop to FieldError component for error messages.
  • src/components/external/PaymentLinkCreation/components/Form/PaymentDetailsForm/Fields/ValidityField.tsx
    • Added testId prop to FormField components.
    • Added testId prop to FieldError component for error messages.
  • src/components/external/PayoutDetails/components/PayoutData.tsx
    • Wrapped StructuredList components with div elements and assigned data-testid attributes for improved testability.
  • src/components/external/TransactionsOverview/components/TransactionsExport/TransactionsExport.tsx
    • Added data-testid to the Alert component for export errors.
    • Added data-testid to the export popover and its filters section.
  • src/components/external/UIElement/UIElement.tsx
    • Added data-testid="component-root" to the root section element of UIElement.
  • src/components/internal/Alert/Alert.tsx
    • Added data-testid prop to the root div element of the Alert component.
    • Refactored conditional rendering logic for actions and close button using new variables.
  • src/components/internal/Alert/types.ts
    • Added data-testid property to the AlertProps interface.
  • src/components/internal/Calendar/components/CalendarGrid/CalendarGrid.tsx
    • Added data-testid="calendar-month-name" to the month name div.
  • src/components/internal/Calendar/components/CalendarGrid/CalendarGridDate.tsx
    • Conditionally added data-testid="calendar-current-day" to the current day element.
  • src/components/internal/DataGrid/DataGridCell.tsx
    • Added data-testid attribute to the div element, using the column name as its value.
  • src/components/internal/DatePicker/DatePicker.tsx
    • Added data-testid="date-picker" to the root div element.
    • Added data-testid="date-picker-timezone" to the timezone information div.
  • src/components/internal/FilterBar/FilterBar.tsx
    • Updated data-testId attribute to data-testid for consistency.
  • src/components/internal/FormFields/FieldError/FieldError.tsx
    • Added testId prop and applied it as a data-testid attribute to the error message div.
  • src/components/internal/FormFields/FileInput/components/Dropzone.tsx
    • Updated data-testId attribute to data-testid for consistency.
  • src/components/internal/FormFields/InputBase.tsx
    • Added errorTestId prop to InputBase and passed it to the FieldError component.
  • src/components/internal/FormFields/Select/BalanceAccountSelector/BalanceAccountSelector.tsx
    • Added data-testid="balance-account-id" to the balance account ID span.
  • src/components/internal/FormFields/types.ts
    • Added errorTestId property to the InputBaseProps interface.
  • src/components/internal/FormWrappers/FormField.tsx
    • Added testId prop and applied it as a data-testid attribute to the form field container div.
  • src/components/internal/FormWrappers/FormSelect.tsx
    • Added fieldNameValue variable to derive data-testid values.
    • Passed testId to FormField and errorTestId to FieldError using fieldNameValue.
  • src/components/internal/FormWrappers/FormTextInput.tsx
    • Added fieldNameValue variable to derive data-testid values.
    • Passed testId to FormField and errorTestId to InputBase using fieldNameValue.
  • src/components/internal/StructuredList/StructuredList.tsx
    • Added data-testid attribute to dd elements, dynamically using the item label.
  • tests/models/external-components/transactionDetails.page.ts
    • Updated constructor to optionally accept a rootElementSelector and default to component-root.
    • Modified referenceId locator to use getByTestId with the new data-testid format.
  • tests/models/external-components/transactionsOverview.page.ts
    • Updated constructor to optionally accept a rootElementSelector.
  • tests/models/internal-components/dataGrid.ts
    • Updated constructor to optionally accept a rootElementSelector and default to component-root.
    • Modified getCell method to use getByTestId for locating cells.
  • tests/models/internal-components/filterBar.ts
    • Updated constructor to optionally accept a rootElementSelector and default to component-root.
  • tests/utils/datePicker.ts
    • Updated locators for month name, timezone, and current day to use getByTestId.
  • tests/utils/utils.ts
    • Updated getComponentRoot function to use getByTestId('component-root').
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@german664 german664 self-assigned this Mar 13, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces stable test hooks (data-testid) across various shared UI components, which is a great step towards more robust and less brittle integration tests. The changes are well-implemented, consistently applying data-testid attributes and updating Playwright page models and helpers to use them. I've found one area for potential improvement in StructuredList.tsx regarding the value used for data-testid to make it even more resilient. Overall, this is a solid refactoring that will improve the testability of the codebase.

german664 and others added 2 commits March 17, 2026 14:50
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Glad Chinda <117656861+glad-adyen@users.noreply.github.com>
getCell(label: string, row = 0) {
return this.getRow(row).locator(`div[aria-labelledby=${label}]`);
getCell(testId: string, row = 0) {
return this.getRow(row).getByTestId(label);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we missed switching to the testId parameter in the body of the function.

Suggested change
return this.getRow(row).getByTestId(label);
return this.getRow(row).getByTestId(testId);


return (
<div className={cx('adyen-pe-payment-link-creation-form__field-container', className)}>
<div className={cx('adyen-pe-payment-link-creation-form__field-container', className)} role="group" aria-label={label} data-testid={testId}>
Copy link
Contributor

@glad-adyen glad-adyen Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this modified to have a "group" role here? The "group" role is particularly useful for defining a logical group of related interactive elements. Since it might be a bit tricky to establish the content of children, it is better to remove it.

Suggested change
<div className={cx('adyen-pe-payment-link-creation-form__field-container', className)} role="group" aria-label={label} data-testid={testId}>
<div className={cx('adyen-pe-payment-link-creation-form__field-container', className)} data-testid={testId}>

validate,
}: FormSelectProps<TFieldValues>) {
const { control, fieldsConfig, getValues, setValue } = useWizardFormContext<TFieldValues>();
const fieldNameValue = String(fieldName);
Copy link
Contributor

@glad-adyen glad-adyen Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this explicit String() casting needed here?

Using the fieldName value directly in the template literal (like so: form-field-${fieldName} or field-error-${fieldName}) implicitly has the same effect as casting to string.

Also, would be nice to double check and ensure that the fieldName prop is always a non-empty string. Otherwise, it would result in malformed and less useful test ids.

}: FormTextInputProps<TFieldValues>) {
const { control, fieldsConfig } = useWizardFormContext<TFieldValues>();
const { i18n } = useCoreContext();
const fieldNameValue = String(fieldName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. See other comment

)}
</dt>
<dd className={cx(SL_CONTENT_CLASS, VALUE_COL_CLASS)}>
<dd className={cx(SL_CONTENT_CLASS, VALUE_COL_CLASS)} data-testid={`${item.key}-value`}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thinking, item.key may not be the ideal choice for constructing test ids, since it is usually a translation key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants