Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const ShopperPhoneField = () => {

return (
<VisibleField<PaymentLinkCreationFormValues> name="telephoneNumber">
<FormField label={i18n.get('payByLink.creation.fields.shopperPhone.label')} optional={!isRequired}>
<FormField label={i18n.get('payByLink.creation.fields.shopperPhone.label')} optional={!isRequired} testId="form-field-telephoneNumber">
<Controller<PaymentLinkCreationFormValues>
name="telephoneNumber"
control={control}
Expand Down Expand Up @@ -136,6 +136,7 @@ export const ShopperPhoneField = () => {
isValid={!fieldState.error && !!field.value}
isInvalid={isInvalid}
errorMessage={fieldState.error?.message}
errorTestId="field-error-telephoneNumber"
maxLength={PAYMENT_LINK_CREATION_FIELD_LENGTHS.telephoneNumber.max}
readonly={isReadOnly}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@ export const AmountField = () => {

return (
<VisibleField<PaymentLinkCreationFormValues> name={VALUE_FIELD_NAME}>
<FormField label={i18n.get('payByLink.creation.fields.amount.label')} optional={false} supportText={undefined} className={undefined}>
<FormField
label={i18n.get('payByLink.creation.fields.amount.label')}
optional={false}
supportText={undefined}
className={undefined}
testId="form-field-amount.value"
>
<Controller<PaymentLinkCreationFormValues>
name={VALUE_FIELD_NAME}
control={control}
Expand All @@ -88,7 +94,7 @@ export const AmountField = () => {
maxValue={MAX_AMOUNT}
readonly={{ amount: isAmountReadOnly, currency: isCurrencyReadOnly }}
/>
{isInvalid && errorMessage && <FieldError errorMessage={errorMessage} />}
{isInvalid && errorMessage && <FieldError errorMessage={errorMessage} testId="field-error-amount.value" />}
</>
);
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export const ValidityField: FunctionalComponent<ValidityFieldProps> = ({ configu
label={i18n.get('payByLink.creation.fields.validity.label')}
supportText={i18n.get('payByLink.creation.fields.validity.supportText')}
optional={!isDurationUnitRequired && !isDurationQuantityRequired}
testId="form-field-linkValidity.durationUnit"
>
<Select
selected={validityValue}
Expand All @@ -186,7 +187,11 @@ export const ValidityField: FunctionalComponent<ValidityFieldProps> = ({ configu
/>
</FormField>
{validityValue === FLEXIBLE_ID && (
<FormField label={i18n.get('payByLink.creation.fields.validity.customDuration.label')} optional={false}>
<FormField
label={i18n.get('payByLink.creation.fields.validity.customDuration.label')}
optional={false}
testId="form-field-linkValidity.quantity"
>
<InputBase
{...durationQuantityField}
dropdown={{
Expand All @@ -207,7 +212,9 @@ export const ValidityField: FunctionalComponent<ValidityFieldProps> = ({ configu
</FormField>
)}
</div>
{isInvalid && errorMessage && <FieldError errorMessage={errorMessage} withTopMargin />}
{isInvalid && errorMessage && (
<FieldError errorMessage={errorMessage} testId="field-error-linkValidity.quantity" withTopMargin />
)}
</div>
);
}}
Expand Down
18 changes: 15 additions & 3 deletions src/components/external/PayoutDetails/components/PayoutData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,12 @@ export const PayoutData = ({
{
<div className={PD_CARD_CLASS}>
<Card noPadding>
<StructuredList items={fundsCaptured} renderLabel={payoutFundsCapturedTypeLabelRenderer} />
<div data-testid="payout-funds-captured-breakdown">
<StructuredList
items={fundsCaptured}
renderLabel={payoutFundsCapturedTypeLabelRenderer}
/>
</div>
</Card>
</div>
}
Expand Down Expand Up @@ -285,7 +290,9 @@ export const PayoutData = ({
</Typography>
}
>
<StructuredList items={adjustments?.additions} renderLabel={payoutAdjustmentTypeLabelRenderer} />
<div data-testid="payout-adjustments-additions-breakdown">
<StructuredList items={adjustments?.additions} renderLabel={payoutAdjustmentTypeLabelRenderer} />
</div>
</Card>
</div>
)}
Expand All @@ -299,7 +306,12 @@ export const PayoutData = ({
</Typography>
}
>
<StructuredList items={adjustments?.subtractions} renderLabel={payoutAdjustmentTypeLabelRenderer} />
<div data-testid="payout-adjustments-subtractions-breakdown">
<StructuredList
items={adjustments?.subtractions}
renderLabel={payoutAdjustmentTypeLabelRenderer}
/>
</div>
</Card>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,12 @@ const TransactionsExport = ({ disabled, filters, now }: { disabled?: boolean; fi

const renderAlertError = useCallback(
() => (
<Alert onClose={dismissExportError} className={classes.errorAlert} type={AlertTypeOption.CRITICAL}>
<Alert
onClose={dismissExportError}
className={classes.errorAlert}
type={AlertTypeOption.CRITICAL}
data-testid="transactions-export-error-alert"
>
<Typography variant={TypographyVariant.BODY}>{i18n.get('transactions.overview.export.actions.error')}</Typography>
</Alert>
),
Expand Down Expand Up @@ -305,9 +310,9 @@ const TransactionsExport = ({ disabled, filters, now }: { disabled?: boolean; fi
targetElement={exportButtonRef}
title={exportButtonLabel}
>
<div className={classes.popover}>
<div className={classes.popover} data-testid="transactions-export-popover">
<div className={classes.popoverSections}>
<div className={cx(classes.popoverSection, classes.filtersSection)}>
<div className={cx(classes.popoverSection, classes.filtersSection)} data-testid="transactions-export-filters">
<SectionTitle>{`${activeFiltersTitle}:`}</SectionTitle>
{activeFilters.map(filter => (
<Tag label={i18n.get(filter)} key={filter} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/external/UIElement/UIElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export class UIElement<P> extends BaseElement<P & UIElementProps> implements IUI
>
<AnalyticsProvider componentName={this.displayName} analyticsEnabled={core?.analyticsEnabled ?? true}>
{this.componentToRender && (
<section ref={this.compRef} className={cx('adyen-pe-component', this.customClassNames)}>
<section ref={this.compRef} className={cx('adyen-pe-component', this.customClassNames)} data-testid="component-root">
<div className="adyen-pe-component__container">{this.componentToRender()}</div>
</section>
)}
Expand Down
14 changes: 11 additions & 3 deletions src/components/internal/Alert/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ export const Alert = ({
onClose,
actions,
variant = AlertVariantOption.DEFAULT,
'data-testid': dataTestId,
}: AlertProps) => {
const { i18n } = useCoreContext();
const hasActions = !!actions?.length;
const shouldShowCloseButton = onClose && (variant !== AlertVariantOption.TIP || closeButton);

return (
<div className={cx('adyen-pe-alert', `adyen-pe-alert--${type}`, `adyen-pe-alert--${variant}`, className)} role="alert">
<div
data-testid={dataTestId}
className={cx('adyen-pe-alert', `adyen-pe-alert--${type}`, `adyen-pe-alert--${variant}`, className)}
role="alert"
>
<AlertIcon type={type} className="adyen-pe-alert__icon" />
<div className="adyen-pe-alert__content-container">
<div className="adyen-pe-alert__content">
Expand All @@ -44,7 +52,7 @@ export const Alert = ({
)}
{children}
</div>
{!!actions?.length && (
{hasActions && (
<div className="adyen-pe-alert__actions">
{actions?.map((action, index) => (
<Button key={index} onClick={action.onClick} variant={ButtonVariant.TERTIARY}>
Expand All @@ -54,7 +62,7 @@ export const Alert = ({
</div>
)}
</div>
{onClose && (variant !== AlertVariantOption.TIP || closeButton) && (
{shouldShowCloseButton && (
<div className="adyen-pe-alert__close-button">
<Button
iconButton
Expand Down
1 change: 1 addition & 0 deletions src/components/internal/Alert/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface AlertProps {
actions?: AlertAction[];
className?: string;
closeButton?: boolean;
'data-testid'?: string;
type: AlertTypeOption;
title?: VNode<Element> | string;
description?: VNode<Element> | string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const CalendarGrid = forwardRef(({ cursorRootProps, onlyCellsWithin, prepare, ge
<ol className={'adyen-pe-calendar'} role="none" {...cursorRootProps}>
{grid.map(block => (
<li key={block.datetime} className={'adyen-pe-calendar__month'} role="none">
<div className={'adyen-pe-calendar__month-name'} role="none">
<div className={'adyen-pe-calendar__month-name'} role="none" data-testid="calendar-month-name">
<time dateTime={block.datetime} aria-hidden="true">
{block.label}
</time>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const CalendarGridDate = fixedForwardRef(
const withinRange = flags.WITHIN_RANGE;

props['data-today'] = flags.CURRENT;
if (flags.CURRENT) props['data-testid'] = 'calendar-current-day';
props['data-first-week-day'] = flags.LINE_START;
props['data-last-week-day'] = flags.LINE_END;
props['data-weekend'] = flags.WEEKEND;
Expand Down
1 change: 1 addition & 0 deletions src/components/internal/DataGrid/DataGridCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default function DataGridCell({
return (
<div
role="cell"
data-testid={column}
className={cx('adyen-pe-data-grid__cell', {
'adyen-pe-data-grid__cell--right': position === 'right',
'adyen-pe-data-grid__cell--center': position === 'center',
Expand Down
6 changes: 4 additions & 2 deletions src/components/internal/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const DatePicker = forwardRef((props: DatePickerProps, ref) => {
}, [setLastUpdatedTimestamp, props.onHighlight]);

return (
<div className={datePickerClassName}>
<div className={datePickerClassName} data-testid="date-picker">
<div className={'adyen-pe-datepicker__selector-container'}>
<TimeRangeSelector
now={props.now}
Expand Down Expand Up @@ -79,7 +79,9 @@ const DatePicker = forwardRef((props: DatePickerProps, ref) => {
trackCurrentDay={true}
/>
{withTimezone && (
<div className={'adyen-pe-datepicker__timezone'}>{i18n.get('common.filters.types.date.timezoneInfo', timezoneI18nOptions)}</div>
<div className={'adyen-pe-datepicker__timezone'} data-testid="date-picker-timezone">
{i18n.get('common.filters.types.date.timezoneInfo', timezoneI18nOptions)}
</div>
)}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/internal/FilterBar/FilterBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const FilterBar = (props: PropsWithChildren<FilterBarProps>) => {
return props.showingFilters ? (
<div
role="group"
data-testId="filter-bar"
data-testid="filter-bar"
aria-label={i18n.get(props.ariaLabelKey ?? 'common.filters.label')}
className={cx('adyen-pe-filter-bar', { 'adyen-pe-filter-bar--mobile': props.isMobileContainer })}
id={props.filterBarElementId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import cx from 'classnames';
interface FieldErrorProps {
id?: string;
errorMessage: string;
testId?: string;
withTopMargin?: boolean;
}

export const FieldError = ({ id, errorMessage, withTopMargin }: FieldErrorProps) => {
export const FieldError = ({ id, errorMessage, testId, withTopMargin }: FieldErrorProps) => {
return (
<div className={cx('adyen-pe-field-error', { 'adyen-pe-field-error--with-top-margin': withTopMargin })} id={id}>
<div className={cx('adyen-pe-field-error', { 'adyen-pe-field-error--with-top-margin': withTopMargin })} id={id} data-testid={testId}>
<Icon name="cross-circle-fill" className="adyen-pe-field-error__icon" />
<span className="adyen-pe-field-error__message">{errorMessage}</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export const Dropzone = fixedForwardRef<DropzoneProps, HTMLInputElement>((props,
onChange={handleFileChange}
onInvalid={handleInputInvalid}
aria-invalid={isInvalid}
data-testId="dropzone-input"
data-testid="dropzone-input"
/>

{/* Using the label element here to expose a user interaction surface for the file input element. */}
Expand Down
4 changes: 3 additions & 1 deletion src/components/internal/FormFields/InputBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function InputBase(
onBlur,
onFocusHandler,
errorMessage,
errorTestId,
iconBeforeSlot,
iconAfterSlot,
dropdown,
Expand Down Expand Up @@ -111,6 +112,7 @@ function InputBase(
isInvalid: iiv,
isValid: iv,
isCollatingErrors: ce,
errorTestId: eti,
autoFocus,
autofocus,
...newProps
Expand Down Expand Up @@ -196,7 +198,7 @@ function InputBase(
) : (
inputElement
)}
{isInvalid && errorMessage && <FieldError id={uniqueId} errorMessage={errorMessage} />}
{isInvalid && errorMessage && <FieldError id={uniqueId} errorMessage={errorMessage} testId={errorTestId} />}
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ const BalanceAccountSelector = memo(
<div className={data.contentClassName}>
{data.item.name && <span className={BA_SELECTOR_ACCOUNT_LABEL_CLASS}>{data.item.name}</span>}
{data.item.id !== ALL_BALANCE_ACCOUNTS_SELECTION_ID && (
<span className={data.item.name ? BA_SELECTOR_ACCOUNT_ID_CLASS : BA_SELECTOR_ACCOUNT_LABEL_CLASS}>{data.item.id}</span>
<span
className={data.item.name ? BA_SELECTOR_ACCOUNT_ID_CLASS : BA_SELECTOR_ACCOUNT_LABEL_CLASS}
data-testid="balance-account-id"
>
{data.item.id}
</span>
)}
</div>
{renderDefaultSingleSelectionCheckedness(data)}
Expand Down
1 change: 1 addition & 0 deletions src/components/internal/FormFields/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export interface InputBaseProps {
role?: JSX.HTMLAttributes<HTMLInputElement>['role'];
min?: number;
errorMessage?: string;
errorTestId?: string;
lang?: HTMLInputElement['lang'];
iconBeforeSlot?: ComponentChildren;
iconAfterSlot?: ComponentChildren;
Expand Down
5 changes: 3 additions & 2 deletions src/components/internal/FormWrappers/FormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ const FormField = ({
supportText,
children,
className,
}: PropsWithChildren<{ label: string; optional: boolean; supportText?: string; className?: string }>) => {
testId,
}: PropsWithChildren<{ label: string; optional: boolean; supportText?: string; className?: string; testId?: string }>) => {
const { i18n } = useCoreContext();

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

<div className="adyen-pe-payment-link-creation-form__field-label-container">
<Typography
el={TypographyElement.SPAN}
Expand Down
Loading
Loading