UNPKG

@v4fire/client

Version:

V4Fire client core library

335 lines (274 loc) • 8.61 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ /** * @file This file contains test cases that verify the correctness of the internal component state module. */ import test from 'tests/config/unit/test'; import type bVirtualScrollNew from 'base/b-virtual-scroll-new/b-virtual-scroll-new'; import { defaultShouldProps } from 'base/b-virtual-scroll-new/const'; import type { ComponentItem, ShouldPerform } from 'base/b-virtual-scroll-new/interface'; import { createTestHelpers } from 'base/b-virtual-scroll-new/test/api/helpers'; import type { VirtualScrollTestHelpers } from 'base/b-virtual-scroll-new/test/api/helpers/interface'; test.describe('<b-virtual-scroll-new>', () => { let component: VirtualScrollTestHelpers['component'], provider: VirtualScrollTestHelpers['provider'], state: VirtualScrollTestHelpers['state']; test.beforeEach(async ({demoPage, page}) => { await demoPage.goto(); ({component, provider, state} = await createTestHelpers(page)); await provider.start(); }); test('Initial state', async () => { const chunkSize = 12, mockFn = await component.mockFn((ctx: bVirtualScrollNew) => ctx.getVirtualScrollState()); provider.response(200, {data: []}, {delay: (10).seconds()}); const expectedState = state.compile({ lastLoadedRawData: undefined, remainingItems: undefined, remainingChildren: undefined, maxViewedItem: undefined, maxViewedChild: undefined, areRequestsStopped: false, isLoadingInProgress: true, lastLoadedData: [], loadPage: 0 }); await component .withDefaultPaginationProviderProps({chunkSize}) .withProps({ '@componentHook:created': mockFn }) .build(); await test.expect(mockFn.results).resolves.toEqual([{type: 'return', value: expectedState}]); }); test('State after loading first and second data chunks', async () => { const chunkSize = 12, providerChunkSize = chunkSize / 2; const shouldStopRequestingData = <ShouldPerform>(defaultShouldProps.shouldStopRequestingData), shouldPerformDataRender = <ShouldPerform>(({isInitialRender, remainingItems: remainingItems}) => isInitialRender || remainingItems === 0); await test.step('After rendering first data chunk', async () => { provider .responseOnce(200, {data: state.data.addData(providerChunkSize)}) .responseOnce(200, {data: state.data.addData(providerChunkSize)}); state.data.addItems(chunkSize); await component .withDefaultPaginationProviderProps({chunkSize: providerChunkSize}) .withProps({ chunkSize, shouldStopRequestingData, shouldPerformDataRender }) .build(); await component.waitForChildCountEqualsTo(chunkSize); const currentState = await component.getVirtualScrollState(); test.expect(currentState).toEqual(state.compile({ isInitialLoading: false, isInitialRender: false, areRequestsStopped: false, isLoadingInProgress: false, loadPage: 2, renderPage: 1 })); }); await test.step('After rendering second data chunk', async () => { provider .responseOnce(200, {data: state.data.addData(providerChunkSize)}) .responseOnce(200, {data: state.data.addData(providerChunkSize)}) .response(200, {data: state.data.addData(0)}); state.data.addItems(chunkSize); await component.scrollToBottom(); await component.waitForChildCountEqualsTo(chunkSize * 2); await component.scrollToBottom(); await component.waitForLifecycleDone(); const currentState = await component.getVirtualScrollState(); test.expect(currentState).toEqual(state.compile({ isInitialLoading: false, isInitialRender: false, areRequestsStopped: true, isLoadingInProgress: false, isLastEmpty: true, isLifecycleDone: true, isLastRender: true, loadPage: 5, renderPage: 2 })); }); }); test.describe('state after rendering via `itemsFactory`', () => { test('`itemsFactory` returns mixed items with `item` and `separator` type', async () => { const chunkSize = 12; const separator: ComponentItem = { item: 'b-button', key: Object.cast(undefined), children: ['ima button'], props: { id: 'button' }, type: 'separator' }; const item = (data): ComponentItem => ({ item: 'section', key: Object.cast(undefined), type: 'item', props: { 'data-index': data.i }, meta: { data } }); const compileItemsFn = (state, ctx, separator, item) => { const data = state.lastLoadedData, result: ComponentItem[] = []; data.forEach((data) => { result.push(separator, item(data)); }); return result; }; const itemsFactory = await component.mockFn(compileItemsFn, separator, item); provider .responseOnce(200, {data: state.data.addData(chunkSize)}) .response(200, {data: state.data.addData(0)}); state.data.addChild(compileItemsFn({lastLoadedData: state.data.data}, null, separator, item)); await component .withDefaultPaginationProviderProps({chunkSize}) .withProps({ itemsFactory, shouldPerformDataRender: () => true, chunkSize }) .build(); await component.waitForChildCountEqualsTo(chunkSize * 2); await component.waitForLifecycleDone(); const currentState = await component.getVirtualScrollState(); test.expect(currentState).toEqual(state.compile({ isInitialLoading: false, isInitialRender: false, areRequestsStopped: true, isLoadingInProgress: false, isLastEmpty: true, isLifecycleDone: true, isLastRender: true, loadPage: 2, renderPage: 1 })); }); test('`itemsFactory` returns items with `item` and last item with `separator` type', async () => { const chunkSize = 12; const separator: ComponentItem = { item: 'b-button', key: Object.cast(undefined), children: ['ima button'], props: { id: 'button' }, type: 'separator' }; const itemsFactory = await component.mockFn((state, ctx, separator) => { const data = state.lastLoadedData; const items = data.map((item) => ({ item: 'section', key: Object.cast(undefined), type: 'item', props: { 'data-index': item.i }, meta: { data: item } })); if (data.length > 0) { items.push(separator); } return items; }, separator); provider .responseOnce(200, {data: state.data.addData(chunkSize)}) .response(200, {data: state.data.addData(0)}); state.data.addItems(chunkSize); state.data.addChild([separator]); await component .withDefaultPaginationProviderProps({chunkSize}) .withProps({ itemsFactory, shouldPerformDataRender: () => true, chunkSize }) .build(); await component.waitForChildCountEqualsTo(chunkSize + 1); await component.waitForLifecycleDone(); const currentState = await component.getVirtualScrollState(); test.expect(currentState).toEqual(state.compile({ isInitialLoading: false, isInitialRender: false, areRequestsStopped: true, isLoadingInProgress: false, isLastEmpty: true, isLifecycleDone: true, isLastRender: true, loadPage: 2, renderPage: 1 })); }); test('`itemsFactory` does not returns items with `item` type', async () => { const chunkSize = 12; const itemsFactory = await component.mockFn((state) => { const data = state.lastLoadedData; const items = data.map((item) => ({ item: 'section', key: Object.cast(undefined), type: 'separator', props: { 'data-index': item.i } })); return items; }); provider .responseOnce(200, {data: state.data.addData(chunkSize)}) .response(200, {data: state.data.addData(0)}); state.data.addSeparators(chunkSize); await component .withDefaultPaginationProviderProps({chunkSize}) .withProps({ itemsFactory, shouldPerformDataRender: () => true, chunkSize }) .build(); await component.waitForChildCountEqualsTo(chunkSize); await component.waitForLifecycleDone(); const currentState = await component.getVirtualScrollState(); test.expect(currentState).toEqual(state.compile({ isInitialLoading: false, isInitialRender: false, areRequestsStopped: true, isLoadingInProgress: false, isLastEmpty: true, isLifecycleDone: true, isLastRender: true, maxViewedItem: undefined, loadPage: 2, renderPage: 1 })); }); }); });