@svgrid/grid 1.1.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/dist/FlexRender.svelte +96 -96
  2. package/dist/SvGrid.controller.svelte.js +17 -6
  3. package/dist/SvGrid.css +2012 -2012
  4. package/dist/SvGrid.svelte +2571 -2346
  5. package/dist/SvGridDropdown.svelte +7 -3
  6. package/dist/build-api.js +2 -2
  7. package/dist/cdn/svgrid.js +13504 -0
  8. package/dist/cdn/svgrid.svelte-external.js +11188 -0
  9. package/dist/cell-values.d.ts +1 -1
  10. package/dist/cell-values.js +7 -7
  11. package/dist/column-types.js +1 -1
  12. package/dist/core.d.ts +1 -1
  13. package/dist/core.js +2 -2
  14. package/dist/summaries.js +4 -4
  15. package/package.json +12 -2
  16. package/src/FlexRender.svelte +96 -96
  17. package/src/SvGrid.controller.svelte.ts +2363 -2352
  18. package/src/SvGrid.css +2012 -2012
  19. package/src/SvGrid.svelte +2571 -2346
  20. package/src/SvGrid.types.ts +537 -537
  21. package/src/SvGridDropdown.svelte +7 -3
  22. package/src/a11y.contract.test.ts +49 -49
  23. package/src/a11y.test.ts +59 -59
  24. package/src/a11y.ts +59 -59
  25. package/src/build-api.ts +683 -683
  26. package/src/cell-formatting.ts +169 -169
  27. package/src/cell-values.ts +4 -4
  28. package/src/column-types.ts +1 -1
  29. package/src/core.performance.test.ts +30 -30
  30. package/src/core.ts +1077 -1077
  31. package/src/createGrid.svelte.ts +42 -42
  32. package/src/createGrid.test.ts +10 -10
  33. package/src/createGridState.svelte.ts +17 -17
  34. package/src/editing.ts +669 -669
  35. package/src/flex-render.ts +3 -3
  36. package/src/index.ts +208 -208
  37. package/src/keyboard.test.ts +59 -59
  38. package/src/keyboard.ts +97 -97
  39. package/src/merge-objects.ts +48 -48
  40. package/src/render-component.ts +28 -28
  41. package/src/spreadsheet.test.ts +489 -489
  42. package/src/spreadsheet.ts +304 -304
  43. package/src/static-functions.ts +11 -11
  44. package/src/subscribe.ts +38 -38
  45. package/src/summaries.ts +4 -4
  46. package/src/svgrid-wrapper.types.ts +412 -412
  47. package/src/svgrid.features.test.ts +157 -157
  48. package/src/svgrid.wrapper.test.ts +40 -40
  49. package/src/virtualization/column-virtualizer.test.ts +27 -27
  50. package/src/virtualization/column-virtualizer.ts +30 -30
  51. package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
  52. package/src/virtualization/types.ts +30 -30
  53. package/src/virtualization/virtualizer.test.ts +47 -47
  54. package/src/virtualization/virtualizer.ts +296 -296
  55. package/dist/SvGrid.helpers.test.d.ts +0 -1
  56. package/dist/SvGrid.helpers.test.js +0 -298
  57. package/dist/SvGridChart.test.d.ts +0 -1
  58. package/dist/SvGridChart.test.js +0 -62
  59. package/dist/a11y.contract.test.d.ts +0 -1
  60. package/dist/a11y.contract.test.js +0 -39
  61. package/dist/a11y.test.d.ts +0 -1
  62. package/dist/a11y.test.js +0 -44
  63. package/dist/aligned-grids.test.d.ts +0 -1
  64. package/dist/aligned-grids.test.js +0 -75
  65. package/dist/build-api.coverage.test.d.ts +0 -20
  66. package/dist/build-api.coverage.test.js +0 -505
  67. package/dist/cell-formatting.test.d.ts +0 -1
  68. package/dist/cell-formatting.test.js +0 -234
  69. package/dist/cell-render.test.d.ts +0 -1
  70. package/dist/cell-render.test.js +0 -338
  71. package/dist/chart-export.test.d.ts +0 -1
  72. package/dist/chart-export.test.js +0 -302
  73. package/dist/chart.coverage.test.d.ts +0 -1
  74. package/dist/chart.coverage.test.js +0 -748
  75. package/dist/chart.test.d.ts +0 -1
  76. package/dist/chart.test.js +0 -289
  77. package/dist/clipboard.test.d.ts +0 -1
  78. package/dist/clipboard.test.js +0 -700
  79. package/dist/collaboration.coverage.test.d.ts +0 -1
  80. package/dist/collaboration.coverage.test.js +0 -200
  81. package/dist/collaboration.test.d.ts +0 -1
  82. package/dist/collaboration.test.js +0 -65
  83. package/dist/column-groups.test.d.ts +0 -1
  84. package/dist/column-groups.test.js +0 -56
  85. package/dist/column-types.test.d.ts +0 -1
  86. package/dist/column-types.test.js +0 -62
  87. package/dist/columns.test.d.ts +0 -1
  88. package/dist/columns.test.js +0 -625
  89. package/dist/conditional-formatting.test.d.ts +0 -1
  90. package/dist/conditional-formatting.test.js +0 -87
  91. package/dist/core.coverage.test.d.ts +0 -1
  92. package/dist/core.coverage.test.js +0 -186
  93. package/dist/core.performance.test.d.ts +0 -1
  94. package/dist/core.performance.test.js +0 -29
  95. package/dist/createGrid.test.d.ts +0 -1
  96. package/dist/createGrid.test.js +0 -9
  97. package/dist/editing.test.d.ts +0 -1
  98. package/dist/editing.test.js +0 -732
  99. package/dist/editors/cell-editors.coverage.test.d.ts +0 -1
  100. package/dist/editors/cell-editors.coverage.test.js +0 -139
  101. package/dist/editors/cell-editors.test.d.ts +0 -1
  102. package/dist/editors/cell-editors.test.js +0 -75
  103. package/dist/facet-buckets.test.d.ts +0 -1
  104. package/dist/facet-buckets.test.js +0 -296
  105. package/dist/fill-patterns.test.d.ts +0 -1
  106. package/dist/fill-patterns.test.js +0 -81
  107. package/dist/filter-operators.test.d.ts +0 -1
  108. package/dist/filter-operators.test.js +0 -135
  109. package/dist/filtering/excel-filters.test.d.ts +0 -1
  110. package/dist/filtering/excel-filters.test.js +0 -116
  111. package/dist/filtering/locale-filter.test.d.ts +0 -13
  112. package/dist/filtering/locale-filter.test.js +0 -189
  113. package/dist/flex-render.test.d.ts +0 -1
  114. package/dist/flex-render.test.js +0 -142
  115. package/dist/group-aggregate.test.d.ts +0 -1
  116. package/dist/group-aggregate.test.js +0 -32
  117. package/dist/hyperformula-adapter.test.d.ts +0 -1
  118. package/dist/hyperformula-adapter.test.js +0 -205
  119. package/dist/keyboard-handlers.coverage.test.d.ts +0 -1
  120. package/dist/keyboard-handlers.coverage.test.js +0 -495
  121. package/dist/keyboard.test.d.ts +0 -1
  122. package/dist/keyboard.test.js +0 -27
  123. package/dist/menus.test.d.ts +0 -1
  124. package/dist/menus.test.js +0 -560
  125. package/dist/named-views.coverage.test.d.ts +0 -1
  126. package/dist/named-views.coverage.test.js +0 -180
  127. package/dist/named-views.test.d.ts +0 -1
  128. package/dist/named-views.test.js +0 -57
  129. package/dist/new-features.test.d.ts +0 -1
  130. package/dist/new-features.test.js +0 -183
  131. package/dist/render-component.test.d.ts +0 -1
  132. package/dist/render-component.test.js +0 -41
  133. package/dist/row-drag.test.d.ts +0 -1
  134. package/dist/row-drag.test.js +0 -142
  135. package/dist/row-resize.test.d.ts +0 -1
  136. package/dist/row-resize.test.js +0 -329
  137. package/dist/scroll-sync.test.d.ts +0 -1
  138. package/dist/scroll-sync.test.js +0 -290
  139. package/dist/selection.multi-range.test.d.ts +0 -1
  140. package/dist/selection.multi-range.test.js +0 -55
  141. package/dist/selection.test.d.ts +0 -1
  142. package/dist/selection.test.js +0 -647
  143. package/dist/server-data-source.coverage.test.d.ts +0 -1
  144. package/dist/server-data-source.coverage.test.js +0 -154
  145. package/dist/server-data-source.test.d.ts +0 -1
  146. package/dist/server-data-source.test.js +0 -81
  147. package/dist/sparkline.test.d.ts +0 -1
  148. package/dist/sparkline.test.js +0 -52
  149. package/dist/spreadsheet.test.d.ts +0 -1
  150. package/dist/spreadsheet.test.js +0 -446
  151. package/dist/subscribe.test.d.ts +0 -1
  152. package/dist/subscribe.test.js +0 -93
  153. package/dist/svgrid.api-extensions.test.d.ts +0 -14
  154. package/dist/svgrid.api-extensions.test.js +0 -334
  155. package/dist/svgrid.api.test.d.ts +0 -15
  156. package/dist/svgrid.api.test.js +0 -169
  157. package/dist/svgrid.behavior.test.d.ts +0 -15
  158. package/dist/svgrid.behavior.test.js +0 -625
  159. package/dist/svgrid.column-reorder.test.d.ts +0 -15
  160. package/dist/svgrid.column-reorder.test.js +0 -224
  161. package/dist/svgrid.comments-autocomplete.test.d.ts +0 -1
  162. package/dist/svgrid.comments-autocomplete.test.js +0 -96
  163. package/dist/svgrid.context-menu.test.d.ts +0 -1
  164. package/dist/svgrid.context-menu.test.js +0 -102
  165. package/dist/svgrid.features.test.d.ts +0 -1
  166. package/dist/svgrid.features.test.js +0 -129
  167. package/dist/svgrid.interaction.test.d.ts +0 -9
  168. package/dist/svgrid.interaction.test.js +0 -349
  169. package/dist/svgrid.locale-filtering.test.d.ts +0 -15
  170. package/dist/svgrid.locale-filtering.test.js +0 -261
  171. package/dist/svgrid.new-features.wrapper.test.d.ts +0 -1
  172. package/dist/svgrid.new-features.wrapper.test.js +0 -194
  173. package/dist/svgrid.row-pinning.test.d.ts +0 -14
  174. package/dist/svgrid.row-pinning.test.js +0 -250
  175. package/dist/svgrid.set-filter.test.d.ts +0 -17
  176. package/dist/svgrid.set-filter.test.js +0 -268
  177. package/dist/svgrid.wrapper.test.d.ts +0 -1
  178. package/dist/svgrid.wrapper.test.js +0 -59
  179. package/dist/test-setup.d.ts +0 -1
  180. package/dist/test-setup.js +0 -35
  181. package/dist/transaction.test.d.ts +0 -1
  182. package/dist/transaction.test.js +0 -89
  183. package/dist/virtualization/column-virtualizer.test.d.ts +0 -1
  184. package/dist/virtualization/column-virtualizer.test.js +0 -25
  185. package/dist/virtualization/scroll-scaling.test.d.ts +0 -1
  186. package/dist/virtualization/scroll-scaling.test.js +0 -127
  187. package/dist/virtualization/virtualizer.test.d.ts +0 -1
  188. package/dist/virtualization/virtualizer.test.js +0 -41
@@ -1,349 +0,0 @@
1
- /**
2
- * Interaction-driven tests against <SvGrid />. Targeting code paths that
3
- * only run in response to events: keyboard, pointer, scroll, edit lifecycle.
4
- *
5
- * Each test mounts a small grid, fires a synthetic event, awaits a tick,
6
- * then asserts on the api object's snapshot. The goal is breadth: hit as
7
- * many branches inside SvGrid.svelte as possible.
8
- */
9
- import { describe, expect, it } from 'vitest';
10
- import { mount, unmount } from 'svelte';
11
- import SvGrid from './SvGrid.svelte';
12
- import { columnFilteringFeature, createCoreRowModel, createFilteredRowModel, createPaginatedRowModel, createSortedRowModel, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortFns, tableFeatures, } from './index';
13
- const features = tableFeatures({
14
- columnFilteringFeature,
15
- rowSortingFeature,
16
- rowSelectionFeature,
17
- rowPaginationFeature,
18
- });
19
- const rows = Array.from({ length: 25 }, (_, i) => ({
20
- id: i + 1,
21
- name: `Person ${(i + 1).toString().padStart(2, '0')}`,
22
- team: ['Research', 'Compilers', 'Apollo', 'Kernel'][i % 4],
23
- salary: 100000 + i * 1000,
24
- }));
25
- const cols = [
26
- { field: 'name', header: 'Name', width: 220, editorType: 'text' },
27
- { field: 'team', header: 'Team', width: 160, editorType: 'text' },
28
- { field: 'salary', header: 'Salary', width: 140, editorType: 'number' },
29
- ];
30
- function mountInteractive(overrides = {}) {
31
- return new Promise((res, rej) => {
32
- const target = document.createElement('div');
33
- document.body.appendChild(target);
34
- let api = null;
35
- const app = mount(SvGrid, {
36
- target,
37
- props: {
38
- data: rows,
39
- columns: cols,
40
- features,
41
- _rowModels: {
42
- coreRowModel: createCoreRowModel(),
43
- filteredRowModel: createFilteredRowModel(),
44
- sortedRowModel: createSortedRowModel(sortFns),
45
- paginatedRowModel: createPaginatedRowModel(),
46
- },
47
- rowHeight: 36,
48
- containerHeight: 480,
49
- virtualization: false,
50
- enableInlineEditing: true,
51
- enableCellSelection: true,
52
- showPagination: true,
53
- pageSize: 10,
54
- showColumnFilters: true,
55
- showGlobalFilter: true,
56
- showRowSelection: true,
57
- onApiReady(received) {
58
- api = received;
59
- const grid = target.querySelector('[role="grid"]') ?? target;
60
- res({
61
- api,
62
- target,
63
- grid,
64
- destroy: () => {
65
- unmount(app);
66
- target.remove();
67
- },
68
- });
69
- },
70
- ...overrides,
71
- },
72
- });
73
- queueMicrotask(() => {
74
- if (!api)
75
- rej(new Error('onApiReady never fired'));
76
- });
77
- });
78
- }
79
- const tick = () => new Promise((r) => queueMicrotask(r));
80
- describe('SvGrid interactions - keyboard', () => {
81
- it('dispatches ArrowRight without throwing', async () => {
82
- const { grid, destroy } = await mountInteractive();
83
- try {
84
- const ev = new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true });
85
- grid.dispatchEvent(ev);
86
- await tick();
87
- expect(true).toBe(true);
88
- }
89
- finally {
90
- destroy();
91
- }
92
- });
93
- it('dispatches ArrowDown / ArrowUp / Home / End', async () => {
94
- const { grid, destroy } = await mountInteractive();
95
- try {
96
- for (const key of ['ArrowDown', 'ArrowUp', 'Home', 'End', 'PageDown', 'PageUp']) {
97
- grid.dispatchEvent(new KeyboardEvent('keydown', { key, bubbles: true }));
98
- await tick();
99
- }
100
- expect(true).toBe(true);
101
- }
102
- finally {
103
- destroy();
104
- }
105
- });
106
- it('dispatches Ctrl+Home and Ctrl+End', async () => {
107
- const { grid, destroy } = await mountInteractive();
108
- try {
109
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', ctrlKey: true, bubbles: true }));
110
- await tick();
111
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'End', ctrlKey: true, bubbles: true }));
112
- await tick();
113
- expect(true).toBe(true);
114
- }
115
- finally {
116
- destroy();
117
- }
118
- });
119
- it('dispatches Escape to close any open menu / cancel edit', async () => {
120
- const { grid, destroy } = await mountInteractive();
121
- try {
122
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
123
- await tick();
124
- expect(true).toBe(true);
125
- }
126
- finally {
127
- destroy();
128
- }
129
- });
130
- it('dispatches Tab and Shift+Tab', async () => {
131
- const { grid, destroy } = await mountInteractive();
132
- try {
133
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab', bubbles: true }));
134
- await tick();
135
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab', shiftKey: true, bubbles: true }));
136
- await tick();
137
- expect(true).toBe(true);
138
- }
139
- finally {
140
- destroy();
141
- }
142
- });
143
- });
144
- describe('SvGrid interactions - global filter input', () => {
145
- it('typing in the global filter narrows the displayed rows', async () => {
146
- const { api, target, destroy } = await mountInteractive();
147
- try {
148
- const input = target.querySelector('.sv-grid-global-filter input');
149
- if (!input) {
150
- // global filter input wasn't rendered (jsdom quirk) - just verify api still works.
151
- expect(api.getData().length).toBe(rows.length);
152
- return;
153
- }
154
- input.value = 'Person 01';
155
- input.dispatchEvent(new Event('input', { bubbles: true }));
156
- await tick();
157
- await tick();
158
- // Some narrowing happened.
159
- expect(api.getDisplayedRows().length).toBeLessThanOrEqual(rows.length);
160
- }
161
- finally {
162
- destroy();
163
- }
164
- });
165
- });
166
- describe('SvGrid interactions - column resize', () => {
167
- it('starts a column resize via pointerdown on the handle', async () => {
168
- const { target, destroy } = await mountInteractive();
169
- try {
170
- const handle = target.querySelector('.sv-grid-resize-handle');
171
- if (!handle) {
172
- // jsdom may not lay out the handle; assertion skipped.
173
- return;
174
- }
175
- handle.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, pointerId: 1, button: 0 }));
176
- await tick();
177
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 200, clientY: 0 }));
178
- await tick();
179
- window.dispatchEvent(new PointerEvent('pointerup', { clientX: 200, clientY: 0 }));
180
- await tick();
181
- expect(true).toBe(true);
182
- }
183
- finally {
184
- destroy();
185
- }
186
- });
187
- });
188
- describe('SvGrid interactions - pagination nav', () => {
189
- it('clicking next/prev/last/first paginator buttons does not throw', async () => {
190
- const { target, destroy } = await mountInteractive();
191
- try {
192
- const buttons = target.querySelectorAll('.sv-grid-pagination-btn');
193
- for (const btn of Array.from(buttons)) {
194
- ;
195
- btn.click();
196
- await tick();
197
- }
198
- expect(true).toBe(true);
199
- }
200
- finally {
201
- destroy();
202
- }
203
- });
204
- });
205
- describe('SvGrid interactions - sort header click', () => {
206
- it('clicking a column header toggles the sort indicator', async () => {
207
- const { api, target, destroy } = await mountInteractive();
208
- try {
209
- const headerEl = target.querySelector('[data-svgrid-header-col]');
210
- if (!headerEl)
211
- return;
212
- headerEl.click();
213
- await tick();
214
- headerEl.click();
215
- await tick();
216
- headerEl.click();
217
- await tick();
218
- // No throw means we exercised onHeaderSortClick.
219
- expect(api.getData().length).toBe(rows.length);
220
- }
221
- finally {
222
- destroy();
223
- }
224
- });
225
- it('shift-click on a header adds a secondary sort clause', async () => {
226
- const { target, destroy } = await mountInteractive();
227
- try {
228
- const headers = target.querySelectorAll('[data-svgrid-header-col]');
229
- if (headers.length < 2)
230
- return;
231
- headers[0].click();
232
- await tick();
233
- headers[1].dispatchEvent(new MouseEvent('click', { bubbles: true, shiftKey: true }));
234
- await tick();
235
- expect(true).toBe(true);
236
- }
237
- finally {
238
- destroy();
239
- }
240
- });
241
- });
242
- describe('SvGrid interactions - cell pointer events', () => {
243
- it('pointerdown on a cell starts a selection', async () => {
244
- const { target, destroy } = await mountInteractive();
245
- try {
246
- const cell = target.querySelector('.sv-grid-cell');
247
- if (!cell)
248
- return;
249
- cell.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, pointerId: 1, button: 0 }));
250
- await tick();
251
- cell.dispatchEvent(new PointerEvent('pointerup', { bubbles: true, pointerId: 1 }));
252
- await tick();
253
- expect(true).toBe(true);
254
- }
255
- finally {
256
- destroy();
257
- }
258
- });
259
- it('double-click on an editable cell enters edit mode', async () => {
260
- const { target, destroy } = await mountInteractive();
261
- try {
262
- const cell = target.querySelector('.sv-grid-cell');
263
- if (!cell)
264
- return;
265
- cell.dispatchEvent(new MouseEvent('dblclick', { bubbles: true }));
266
- await tick();
267
- // Editor input may or may not be in DOM depending on layout; just
268
- // exercising the codepath is enough.
269
- expect(true).toBe(true);
270
- }
271
- finally {
272
- destroy();
273
- }
274
- });
275
- // issue #23: a mouse drag extends the cell range, but a touch drag must NOT -
276
- // it should leave the single tapped cell selected so the finger-drag scrolls.
277
- async function dragSelectCount(pointerType) {
278
- const { target, destroy } = await mountInteractive();
279
- try {
280
- const a = target.querySelector('[data-svgrid-row="0"][data-svgrid-col="0"]');
281
- const c = target.querySelector('[data-svgrid-row="0"][data-svgrid-col="2"]');
282
- if (!a || !c)
283
- return -1; // jsdom didn't lay the cells out; caller skips
284
- a.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, pointerId: 1, button: 0, pointerType }));
285
- await tick();
286
- c.dispatchEvent(new PointerEvent('pointerenter', { bubbles: true, pointerId: 1, pointerType }));
287
- await tick();
288
- return target.querySelectorAll('[data-selected-range="true"]').length;
289
- }
290
- finally {
291
- destroy();
292
- }
293
- }
294
- it('mouse drag extends the selection across cells', async () => {
295
- const n = await dragSelectCount('mouse');
296
- if (n < 0)
297
- return;
298
- expect(n).toBeGreaterThan(1); // (0,0) -> (0,2) selects the row's 3 cells
299
- });
300
- it('touch drag does not start a range selection (issue #23)', async () => {
301
- const n = await dragSelectCount('touch');
302
- if (n < 0)
303
- return;
304
- expect(n).toBeLessThanOrEqual(1); // only the tapped cell; finger-drag scrolls
305
- });
306
- });
307
- describe('SvGrid interactions - copy', () => {
308
- it('Ctrl+C with a cell range does not throw', async () => {
309
- const { grid, destroy } = await mountInteractive();
310
- try {
311
- const cev = new KeyboardEvent('keydown', { key: 'c', ctrlKey: true, bubbles: true });
312
- grid.dispatchEvent(cev);
313
- await tick();
314
- expect(true).toBe(true);
315
- }
316
- finally {
317
- destroy();
318
- }
319
- });
320
- });
321
- describe('SvGrid interactions - selection mode', () => {
322
- it('selecting a row via the API surfaces via getDisplayedRows', async () => {
323
- const { api, destroy } = await mountInteractive();
324
- try {
325
- // Simulate clicking the first row checkbox via the API.
326
- expect(api.getDisplayedRows().length).toBeGreaterThan(0);
327
- }
328
- finally {
329
- destroy();
330
- }
331
- });
332
- });
333
- describe('SvGrid interactions - clearAllFilters round-trip', () => {
334
- it('setting + clearing global + column filters returns to full set', async () => {
335
- const { api, destroy } = await mountInteractive();
336
- try {
337
- api.setFilter('name', { operator: 'contains', value: 'XYZ-NONE' });
338
- await tick();
339
- expect(api.getDisplayedRows().length).toBeLessThanOrEqual(rows.length);
340
- api.clearAllFilters();
341
- await tick();
342
- await tick();
343
- expect(api.getDisplayedRows().length).toBeGreaterThanOrEqual(1);
344
- }
345
- finally {
346
- destroy();
347
- }
348
- });
349
- });
@@ -1,15 +0,0 @@
1
- /**
2
- * Integration tests for the `filterLocale` prop. Mounts a real
3
- * <SvGrid> with accented data, drives the column-menu filter via
4
- * `api.setFilter()`, then asserts the visible row count via
5
- * `api.getDisplayedRows()`.
6
- *
7
- * Covers:
8
- * - Accent-insensitive `contains` operator on the menu filter
9
- * - Diacritic-stripped global filter (via `setGlobalFilter` not in
10
- * the public api yet; here we use `api.setFilter('city', ...)`
11
- * which exercises the same pipeline)
12
- * - filterLocale prop pass-through (es-ES, de-DE)
13
- * - Regression: ASCII queries still narrow rows
14
- */
15
- export {};
@@ -1,261 +0,0 @@
1
- /**
2
- * Integration tests for the `filterLocale` prop. Mounts a real
3
- * <SvGrid> with accented data, drives the column-menu filter via
4
- * `api.setFilter()`, then asserts the visible row count via
5
- * `api.getDisplayedRows()`.
6
- *
7
- * Covers:
8
- * - Accent-insensitive `contains` operator on the menu filter
9
- * - Diacritic-stripped global filter (via `setGlobalFilter` not in
10
- * the public api yet; here we use `api.setFilter('city', ...)`
11
- * which exercises the same pipeline)
12
- * - filterLocale prop pass-through (es-ES, de-DE)
13
- * - Regression: ASCII queries still narrow rows
14
- */
15
- import { describe, expect, it } from 'vitest';
16
- import { mount, unmount } from 'svelte';
17
- import SvGrid from './SvGrid.svelte';
18
- import { columnFilteringFeature, createCoreRowModel, createFilteredRowModel, createSortedRowModel, rowSortingFeature, sortFns, tableFeatures, } from './index';
19
- const features = tableFeatures({ columnFilteringFeature, rowSortingFeature });
20
- const rows = [
21
- { id: 1, city: 'München', country: 'Deutschland', region: 'Europe', population: 1510000 },
22
- { id: 2, city: 'Köln', country: 'Deutschland', region: 'Europe', population: 1080000 },
23
- { id: 3, city: 'Genève', country: 'Suisse', region: 'Europe', population: 203000 },
24
- { id: 4, city: 'Montréal', country: 'Canada', region: 'Americas', population: 1780000 },
25
- { id: 5, city: 'México', country: 'México', region: 'Americas', population: 9210000 },
26
- { id: 6, city: 'São Paulo', country: 'Brasil', region: 'Americas', population: 12330000 },
27
- { id: 7, city: 'Tōkyō', country: '日本', region: 'Asia', population: 13960000 },
28
- { id: 8, city: 'İstanbul', country: 'Türkiye', region: 'Asia', population: 15840000 },
29
- { id: 9, city: 'Málaga', country: 'España', region: 'Europe', population: 580000 },
30
- { id: 10, city: 'Berlin', country: 'Deutschland', region: 'Europe', population: 3770000 },
31
- ];
32
- const cols = [
33
- { field: 'city', header: 'City', width: 180, editable: false },
34
- { field: 'country', header: 'Country', width: 160, editable: false },
35
- { field: 'region', header: 'Region', width: 110, editable: false },
36
- { field: 'population', header: 'Population', width: 130, editable: false, align: 'right' },
37
- ];
38
- function mountGrid(opts = {}) {
39
- return new Promise((res, rej) => {
40
- const target = document.createElement('div');
41
- document.body.appendChild(target);
42
- let api = null;
43
- const app = mount(SvGrid, {
44
- target,
45
- props: {
46
- data: rows,
47
- columns: cols,
48
- features,
49
- _rowModels: {
50
- coreRowModel: createCoreRowModel(),
51
- filteredRowModel: createFilteredRowModel(),
52
- sortedRowModel: createSortedRowModel(sortFns),
53
- },
54
- containerHeight: 360,
55
- virtualization: false,
56
- columnVirtualization: false,
57
- showPagination: false,
58
- showColumnFilters: false,
59
- showGlobalFilter: false,
60
- showRowSelection: false,
61
- filterLocale: opts.filterLocale,
62
- onApiReady(received) {
63
- api = received;
64
- res({
65
- api,
66
- destroy: () => { unmount(app); target.remove(); },
67
- });
68
- },
69
- },
70
- });
71
- queueMicrotask(() => { if (!api)
72
- rej(new Error('onApiReady never fired')); });
73
- });
74
- }
75
- const tick = () => new Promise((r) => queueMicrotask(r));
76
- describe('SvGrid filter - default locale (no prop)', () => {
77
- it('"munch" matches "München" via contains operator', async () => {
78
- const { api, destroy } = await mountGrid();
79
- try {
80
- api.setFilter('city', { operator: 'contains', value: 'munch' });
81
- await tick();
82
- const visible = api.getDisplayedRows();
83
- expect(visible.map((r) => r.city)).toEqual(['München']);
84
- }
85
- finally {
86
- destroy();
87
- }
88
- });
89
- it('"geneve" matches "Genève"', async () => {
90
- const { api, destroy } = await mountGrid();
91
- try {
92
- api.setFilter('city', { operator: 'contains', value: 'geneve' });
93
- await tick();
94
- const visible = api.getDisplayedRows();
95
- expect(visible.map((r) => r.city)).toEqual(['Genève']);
96
- }
97
- finally {
98
- destroy();
99
- }
100
- });
101
- it('"sao paulo" matches "São Paulo"', async () => {
102
- const { api, destroy } = await mountGrid();
103
- try {
104
- api.setFilter('city', { operator: 'contains', value: 'sao paulo' });
105
- await tick();
106
- const visible = api.getDisplayedRows();
107
- expect(visible.map((r) => r.city)).toEqual(['São Paulo']);
108
- }
109
- finally {
110
- destroy();
111
- }
112
- });
113
- it('"tokyo" matches "Tōkyō"', async () => {
114
- const { api, destroy } = await mountGrid();
115
- try {
116
- api.setFilter('city', { operator: 'contains', value: 'tokyo' });
117
- await tick();
118
- const visible = api.getDisplayedRows();
119
- expect(visible.map((r) => r.city)).toEqual(['Tōkyō']);
120
- }
121
- finally {
122
- destroy();
123
- }
124
- });
125
- it('"istanbul" matches "İstanbul" (dotted-I default folding)', async () => {
126
- const { api, destroy } = await mountGrid();
127
- try {
128
- api.setFilter('city', { operator: 'contains', value: 'istanbul' });
129
- await tick();
130
- const visible = api.getDisplayedRows();
131
- expect(visible.map((r) => r.city)).toEqual(['İstanbul']);
132
- }
133
- finally {
134
- destroy();
135
- }
136
- });
137
- it('"deutschland" matches all German cities', async () => {
138
- const { api, destroy } = await mountGrid();
139
- try {
140
- api.setFilter('country', { operator: 'contains', value: 'deutschland' });
141
- await tick();
142
- const visible = api.getDisplayedRows();
143
- expect(visible.map((r) => r.city).sort()).toEqual(['Berlin', 'Köln', 'München']);
144
- }
145
- finally {
146
- destroy();
147
- }
148
- });
149
- });
150
- describe('SvGrid filter - filterLocale="de-DE"', () => {
151
- it('explicit German locale - "munchen" still matches "München"', async () => {
152
- const { api, destroy } = await mountGrid({ filterLocale: 'de-DE' });
153
- try {
154
- api.setFilter('city', { operator: 'contains', value: 'munchen' });
155
- await tick();
156
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['München']);
157
- }
158
- finally {
159
- destroy();
160
- }
161
- });
162
- it('"koln" matches "Köln"', async () => {
163
- const { api, destroy } = await mountGrid({ filterLocale: 'de-DE' });
164
- try {
165
- api.setFilter('city', { operator: 'contains', value: 'koln' });
166
- await tick();
167
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['Köln']);
168
- }
169
- finally {
170
- destroy();
171
- }
172
- });
173
- });
174
- describe('SvGrid filter - filterLocale="es-ES"', () => {
175
- it('"mexico" matches "México"', async () => {
176
- const { api, destroy } = await mountGrid({ filterLocale: 'es-ES' });
177
- try {
178
- api.setFilter('city', { operator: 'contains', value: 'mexico' });
179
- await tick();
180
- const cities = api.getDisplayedRows().map((r) => r.city);
181
- expect(cities).toContain('México');
182
- }
183
- finally {
184
- destroy();
185
- }
186
- });
187
- it('"malaga" matches "Málaga"', async () => {
188
- const { api, destroy } = await mountGrid({ filterLocale: 'es-ES' });
189
- try {
190
- api.setFilter('city', { operator: 'contains', value: 'malaga' });
191
- await tick();
192
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['Málaga']);
193
- }
194
- finally {
195
- destroy();
196
- }
197
- });
198
- });
199
- describe('SvGrid filter - startsWith + equals operators', () => {
200
- it('startsWith "mun" matches München', async () => {
201
- const { api, destroy } = await mountGrid();
202
- try {
203
- api.setFilter('city', { operator: 'startsWith', value: 'mun' });
204
- await tick();
205
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['München']);
206
- }
207
- finally {
208
- destroy();
209
- }
210
- });
211
- it('equals "berlin" matches exactly "Berlin" (case-insensitive)', async () => {
212
- const { api, destroy } = await mountGrid();
213
- try {
214
- api.setFilter('city', { operator: 'equals', value: 'berlin' });
215
- await tick();
216
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['Berlin']);
217
- }
218
- finally {
219
- destroy();
220
- }
221
- });
222
- it('equals "kolN" matches "Köln" (case + accent insensitive)', async () => {
223
- const { api, destroy } = await mountGrid();
224
- try {
225
- api.setFilter('city', { operator: 'equals', value: 'kolN' });
226
- await tick();
227
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['Köln']);
228
- }
229
- finally {
230
- destroy();
231
- }
232
- });
233
- });
234
- describe('SvGrid filter - clear + compose', () => {
235
- it('clearFilter removes the narrowing', async () => {
236
- const { api, destroy } = await mountGrid();
237
- try {
238
- api.setFilter('city', { operator: 'contains', value: 'munch' });
239
- await tick();
240
- expect(api.getDisplayedRows().length).toBe(1);
241
- api.clearFilter('city');
242
- await tick();
243
- expect(api.getDisplayedRows().length).toBe(rows.length);
244
- }
245
- finally {
246
- destroy();
247
- }
248
- });
249
- it('two column filters compose (AND across columns)', async () => {
250
- const { api, destroy } = await mountGrid();
251
- try {
252
- api.setFilter('country', { operator: 'contains', value: 'deutschland' });
253
- api.setFilter('city', { operator: 'contains', value: 'mun' });
254
- await tick();
255
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['München']);
256
- }
257
- finally {
258
- destroy();
259
- }
260
- });
261
- });
@@ -1 +0,0 @@
1
- export {};