Skip to content

Commit c99114e

Browse files
committed
feat(createDataGrid): add integration tests
1 parent dc3a339 commit c99114e

2 files changed

Lines changed: 173 additions & 1 deletion

File tree

packages/0/src/composables/createDataGrid/editing.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { createCellEditing } from './editing'
55
describe('createCellEditing', () => {
66
const columns = [
77
{ key: 'name', editable: true },
8-
{ key: 'email', editable: true, validate: (v: unknown) => typeof v === 'string' && v.includes('@') || 'Invalid email' },
8+
{ key: 'email', editable: true, validate: (v: unknown) => (typeof v === 'string' && v.includes('@')) || 'Invalid email' },
99
{ key: 'id', editable: false },
1010
]
1111

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import { describe, expect, it, vi } from 'vitest'
2+
3+
// Utilities
4+
import { inject, provide } from 'vue'
5+
6+
import { createDataGrid } from './index'
7+
8+
vi.mock('vue', async () => {
9+
const actual = await vi.importActual('vue')
10+
return {
11+
...actual,
12+
provide: vi.fn(),
13+
inject: vi.fn(),
14+
}
15+
})
16+
17+
vi.mocked(provide)
18+
vi.mocked(inject)
19+
20+
const items = [
21+
{ id: 1, name: 'Alice', email: 'alice@test.com', age: 30, dept: 'Eng' },
22+
{ id: 2, name: 'Bob', email: 'bob@test.com', age: 25, dept: 'Eng' },
23+
{ id: 3, name: 'Carol', email: 'carol@test.com', age: 35, dept: 'Sales' },
24+
{ id: 4, name: 'Dave', email: 'dave@test.com', age: 28, dept: 'Sales' },
25+
]
26+
27+
describe('createDataGrid', () => {
28+
it('creates a grid with data table pipeline', () => {
29+
const grid = createDataGrid({
30+
items,
31+
columns: [
32+
{ key: 'name', title: 'Name', sortable: true, filterable: true, size: 30 },
33+
{ key: 'email', title: 'Email', filterable: true, size: 40 },
34+
{ key: 'age', title: 'Age', sortable: true, size: 30 },
35+
],
36+
})
37+
38+
expect(grid.items.value).toHaveLength(4)
39+
expect(grid.layout.columns.value).toHaveLength(3)
40+
})
41+
42+
it('search filters items', () => {
43+
const grid = createDataGrid({
44+
items,
45+
columns: [
46+
{ key: 'name', filterable: true, size: 50 },
47+
{ key: 'email', filterable: true, size: 50 },
48+
],
49+
})
50+
51+
grid.search('alice')
52+
expect(grid.items.value).toHaveLength(1)
53+
expect(grid.items.value[0].name).toBe('Alice')
54+
})
55+
56+
it('sort works through the table pipeline', () => {
57+
const grid = createDataGrid({
58+
items,
59+
columns: [
60+
{ key: 'name', sortable: true, size: 50 },
61+
{ key: 'age', sortable: true, size: 50 },
62+
],
63+
})
64+
65+
grid.sort.toggle('age')
66+
expect(grid.items.value[0].name).toBe('Bob') // age 25
67+
expect(grid.items.value[3].name).toBe('Carol') // age 35
68+
})
69+
70+
describe('column layout', () => {
71+
it('initializes with correct sizes', () => {
72+
const grid = createDataGrid({
73+
items,
74+
columns: [
75+
{ key: 'name', size: 40 },
76+
{ key: 'email', size: 60 },
77+
],
78+
})
79+
80+
expect(grid.layout.columns.value[0].size).toBe(40)
81+
expect(grid.layout.columns.value[1].size).toBe(60)
82+
})
83+
84+
it('supports nested columns', () => {
85+
const grid = createDataGrid({
86+
items,
87+
columns: [
88+
{ key: 'name', title: 'Name', size: 30 },
89+
{
90+
key: 'contact',
91+
title: 'Contact',
92+
children: [
93+
{ key: 'email', title: 'Email', size: 40 },
94+
{ key: 'age', title: 'Age', size: 30 },
95+
],
96+
},
97+
],
98+
})
99+
100+
// Layout should have leaf columns only
101+
expect(grid.layout.columns.value).toHaveLength(3)
102+
103+
// Headers should be 2D
104+
expect(grid.headers.value).toHaveLength(2)
105+
expect(grid.headers.value[0][0].rowspan).toBe(2) // name spans 2 rows
106+
expect(grid.headers.value[0][1].colspan).toBe(2) // contact spans 2 cols
107+
})
108+
})
109+
110+
describe('cell editing', () => {
111+
it('edit and commit lifecycle', () => {
112+
const onEdit = vi.fn()
113+
const grid = createDataGrid({
114+
items,
115+
columns: [
116+
{ key: 'name', size: 50, editable: true },
117+
{ key: 'email', size: 50 },
118+
],
119+
editing: { onEdit },
120+
})
121+
122+
grid.editing.edit(1, 'name')
123+
expect(grid.editing.active.value).toEqual({ row: 1, column: 'name' })
124+
125+
grid.editing.commit('Alicia')
126+
expect(onEdit).toHaveBeenCalledWith(1, 'name', 'Alicia', items[0])
127+
expect(grid.editing.active.value).toBeNull()
128+
})
129+
130+
it('validation rejects bad values', () => {
131+
const grid = createDataGrid({
132+
items,
133+
columns: [
134+
{
135+
key: 'email',
136+
size: 100,
137+
editable: true,
138+
validate: v => (typeof v === 'string' && v.includes('@')) || 'Invalid email',
139+
},
140+
],
141+
editing: {},
142+
})
143+
144+
grid.editing.edit(1, 'email')
145+
grid.editing.commit('not-email')
146+
expect(grid.editing.error.value).toBe('Invalid email')
147+
expect(grid.editing.active.value).not.toBeNull()
148+
})
149+
})
150+
151+
describe('row spanning', () => {
152+
it('computes span map', () => {
153+
const grid = createDataGrid({
154+
items,
155+
columns: [
156+
{ key: 'dept', size: 50 },
157+
{ key: 'name', size: 50 },
158+
],
159+
rowSpanning: (item, column) => {
160+
if (column === 'dept' && (item.dept === 'Eng' || item.dept === 'Sales')) return 2
161+
return 1
162+
},
163+
})
164+
165+
const spans = grid.spans.value
166+
expect(spans.get(1)?.get('dept')?.rowSpan).toBe(2)
167+
expect(spans.get(2)?.get('dept')?.hidden).toBe(true)
168+
expect(spans.get(3)?.get('dept')?.rowSpan).toBe(2)
169+
expect(spans.get(4)?.get('dept')?.hidden).toBe(true)
170+
})
171+
})
172+
})

0 commit comments

Comments
 (0)