|
1 | 1 | import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' |
2 | | -import { fireEvent, render } from '@solidjs/testing-library' |
| 2 | +import { fireEvent, render, within } from '@solidjs/testing-library' |
3 | 3 | import { QueryClient, onlineManager } from '@tanstack/query-core' |
4 | 4 | import Explorer from '../Explorer' |
5 | 5 | import { QueryDevtoolsContext, ThemeContext } from '../contexts' |
@@ -232,6 +232,63 @@ describe('Explorer', () => { |
232 | 232 | ) |
233 | 233 | }) |
234 | 234 |
|
| 235 | + it('should reset the copy button to the idle state 1500ms after a successful copy', async () => { |
| 236 | + const writeText = vi.fn().mockResolvedValue(undefined) |
| 237 | + vi.stubGlobal('navigator', { clipboard: { writeText } }) |
| 238 | + queryClient.setQueryData(['data'], { name: 'Anna' }) |
| 239 | + |
| 240 | + const rendered = renderExplorer({ |
| 241 | + label: 'data', |
| 242 | + value: { name: 'Anna' }, |
| 243 | + editable: true, |
| 244 | + activeQuery: queryClient |
| 245 | + .getQueryCache() |
| 246 | + .find({ queryKey: ['data'] }) as Query, |
| 247 | + }) |
| 248 | + |
| 249 | + fireEvent.click(rendered.getByLabelText('Copy object to clipboard')) |
| 250 | + await vi.advanceTimersByTimeAsync(0) |
| 251 | + |
| 252 | + expect( |
| 253 | + rendered.getByLabelText('Object copied to clipboard'), |
| 254 | + ).toBeInTheDocument() |
| 255 | + |
| 256 | + await vi.advanceTimersByTimeAsync(1500) |
| 257 | + |
| 258 | + expect( |
| 259 | + rendered.getByLabelText('Copy object to clipboard'), |
| 260 | + ).toBeInTheDocument() |
| 261 | + }) |
| 262 | + |
| 263 | + it('should reset the copy button to the idle state 1500ms after a failed copy', async () => { |
| 264 | + const writeText = vi.fn().mockRejectedValue(new Error('denied')) |
| 265 | + vi.stubGlobal('navigator', { clipboard: { writeText } }) |
| 266 | + vi.spyOn(console, 'error').mockImplementation(() => {}) |
| 267 | + queryClient.setQueryData(['data'], { name: 'Anna' }) |
| 268 | + |
| 269 | + const rendered = renderExplorer({ |
| 270 | + label: 'data', |
| 271 | + value: { name: 'Anna' }, |
| 272 | + editable: true, |
| 273 | + activeQuery: queryClient |
| 274 | + .getQueryCache() |
| 275 | + .find({ queryKey: ['data'] }) as Query, |
| 276 | + }) |
| 277 | + |
| 278 | + fireEvent.click(rendered.getByLabelText('Copy object to clipboard')) |
| 279 | + await vi.advanceTimersByTimeAsync(0) |
| 280 | + |
| 281 | + expect( |
| 282 | + rendered.getByLabelText('Error copying object to clipboard'), |
| 283 | + ).toBeInTheDocument() |
| 284 | + |
| 285 | + await vi.advanceTimersByTimeAsync(1500) |
| 286 | + |
| 287 | + expect( |
| 288 | + rendered.getByLabelText('Copy object to clipboard'), |
| 289 | + ).toBeInTheDocument() |
| 290 | + }) |
| 291 | + |
235 | 292 | it('should clear array items via "setQueryData" when the clear-array button is clicked', () => { |
236 | 293 | queryClient.setQueryData(['data'], ['a', 'b', 'c']) |
237 | 294 |
|
@@ -357,6 +414,49 @@ describe('Explorer', () => { |
357 | 414 | expect(rendered.getByText('0:')).toBeInTheDocument() |
358 | 415 | expect(rendered.getByText('"item-0"')).toBeInTheDocument() |
359 | 416 | }) |
| 417 | + |
| 418 | + it('should independently toggle two pages when their headers are clicked', () => { |
| 419 | + const rendered = renderExplorer({ |
| 420 | + label: 'big', |
| 421 | + value: Array.from({ length: 200 }, (_, i) => `item-${i}`), |
| 422 | + }) |
| 423 | + |
| 424 | + fireEvent.click(rendered.getByRole('button', { expanded: false })) |
| 425 | + fireEvent.click(rendered.getByText('[0...99]')) |
| 426 | + fireEvent.click(rendered.getByText('[100...199]')) |
| 427 | + |
| 428 | + expect(rendered.getByText('"item-0"')).toBeInTheDocument() |
| 429 | + expect(rendered.getByText('"item-100"')).toBeInTheDocument() |
| 430 | + |
| 431 | + fireEvent.click(rendered.getByText('[0...99]')) |
| 432 | + |
| 433 | + expect(rendered.queryByText('"item-0"')).toBeNull() |
| 434 | + expect(rendered.getByText('"item-100"')).toBeInTheDocument() |
| 435 | + }) |
| 436 | + |
| 437 | + it('should render action buttons for items inside a paginated page', () => { |
| 438 | + const value: Array<Array<number>> = Array.from( |
| 439 | + { length: 200 }, |
| 440 | + (_, i) => [i], |
| 441 | + ) |
| 442 | + queryClient.setQueryData(['data'], value) |
| 443 | + |
| 444 | + const rendered = renderExplorer({ |
| 445 | + label: 'Data', |
| 446 | + value, |
| 447 | + defaultExpanded: ['Data'], |
| 448 | + editable: true, |
| 449 | + activeQuery: queryClient |
| 450 | + .getQueryCache() |
| 451 | + .find({ queryKey: ['data'] }) as Query, |
| 452 | + }) |
| 453 | + |
| 454 | + fireEvent.click(rendered.getByText('[0...99]')) |
| 455 | + |
| 456 | + expect( |
| 457 | + rendered.getAllByLabelText('Remove all items').length, |
| 458 | + ).toBeGreaterThan(1) |
| 459 | + }) |
360 | 460 | }) |
361 | 461 |
|
362 | 462 | describe('inline edit', () => { |
@@ -436,5 +536,30 @@ describe('Explorer', () => { |
436 | 536 |
|
437 | 537 | expect(rendered.getByLabelText('Delete item')).toBeInTheDocument() |
438 | 538 | }) |
| 539 | + |
| 540 | + it('should delete fields from the active query when their inline delete buttons are clicked', () => { |
| 541 | + const value = { name: 'Anna', age: 30 } |
| 542 | + queryClient.setQueryData(['data'], value) |
| 543 | + |
| 544 | + const rendered = renderExplorer({ |
| 545 | + label: 'Data', |
| 546 | + value, |
| 547 | + defaultExpanded: ['Data'], |
| 548 | + editable: true, |
| 549 | + activeQuery: queryClient |
| 550 | + .getQueryCache() |
| 551 | + .find({ queryKey: ['data'] }) as Query, |
| 552 | + }) |
| 553 | + |
| 554 | + const ageRow = rendered.getByText('age:').parentElement! |
| 555 | + fireEvent.click(within(ageRow).getByLabelText('Delete item')) |
| 556 | + |
| 557 | + expect(queryClient.getQueryData(['data'])).toEqual({ name: 'Anna' }) |
| 558 | + |
| 559 | + const nameRow = rendered.getByText('name:').parentElement! |
| 560 | + fireEvent.click(within(nameRow).getByLabelText('Delete item')) |
| 561 | + |
| 562 | + expect(queryClient.getQueryData(['data'])).toEqual({}) |
| 563 | + }) |
439 | 564 | }) |
440 | 565 | }) |
0 commit comments