Skip to content

Conversation

@Raushen
Copy link
Contributor

@Raushen Raushen commented Feb 10, 2026

No description provided.

@Raushen Raushen self-assigned this Feb 10, 2026
Copilot AI review requested due to automatic review settings February 10, 2026 09:15
@Raushen Raushen requested review from a team as code owners February 10, 2026 09:15
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts several grid/CardView-related option defaults so that localized strings are resolved at usage time (via messageLocalization.format(...)) rather than being precomputed in defaultOptions, and adds a comprehensive Jest localization test suite + supporting page-object models to prevent regressions.

Changes:

  • Replace many localized string defaults in option objects with undefined and add runtime localization fallbacks in views/controllers.
  • Add CardView localization Jest tests covering column chooser, filter panel, filter builder operations, pager aria-label, sorting context menu, boolean display text, no-data text, header filter texts, search placeholder, and editing texts.
  • Add/extend test page-object models (Popup, Pager, HeaderPanel, CardView, etc.) to support the new localization tests.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
packages/devextreme/js/__internal/ui/tests/mock/model/tree_view.ts Exposes getNodeByText for tests.
packages/devextreme/js/__internal/ui/tests/mock/model/textbox.ts Adds input accessor for placeholder assertions.
packages/devextreme/js/__internal/ui/tests/mock/model/popup.ts New popup POM used by multiple test models.
packages/devextreme/js/__internal/pagination/content.tsx Adds localized fallback for navigation aria-label.
packages/devextreme/js/__internal/pagination/common/base_pagination_props.ts Removes eager localization from default props (label: undefined).
packages/devextreme/js/__internal/pagination/tests/mock/model/pager.ts New Pager POM for aria-label tests.
packages/devextreme/js/__internal/grids/new/grid_core/sorting_controller/options.ts Removes eager localization from sorting option defaults.
packages/devextreme/js/__internal/grids/new/grid_core/search/view.tsx Adds localized fallback for search placeholder in the view.
packages/devextreme/js/__internal/grids/new/grid_core/search/options.ts Removes eager localization from search placeholder default.
packages/devextreme/js/__internal/grids/new/grid_core/pager/options.ts Removes eager localization from pager aria label default.
packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/options.ts Removes eager localization from header filter texts defaults.
packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/legacy_header_filter.ts Adds localized fallback for header filter empty value text.
packages/devextreme/js/__internal/grids/new/grid_core/filtering/filter_panel/options.ts Removes eager localization from filter panel / filter builder text defaults.
packages/devextreme/js/__internal/grids/new/grid_core/editing/popup/view.ts Adds localized fallbacks for editing popup texts.
packages/devextreme/js/__internal/grids/new/grid_core/editing/options.ts Removes eager localization from editing text defaults.
packages/devextreme/js/__internal/grids/new/grid_core/editing/controller.ts Adds localized fallback for confirm delete message; adjusts awaits.
packages/devextreme/js/__internal/grids/new/grid_core/content_view/view.tsx Adds localized fallback for no-data text rendering.
packages/devextreme/js/__internal/grids/new/grid_core/content_view/options.ts Removes eager localization from no-data text default.
packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts Removes eager localization for boolean true/false texts and adds runtime fallback.
packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.tsx Adds localized fallback for empty panel text; simplifies popup toolbar usage.
packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/column_chooser.tsx Ensures toolbar title has a localized fallback at render time.
packages/devextreme/js/__internal/grids/new/card_view/context_menu/controller.ts Adds localized fallbacks for sorting context menu item texts.
packages/devextreme/js/__internal/grids/new/card_view/tests/cardview.localization.test.ts New end-to-end localization coverage for CardView behaviors.
packages/devextreme/js/__internal/grids/new/card_view/tests/mock/model/header_panel.ts New HeaderPanel POM for context-menu / header filter tests.
packages/devextreme/js/__internal/grids/new/card_view/tests/mock/model/header_item.ts New HeaderItem POM for header interactions.
packages/devextreme/js/__internal/grids/new/card_view/tests/mock/model/card_view.ts New CardView POM integrating common grid-core POMs.
packages/devextreme/js/__internal/grids/new/card_view/tests/mock/model/card.ts New Card POM for boolean localization assertions.
packages/devextreme/js/__internal/grids/new/card_view/tests/mock/helpers/utils.ts New CardView test harness (setup/teardown/flush helpers).
packages/devextreme/js/__internal/grids/grid_core/header_filter/m_header_filter_core.ts Adds localized fallbacks for OK/Cancel button texts.
packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_panel.ts Adds localized fallbacks for filter panel texts and makes defaults undefined.
packages/devextreme/js/__internal/grids/grid_core/column_chooser/const.ts Changes column chooser defaults to undefined.
packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/header_filter.ts New HeaderFilter POM built atop Popup POM.
packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/grid_core.ts Enhances shared grid-core POM and adds CardView compatibility/helpers.
packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/filter_panel.ts New FilterPanel POM (supports different widget prefixes).
packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/edit_form.ts Extends edit-form POM with popup toolbar accessors.
packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/data_grid_base.ts New base POM restoring DataGrid-only APIs removed from GridCoreModel.
packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/confirmation_dialog.ts New ConfirmationDialog POM for delete-confirmation localization.
packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/column_chooser.ts Refactors ColumnChooser POM to reuse PopupModel and support multiple widgets.
packages/devextreme/js/__internal/grids/data_grid/tests/mock/model/data_grid.ts Switches DataGrid POM to extend the new DataGridBaseModel.
packages/devextreme/js/__internal/filter_builder/tests/mock/model/filter_builder.ts New FilterBuilder POM for verifying localized operations.

Comment on lines +13 to +16
export class PopupModel {
protected getPopupWrapper(): HTMLElement {
return document.body.querySelector(`.${CLASSES.popupWrapper}`) as HTMLElement;
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

getPopupWrapper() currently selects the first .dx-popup-wrapper in document.body. If multiple popups are present, derived models (ColumnChooser, dialogs, header filter, etc.) may attach to the wrong popup and make tests flaky. Consider allowing PopupModel to be constructed with an identifying selector/class, or selecting the most recently opened wrapper (e.g., last match) when appropriate.

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +16
public getInput(): HTMLInputElement {
return this.root.querySelector('input') as HTMLInputElement;
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

getInput() casts the result of querySelector('input') to HTMLInputElement, but querySelector can return null (and this selector may match unintended inputs). Consider querying a more specific selector (e.g., .dx-texteditor-input) and returning HTMLInputElement | null (or throwing if absence is an error for the test).

Copilot uses AI. Check for mistakes.
this.onSaving.peek()(eventArgs);

// eslint-disable-next-line @typescript-eslint/await-thenable
await eventArgs.promise;
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

Same issue as in addCard(): eventArgs.promise is optional but awaited directly. Consider awaiting eventArgs.promise ?? Promise.resolve() to avoid awaiting undefined and potential lint/type issues.

Suggested change
await eventArgs.promise;
await (eventArgs.promise ?? Promise.resolve());

Copilot uses AI. Check for mistakes.
Comment on lines +76 to +80
const actualTitle = title || messageLocalization.format('dxDataGrid-columnChooserTitle');
const toolbarItems = [
{ text: actualTitle, toolbar: 'top' as const, location: 'before' as const },
];

Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

actualTitle is computed for the toolbar, but setPopupAttributes() still sets the popup aria-label to the localized default (dxDataGrid-columnChooserTitle) regardless of a custom title prop. For accessibility consistency, consider using actualTitle (or title ?? localizedDefault) for the aria-label as well.

Copilot uses AI. Check for mistakes.
Comment on lines 19 to +22
width: 250,
height: 260,
get title() {
return messageLocalization.format('dxDataGrid-columnChooserTitle');
},
get emptyPanelText() {
return messageLocalization.format('dxDataGrid-columnChooserEmptyText');
},
title: undefined,
emptyPanelText: undefined,
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

columnChooser.title and columnChooser.emptyPanelText defaults were changed to undefined, but m_column_chooser.ts uses columnChooserOptions.title directly for the popup toolbar item text. With these defaults, the Column Chooser popup title/empty text can become blank unless the user provides them. Consider restoring the localized default (e.g., via getters) or add a fallback at the usage site (e.g., ?? messageLocalization.format(...)).

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +21
export class PopupModel {
protected getPopupWrapper(): HTMLElement {
return document.body.querySelector(`.${CLASSES.popupWrapper}`) as HTMLElement;
}

public getOverlayContent(): HTMLElement {
const wrapper = this.getPopupWrapper();
return wrapper?.querySelector(`.${CLASSES.overlayContent}`) as HTMLElement;
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

getPopupWrapper() / getOverlayContent() are typed to always return HTMLElement, but querySelector(...) can return null at runtime. This causes misleading typing (e.g., isVisible() and callers can assume non-null) and may lead to runtime errors when the popup is not present. Consider returning HTMLElement | null and either guarding in callers or throwing with a clear error when the popup is expected to exist.

Copilot uses AI. Check for mistakes.
this.onInitNewCard.peek()(eventArgs);

// eslint-disable-next-line @typescript-eslint/await-thenable
await eventArgs.promise;
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

eventArgs.promise is optional (promise?: Promise<void>), but the code does await eventArgs.promise;. If the action doesn't set promise, this awaits undefined (a no-op) and can also trigger @typescript-eslint/await-thenable depending on lint/type inference. Consider await (eventArgs.promise ?? Promise.resolve()); (same applies to the similar pattern in save()).

Suggested change
await eventArgs.promise;
await (eventArgs.promise ?? Promise.resolve());

Copilot uses AI. Check for mistakes.
private readonly dragAndDropModeConfig: ReadonlySignal<TreeViewProperties> = computed(() => ({
noDataText: this.options.oneWay('columnChooser.emptyPanelText').value,
noDataText: this.options.oneWay('columnChooser.emptyPanelText').value
|| messageLocalization.format('dxDataGrid-columnChooserEmptyText'),
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

This fallback uses ||, so an explicitly configured empty string for columnChooser.emptyPanelText will be ignored and replaced with the localized default. If empty string should be a valid override, prefer ?? instead of ||.

Suggested change
|| messageLocalization.format('dxDataGrid-columnChooserEmptyText'),
?? messageLocalization.format('dxDataGrid-columnChooserEmptyText'),

Copilot uses AI. Check for mistakes.
});
$element.attr('title', this.option('filterPanel.texts.filterEnabledHint')!);
const filterEnabledHint = this.option('filterPanel.texts.filterEnabledHint')
|| messageLocalization.format('dxDataGrid-filterPanelFilterEnabledHint');
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

These fallbacks use ||, so an explicitly configured empty string for filterPanel.texts.* will be ignored and replaced with the localized default. If empty string should be a valid override, prefer ?? instead of || (and apply the same change to the other filterPanel.texts.* fallbacks in this file).

Suggested change
|| messageLocalization.format('dxDataGrid-filterPanelFilterEnabledHint');
?? messageLocalization.format('dxDataGrid-filterPanelFilterEnabledHint');

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +25
public getOverlayContent(): HTMLElement {
const wrapper = this.getPopupWrapper();
return wrapper?.querySelector(`.${CLASSES.overlayContent}`) as HTMLElement;
}

public isVisible(): boolean {
return this.getOverlayContent() !== null;
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

isVisible() checks this.getOverlayContent() !== null, but getOverlayContent() can return undefined (when getPopupWrapper() returns null and optional chaining is used). In that case undefined !== null is true, so isVisible() may report visible when no popup exists. Consider returning HTMLElement | null from getOverlayContent() and using a truthiness check like return !!this.getOverlayContent(); (or != null).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant