Grid.utils.test.ts166 lines · main
1import { copyToClipboard } from 'ui'
2import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
3
4import {
5 formatFilterURLParams,
6 formatSortURLParams,
7 handleCellKeyDown,
8} from '@/components/grid/BrivenGrid.utils'
9
10const { toastError, toastSuccess } = vi.hoisted(() => ({
11 toastError: vi.fn(),
12 toastSuccess: vi.fn(),
13}))
14
15vi.mock('sonner', () => ({
16 toast: {
17 error: toastError,
18 success: toastSuccess,
19 },
20}))
21
22// Sort URL syntax: `column:order`
23describe('BrivenGrid.utils: formatSortURLParams', () => {
24 test('should return an array of sort options based on URL params', () => {
25 const mockInput = ['id:asc', 'name:desc']
26 const output = formatSortURLParams('fakeTable', mockInput)
27 expect(output).toStrictEqual([
28 { table: 'fakeTable', column: 'id', ascending: true },
29 { table: 'fakeTable', column: 'name', ascending: false },
30 ])
31 })
32 test('should reject any malformed sort options based on URL params', () => {
33 const mockInput = ['id', 'name:asc', ':asc']
34 const output = formatSortURLParams('fakeTable', mockInput)
35 expect(output).toStrictEqual([
36 {
37 table: 'fakeTable',
38 column: 'name',
39 ascending: true,
40 },
41 ])
42 })
43})
44
45// Filter URL syntax: `column:operatorAbbreviation:value`
46describe('BrivenGrid.utils: formatFilterURLParams', () => {
47 test('should return an array of filter options based on URL params', () => {
48 const mockInput = ['id:gte:20', 'id:lte:40']
49 const output = formatFilterURLParams(mockInput)
50 expect(output).toHaveLength(2)
51 expect(output[0]).toStrictEqual({
52 column: 'id',
53 operator: '>=',
54 value: '20',
55 })
56 expect(output[1]).toStrictEqual({
57 column: 'id',
58 operator: '<=',
59 value: '40',
60 })
61 })
62 test('should format filters for timestamps correctly', () => {
63 const mockInput = ['created_at:gte:2022-05-30 03:00:00']
64 const output = formatFilterURLParams(mockInput)
65 expect(output[0]).toStrictEqual({
66 column: 'created_at',
67 operator: '>=',
68 value: '2022-05-30 03:00:00',
69 })
70 })
71 test('should reject any malformed filter options based on URL params', () => {
72 const mockInput = ['id', ':gte', ':50', 'id:eq:10']
73 const output = formatFilterURLParams(mockInput)
74 expect(output).toHaveLength(1)
75 })
76 test('should reject any filter options with unrecognized operator', () => {
77 const mockInput = ['id:meme:40', 'name:eq:town']
78 const output = formatFilterURLParams(mockInput)
79 expect(output).toHaveLength(1)
80 })
81 test('should allow filter options to have empty value based on URL params', () => {
82 const mockInput = ['id:ilike:']
83 const output = formatFilterURLParams(mockInput)
84 expect(output).toHaveLength(1)
85 expect(output[0]).toStrictEqual({
86 column: 'id',
87 operator: '~~*',
88 value: '',
89 })
90 })
91})
92
93describe('BrivenGrid.utils: handleCellKeyDown', () => {
94 beforeEach(() => {
95 toastError.mockReset()
96 toastSuccess.mockReset()
97 vi.unstubAllGlobals()
98 vi.spyOn(window.document, 'hasFocus').mockReturnValue(true)
99 })
100
101 afterEach(() => {
102 vi.unstubAllGlobals()
103 vi.restoreAllMocks()
104 })
105
106 test('should copy the selected cell value when Meta+C is pressed', async () => {
107 const writeText = vi.fn().mockResolvedValue(undefined)
108 vi.stubGlobal('navigator', {
109 clipboard: { writeText },
110 })
111
112 const args = {
113 mode: 'SELECT',
114 column: { key: 'name' },
115 row: { name: 'hello from safari' },
116 rowIdx: 0,
117 selectCell: vi.fn(),
118 } as unknown as Parameters<typeof handleCellKeyDown>[0]
119
120 const event = {
121 key: 'C',
122 metaKey: true,
123 ctrlKey: false,
124 altKey: false,
125 nativeEvent: new KeyboardEvent('keydown', { key: 'C', metaKey: true }),
126 preventDefault: vi.fn(),
127 preventGridDefault: vi.fn(),
128 } as unknown as Parameters<typeof handleCellKeyDown>[1]
129
130 handleCellKeyDown(args, event)
131
132 await vi.waitFor(() => {
133 expect(writeText).toHaveBeenCalledWith('hello from safari')
134 })
135 expect(event.preventDefault).toHaveBeenCalled()
136 expect(event.preventGridDefault).toHaveBeenCalled()
137 await vi.waitFor(() => {
138 expect(toastSuccess).toHaveBeenCalledWith('Copied cell value to clipboard')
139 })
140 })
141})
142
143describe('shared clipboard util', () => {
144 beforeEach(() => {
145 vi.unstubAllGlobals()
146 vi.spyOn(window.document, 'hasFocus').mockReturnValue(true)
147 })
148
149 afterEach(() => {
150 vi.unstubAllGlobals()
151 vi.restoreAllMocks()
152 })
153
154 test('should invoke the callback after writing text to the clipboard', async () => {
155 const writeText = vi.fn().mockResolvedValue(undefined)
156 const onCopy = vi.fn()
157
158 vi.stubGlobal('navigator', {
159 clipboard: { writeText },
160 })
161
162 await copyToClipboard('hello from safari', onCopy)
163 expect(writeText).toHaveBeenCalledWith('hello from safari')
164 expect(onCopy).toHaveBeenCalled()
165 })
166})