import { render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, test } from 'vitest'
import { WidgetNoData } from './no-data'
import { useWidgetStore } from '../stores/widget-store'
describe('WidgetNoData', () => {
const widgetId = 'test-no-data-widget'
beforeEach(() => {
useWidgetStore.getState().clearWidgets()
})
describe('when sourceData is empty', () => {
test('renders NoData UI with empty array', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [],
})
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(
screen.getByText(/There are no results for the combination of filters/),
).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
test('renders NoData UI with null sourceData', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: null,
})
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
test('renders NoData UI with undefined sourceData', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: undefined,
})
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
test('renders NoData UI with array of empty arrays (CategoryWidget pattern)', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [[], []],
})
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
test('renders NoData UI with empty object', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: {},
})
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
})
describe('when sourceData exists', () => {
test('renders children with array sourceData', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [{ value: 1 }],
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders children with object sourceData', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: { content: 'Hello' },
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders children with nested array sourceData', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [[{ name: 'A', value: 1 }]],
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders children with primitive sourceData (number)', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: 0,
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders children with primitive sourceData (string)', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: 'test',
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders children with primitive sourceData (boolean)', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: false,
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
})
describe('when loading or fetching', () => {
test('renders children when isLoading=true even if sourceData is empty', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: true,
isFetching: false,
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders children when isFetching=true even if sourceData is empty', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: true,
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders children when both isLoading and isFetching are true', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: true,
isFetching: true,
})
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
})
describe('customization', () => {
test('renders custom title', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [],
})
render(
Widget Content
,
)
expect(screen.getByText('No results found')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders custom description', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [],
})
render(
Widget Content
,
)
expect(screen.getByText('Try adjusting your filters')).toBeTruthy()
expect(
screen.queryByText(/There are no results for the combination/),
).toBeNull()
})
test('uses custom isEmpty function', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: { customField: 'value' },
})
// Custom isEmpty that treats this sourceData as empty
const customIsEmpty = (data: unknown) => {
const d = data as { customField: string }
return d?.customField === 'value'
}
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
test('custom isEmpty returning false renders children', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [],
})
// Custom isEmpty that treats empty array as having data
const customIsEmpty = () => false
render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
})
describe('when widget does not exist in store', () => {
test('treats as empty and shows NoData UI', () => {
// Widget not initialized in store
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
})
describe('sourceData vs pipeline-transformed data', () => {
test('renders children when sourceData has data but pipeline data is empty', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [{ value: 1 }, { value: 2 }],
data: [], // pipeline filtered everything out
})
render(
Widget Content
,
)
// Should show children because sourceData is not empty
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('renders NoData when both sourceData and data are empty', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [],
})
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
test('renders NoData when sourceData is null (API returned nothing)', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: null,
})
render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
})
describe('reactivity to store changes', () => {
test('updates from NoData to content when sourceData arrives', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
})
const { rerender } = render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
// Update with sourceData
useWidgetStore.getState().setWidget(widgetId, {
sourceData: [{ value: 1 }],
})
// Force rerender to pick up store changes
rerender(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
test('updates from content to NoData when sourceData becomes empty', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
sourceData: [{ value: 1 }],
})
const { rerender } = render(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
// Clear sourceData
useWidgetStore.getState().setWidget(widgetId, { sourceData: [] })
// Force rerender to pick up store changes
rerender(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
expect(screen.queryByText('Widget Content')).toBeNull()
})
test('updates from NoData to content when loading starts', () => {
useWidgetStore.getState().setWidget(widgetId, {
isLoading: false,
isFetching: false,
})
const { rerender } = render(
Widget Content
,
)
expect(screen.getByText('No data available')).toBeTruthy()
// Start loading
useWidgetStore.getState().setWidget(widgetId, { isLoading: true })
// Force rerender to pick up store changes
rerender(
Widget Content
,
)
expect(screen.getByText('Widget Content')).toBeTruthy()
expect(screen.queryByText('No data available')).toBeNull()
})
})
})