import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { vi } from 'vitest'
import { FileItem, TFileItemList, TFileTransfer } from './types'
import { PktFileUpload } from './FileUpload'
// Polyfill for ResizeObserver
if (!global.ResizeObserver) {
class ResizeObserverPolyfill {
observe() {}
unobserve() {}
disconnect() {}
}
global.ResizeObserver = ResizeObserverPolyfill as any
}
const NOOP = () => {}
const createMockFile = (name: string, type = 'text/plain'): File => new File(['content'], name, { type })
const createFileItem = (name: string, fileId?: string) => new FileItem(createMockFile(name), fileId)
const expectVisibleFilename = (filename: string) => {
// Truncate renders a hidden measuring element with the same text.
// We assert against the visible "first" part to avoid duplicate matches.
expect(
screen.getByText(
(content, element) =>
content === filename && element?.getAttribute('data-pkt-truncate-part') === 'first',
),
).toBeInTheDocument()
}
describe('QueueDisplay', () => {
describe('Progress states', () => {
it.each([
{
state: 'queued',
progress: 'queued' as TFileTransfer['progress'],
filename: 'queued-file.pdf',
description: 'when no transfer exists',
},
{
state: 'done',
progress: 'done' as TFileTransfer['progress'],
filename: 'completed-file.pdf',
description: 'after successful upload',
},
{
state: 'error',
progress: 'error' as TFileTransfer['progress'],
filename: 'failed-file.pdf',
description: 'after failed upload',
},
{
state: 'canceled',
progress: 'canceled' as TFileTransfer['progress'],
filename: 'canceled-file.pdf',
description: 'when canceled',
},
// { state: 'in-progress', progress: 10 as FileTransfer['progress'], filename: 'in-progress-file.pdf', description: 'when canceled' },
])('should display file with $state state $description', ({ progress, filename, state }) => {
const initialValue: TFileItemList = [createFileItem(filename, 'file-1')]
const transfers = progress !== undefined ? [{ fileId: 'file-1', progress }] : []
const { container } = render(
,
)
// File should be displayed
expectVisibleFilename(filename)
// Should have proper class when not in progress
const queueItem = container.querySelector('.pkt-fileupload__queue-display__item')
expect(queueItem).toHaveClass('pkt-fileupload__queue-display__item--' + state)
expect(queueItem).not.toHaveClass('pkt-fileupload__queue-display__item--in-progress')
// Should not show progress bar or cancel button
expect(container.querySelector('.pkt-fileupload__queue-display__item__progress')).not.toBeInTheDocument()
expect(screen.queryByText('Avbryt')).not.toBeInTheDocument()
})
it('should display file with in-progress state and progress bar', () => {
const initialValue: TFileItemList = [createFileItem('uploading-file.pdf', 'file-1')]
const { container } = render(
,
)
// File should be displayed
expectVisibleFilename('uploading-file.pdf')
// Should have the 'in-progress' class
const queueItem = container.querySelector('.pkt-fileupload__queue-display__item')
expect(queueItem).toHaveClass('pkt-fileupload__queue-display__item--in-progress')
expect(queueItem).not.toHaveClass('pkt-fileupload__queue-display__item--done')
// Should show progress bar
expect(container.querySelector('.pkt-fileupload__queue-display__item__progress')).toBeInTheDocument()
// Should show percentage
expect(screen.getByText('45%')).toBeInTheDocument()
// Should show cancel button
expect(screen.getByText('Avbryt')).toBeInTheDocument()
})
it('should display multiple files with different progress states', () => {
const initialValue: TFileItemList = [
createFileItem('queued-file.pdf', 'file-1'),
createFileItem('uploading-file.pdf', 'file-2'),
createFileItem('completed-file.pdf', 'file-3'),
createFileItem('failed-file.pdf', 'file-4'),
]
const { container } = render(
,
)
// All files should be displayed
expectVisibleFilename('queued-file.pdf')
expectVisibleFilename('uploading-file.pdf')
expectVisibleFilename('completed-file.pdf')
expectVisibleFilename('failed-file.pdf')
// Should have 4 queue items
const queueItems = container.querySelectorAll('.pkt-fileupload__queue-display__item')
expect(queueItems).toHaveLength(4)
// Only the uploading file should have in-progress class
const inProgressItems = container.querySelectorAll('.pkt-fileupload__queue-display__item--in-progress')
expect(inProgressItems).toHaveLength(1)
// Only the uploading file should show progress bar and percentage
expect(screen.getByText('75%')).toBeInTheDocument()
expect(container.querySelectorAll('.pkt-fileupload__queue-display__item__progress')).toHaveLength(1)
})
it('should update progress percentage when transfer progresses', () => {
const initialValue: TFileItemList = [createFileItem('uploading-file.pdf', 'file-1')]
const { container, rerender } = render(
,
)
// Initially at 25%
expect(screen.getByText('25%')).toBeInTheDocument()
// Update to 50%
rerender(
,
)
expect(screen.queryByText('25%')).not.toBeInTheDocument()
expect(screen.getByText('50%')).toBeInTheDocument()
// Update to done
rerender(
,
)
// Progress percentage should no longer be visible
expect(screen.queryByText('50%')).not.toBeInTheDocument()
expect(container.querySelector('.pkt-fileupload__queue-display__item__progress')).not.toBeInTheDocument()
})
})
})