# DataGrid Tests — Backlog Source file: `tests/controls/test_datagrid.py` Legend: ✅ Done — ⬜ Pending --- ## TestDataGridBehaviour ### Edition flow | # | Status | Test | Description | |---|--------|-----------------------------------------------------------|----------------------------------------------------------| | 1 | ⬜ | `test_i_can_convert_edition_value_for_number` | `"3.14"` → `float`, `"5"` → `int` | | 2 | ⬜ | `test_i_can_convert_edition_value_for_bool` | `"true"`, `"1"`, `"yes"` → `True`; others → `False` | | 3 | ⬜ | `test_i_can_convert_edition_value_for_text` | String value returned unchanged | | 4 | ⬜ | `test_i_can_handle_start_edition` | Sets `edition.under_edition` and returns a cell render | | 5 | ⬜ | `test_i_cannot_handle_start_edition_when_already_editing` | Second call while `under_edition` is set is a no-op | | 6 | ⬜ | `test_i_can_handle_save_edition` | Writes value to data service and clears `under_edition` | | 7 | ⬜ | `test_i_cannot_handle_save_edition_when_not_editing` | Returns partial render without touching the data service | ### Column management | # | Status | Test | Description | |----|--------|---------------------------------------------------------|----------------------------------------------------------------| | 8 | ⬜ | `test_i_can_add_new_column` | Appends column to `_state.columns` and `_columns` | | 9 | ⬜ | `test_i_can_handle_columns_reorder` | Reorders `_state.columns` according to provided list | | 10 | ⬜ | `test_i_can_handle_columns_reorder_ignores_unknown_ids` | Unknown IDs skipped; known columns not in list appended at end | ### Mouse selection | # | Status | Test | Description | |----|--------|-------------------------------------------------|---------------------------------------------------------------| | 11 | ⬜ | `test_i_can_on_mouse_selection_sets_range` | Sets `extra_selected` with `("range", ...)` from two cell IDs | | 12 | ⬜ | `test_i_cannot_on_mouse_selection_when_outside` | `is_inside=False` leaves `extra_selected` unchanged | ### Key pressed | # | Status | Test | Description | |----|--------|--------------------------------------------------|----------------------------------------------------------------------------------------------| | 13 | ⬜ | `test_i_can_on_key_pressed_enter_starts_edition` | `enter` on selected cell enters edition when `enable_edition=True` and nothing under edition | ### Click | # | Status | Test | Description | |----|--------|---------------------------------------------------|-----------------------------------------------------------------| | 14 | ⬜ | `test_i_can_on_click_second_click_enters_edition` | Second click on already-selected cell triggers `_enter_edition` | ### Filtering / sorting | # | Status | Test | Description | |----|--------|--------------------------------------------|-------------------------------------------------------------------------------------| | 15 | ⬜ | `test_i_can_filter_grid` | `filter()` updates `_state.filtered`; filtered DataFrame excludes non-matching rows | | 16 | ⬜ | `test_i_can_apply_sort` | `_apply_sort` returns rows in correct order when a sort definition is present | | 17 | ⬜ | `test_i_can_apply_filter_by_column_values` | Column filter (non-FILTER_INPUT) keeps only matching rows | ### Format rules priority | # | Status | Test | Description | |----|--------|----------------------------------------------------------------------|------------------------------------------------------------------| | 18 | ⬜ | `test_i_can_get_format_rules_cell_level_takes_priority` | Cell format overrides row, column and table format | | 19 | ⬜ | `test_i_can_get_format_rules_row_level_takes_priority_over_column` | Row format overrides column and table when no cell format | | 20 | ⬜ | `test_i_can_get_format_rules_column_level_takes_priority_over_table` | Column format overrides table when no cell or row format | | 21 | ⬜ | `test_i_can_get_format_rules_falls_back_to_table_format` | Table format returned when no cell, row or column format defined | --- ## TestDataGridRender ### Table structure | # | Status | Test | Description | |----|--------|------------------------------------------|-------------------------------------------------------------------------------------------| | 22 | ✅ | `test_i_can_render_table_wrapper` | ID `tw_{id}`, class `dt2-table-wrapper`, 3 sections: selection manager, table, scrollbars | | 23 | ✅ | `test_i_can_render_table` | ID `t_{id}`, class `dt2-table`, 3 containers: header, body wrapper, footer | | 24 | ✅ | `test_i_can_render_table_has_scrollbars` | Scrollbars overlay contains vertical and horizontal tracks | ### render_partial fragments | # | Status | Test | Description | |----|--------|---------------------------------------------------|--------------------------------------------------------------------------------------| | 25 | ✅ | `test_i_can_render_partial_body` | Returns `(selection_manager, body_wrapper)` — body wrapper has `hx-on::after-settle` | | 26 | ✅ | `test_i_can_render_partial_table` | Returns `(selection_manager, table)` — table has `hx-on::after-settle` | | 27 | ✅ | `test_i_can_render_partial_header` | Returns header with `hx-on::after-settle` containing `setColumnWidth` | | 28 | ✅ | `test_i_can_render_partial_cell_by_pos` | Returns `(selection_manager, cell)` for a specific `(col, row)` position | | 29 | ✅ | `test_i_can_render_partial_cell_with_no_position` | Returns only `(selection_manager,)` when no `pos` or `cell_id` given | ### Edition cell | # | Status | Test | Description | |----|--------|-----------------------------------------------|----------------------------------------------------------------------------------------------------------| | 30 | ⬜ | `test_i_can_render_body_cell_in_edition_mode` | When `edition.under_edition` matches, `mk_body_cell` returns an input cell with class `dt2-cell-edition` | ### Cell content — search highlighting | # | Status | Test | Description | |----|--------|-----------------------------------------------------------------------------|-----------------------------------------------------------------| | 31 | ⬜ | `test_i_can_render_body_cell_content_with_search_highlight` | Matching keyword produces a `Span` with class `dt2-highlight-1` | | 32 | ⬜ | `test_i_can_render_body_cell_content_with_no_highlight_when_keyword_absent` | Non-matching keyword produces no `dt2-highlight-1` span | ### Footer | # | Status | Test | Description | |----|--------|-----------------------------------------------------------|--------------------------------------------------------------------------| | 33 | ⬜ | `test_i_can_render_footers_wrapper` | `mk_footers` renders with ID `tf_{id}` and class `dt2-footer` | | 34 | ⬜ | `test_i_can_render_aggregation_cell_sum` | `mk_aggregation_cell` with `FooterAggregation.Sum` renders the sum value | | 35 | ⬜ | `test_i_cannot_render_aggregation_cell_for_hidden_column` | Hidden column returns `Div(cls="dt2-col-hidden")` | --- ## Summary | Class | Total | ✅ Done | ⬜ Pending | |-------------------------|--------|--------|-----------| | `TestDataGridBehaviour` | 21 | 0 | 21 | | `TestDataGridRender` | 14 | 8 | 6 | | **Total** | **35** | **8** | **27** |