diff --git a/examples/fill-width.tsx b/examples/fill-width.tsx index e433bf1..3f2db62 100644 --- a/examples/fill-width.tsx +++ b/examples/fill-width.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import useLayoutEffect from "@rc-component/util/lib/hooks/useLayoutEffect"; +import { useLayoutEffect } from '@rc-component/util'; import Overflow from '../src'; import '../assets/index.less'; import './common.less'; diff --git a/jest.config.js b/jest.config.js index 86627c3..5328c18 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,4 +1,3 @@ module.exports = { setupFiles: ['./tests/setup.js'], - snapshotSerializers: [require.resolve('enzyme-to-json/serializer')], }; diff --git a/package.json b/package.json index fea8493..32bc953 100644 --- a/package.json +++ b/package.json @@ -46,37 +46,33 @@ "dependencies": { "@babel/runtime": "^7.11.1", "@rc-component/resize-observer": "^1.0.1", - "@rc-component/util": "^1.4.0", + "@rc-component/util": "^1.11.1", "clsx": "^2.1.1" }, "devDependencies": { - "@rc-component/father-plugin": "^2.0.0", + "@rc-component/father-plugin": "^2.2.0", "@rc-component/np": "^1.0.4", "@testing-library/jest-dom": "^5.16.4", - "@testing-library/react": "^12.0.0", - "@types/enzyme": "^3.10.8", + "@testing-library/react": "^16.3.0", "@types/jest": "^26.0.23", "@types/node": "^24.8.1", - "@types/react": "^16.14.2", - "@types/react-dom": "^16.9.10", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "@typescript-eslint/eslint-plugin": "^5.59.0", "@typescript-eslint/parser": "^5.59.0", "@umijs/fabric": "^3.0.0", "dumi": "^2.0.0", - "enzyme": "^3.0.0", - "enzyme-adapter-react-16": "^1.0.1", - "enzyme-to-json": "^3.4.0", "eslint": "^8.57.0", "eslint-plugin-jest": "^27.5.1", "eslint-plugin-unicorn": "^51.0.1", - "father": "^4.0.0", + "father": "^4.6.19", "glob": "^10.0.0", "less": "^3.10.3", "np": "^7.0.0", "prettier": "^2.0.5", "rc-test": "^7.0", - "react": "^16.0.0", - "react-dom": "^16.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0", "regenerator-runtime": "^0.13.7", "typescript": "~5.3.3" }, @@ -84,9 +80,6 @@ "react": ">=16.9.0", "react-dom": ">=16.9.0" }, - "overrides": { - "cheerio": "1.0.0-rc.12" - }, "cnpm": { "mode": "npm" }, diff --git a/src/Overflow.tsx b/src/Overflow.tsx index e4e4bf0..1b73cf9 100644 --- a/src/Overflow.tsx +++ b/src/Overflow.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { useState, useMemo, useCallback } from 'react'; import { clsx } from 'clsx'; import ResizeObserver from '@rc-component/resize-observer'; -import useLayoutEffect from '@rc-component/util/lib/hooks/useLayoutEffect'; +import { useLayoutEffect } from '@rc-component/util'; import Item from './Item'; import useEffectState, { useBatcher } from './hooks/useEffectState'; import type { ComponentType } from './RawItem'; @@ -169,13 +169,14 @@ function Overflow( if (typeof itemKey === 'function') { return itemKey(item); } - return (itemKey && (item as any)?.[itemKey]) ?? index; + return (itemKey && (item as any)?.[itemKey as keyof any]) ?? index; }, [itemKey], ); const mergedRenderItem = useCallback( - renderItem || ((item: ItemType) => item), + (item: ItemType, info: { index: number }) => + renderItem ? renderItem(item, info) : (item as React.ReactNode), [renderItem], ); @@ -461,13 +462,13 @@ type FilledOverflowType = ForwardOverflowType & { INVALIDATE: typeof INVALIDATE; }; -(ForwardOverflow as unknown as FilledOverflowType).Item = RawItem; -(ForwardOverflow as unknown as FilledOverflowType).RESPONSIVE = RESPONSIVE; -(ForwardOverflow as unknown as FilledOverflowType).INVALIDATE = INVALIDATE; +((ForwardOverflow as unknown) as FilledOverflowType).Item = RawItem; +((ForwardOverflow as unknown) as FilledOverflowType).RESPONSIVE = RESPONSIVE; +((ForwardOverflow as unknown) as FilledOverflowType).INVALIDATE = INVALIDATE; if (process.env.NODE_ENV !== 'production') { ForwardOverflow.displayName = 'Overflow'; } // Convert to generic type -export default ForwardOverflow as unknown as FilledOverflowType; +export default (ForwardOverflow as unknown) as FilledOverflowType; diff --git a/src/hooks/channelUpdate.ts b/src/hooks/channelUpdate.ts index 4422798..eabd6b1 100644 --- a/src/hooks/channelUpdate.ts +++ b/src/hooks/channelUpdate.ts @@ -1,4 +1,4 @@ -import raf from '@rc-component/util/lib/raf'; +import { raf } from '@rc-component/util'; export default function channelUpdate(callback: VoidFunction) { if (typeof MessageChannel === 'undefined') { diff --git a/src/hooks/useEffectState.tsx b/src/hooks/useEffectState.tsx index 1d4dd97..75d47bc 100644 --- a/src/hooks/useEffectState.tsx +++ b/src/hooks/useEffectState.tsx @@ -1,4 +1,4 @@ -import useEvent from '@rc-component/util/lib/hooks/useEvent'; +import { useEvent } from '@rc-component/util'; import * as React from 'react'; import { unstable_batchedUpdates } from 'react-dom'; import channelUpdate from './channelUpdate'; diff --git a/tests/github.spec.tsx b/tests/github.spec.tsx index c709b2b..c48ba1f 100644 --- a/tests/github.spec.tsx +++ b/tests/github.spec.tsx @@ -1,9 +1,11 @@ +import './setup'; import React from 'react'; +import '@testing-library/jest-dom'; import { render, act } from '@testing-library/react'; -import { spyElementPrototypes } from '@rc-component/util/lib/test/domHook'; +import { spyElementPrototypes } from '@rc-component/util'; import Overflow from '../src'; -import { _rs as onResize } from '@rc-component/resize-observer/lib/utils/observerUtil'; +import { _rs as onResize } from '@rc-component/resize-observer'; interface ItemType { label: React.ReactNode; @@ -100,7 +102,7 @@ describe('Overflow.github', () => { jest.runAllTimers(); }); - expect(container.querySelector('.rc-overflow-item-rest')).toHaveStyle({ + expect(container.querySelector('.rc-overflow-item-rest')!).toHaveStyle({ opacity: 1, }); }); diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index a4f42d4..4145cc4 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -101,7 +101,7 @@ describe('Overflow.Basic', () => { , ); - expect(wrapper.find('Item').key()).toEqual('k-0'); + expect(wrapper.findItems().text()).toEqual('Label 0'); }); it('function', () => { const wrapper = mount( @@ -112,7 +112,7 @@ describe('Overflow.Basic', () => { />, ); - expect(wrapper.find('Item').key()).toEqual('bamboo-k-0'); + expect(wrapper.findItems().text()).toEqual('Label 0'); }); }); diff --git a/tests/prefix.spec.tsx b/tests/prefix.spec.tsx index 3720fe6..b01217d 100644 --- a/tests/prefix.spec.tsx +++ b/tests/prefix.spec.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { act } from '@testing-library/react'; import { mount } from './wrapper'; import Overflow from '../src'; @@ -24,7 +25,9 @@ describe('Overflow.Prefix', () => { }); afterEach(() => { - jest.runAllTimers(); + act(() => { + jest.runAllTimers(); + }); jest.useRealTimers(); }); @@ -54,7 +57,7 @@ describe('Overflow.Prefix', () => { expect(wrapper.findPrefix()).toHaveLength(0); }); - it('should work with responsive mode and show overflow', () => { + it('should work with responsive mode and show overflow', async () => { const wrapper = mount( data={getData(10)} @@ -66,15 +69,15 @@ describe('Overflow.Prefix', () => { ); // Small container to force overflow - wrapper.initSize(60, 20); + await wrapper.initSize(60, 20); // Should render prefix expect(wrapper.findPrefix()).toHaveLength(1); expect(wrapper.findPrefix().text()).toBe('Label:'); - + // Should show overflow indicator expect(wrapper.findRest()).toHaveLength(1); - + // Should render some but not all items expect(wrapper.findItems().length).toBeGreaterThan(0); expect(wrapper.findItems().length).toBeLessThan(10); @@ -94,7 +97,7 @@ describe('Overflow.Prefix', () => { // Should render prefix expect(wrapper.findPrefix()).toHaveLength(1); expect(wrapper.findPrefix().text()).toBe('Categories:'); - + // Should show exactly 3 items + rest expect(wrapper.findItems()).toHaveLength(3); expect(wrapper.findRest()).toHaveLength(1); @@ -117,7 +120,7 @@ describe('Overflow.Prefix', () => { expect(wrapper.findSuffix()).toHaveLength(1); expect(wrapper.findPrefix().text()).toBe('Start'); expect(wrapper.findSuffix().text()).toBe('End'); - + // Should show 3 items + rest expect(wrapper.findItems()).toHaveLength(3); expect(wrapper.findRest()).toHaveLength(1); @@ -144,4 +147,4 @@ describe('Overflow.Prefix', () => { expect(wrapper.findPrefix().find('.complex-prefix')).toHaveLength(1); expect(wrapper.findPrefix().text()).toBe('🏷️Tags:'); }); -}); \ No newline at end of file +}); diff --git a/tests/raw.spec.tsx b/tests/raw.spec.tsx index 4bc073d..4a545a4 100644 --- a/tests/raw.spec.tsx +++ b/tests/raw.spec.tsx @@ -1,6 +1,5 @@ import React from 'react'; import Overflow from '../src'; -import Item from '../src/Item'; import { mount } from './wrapper'; interface ItemType { @@ -51,7 +50,7 @@ describe('Overflow.Raw', () => { expect(wrapper.render()).toMatchSnapshot(); - expect(wrapper.exists(Item)).toBeFalsy(); + expect(wrapper.findItems()).toHaveLength(0); }); it('HOC usage', () => { diff --git a/tests/responsive.spec.tsx b/tests/responsive.spec.tsx index c7fb13d..f7d537c 100644 --- a/tests/responsive.spec.tsx +++ b/tests/responsive.spec.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { act } from 'react-dom/test-utils'; +import { act } from '@testing-library/react'; import Overflow from '../src'; import { mount } from './wrapper'; @@ -28,7 +28,7 @@ describe('Overflow.Responsive', () => { jest.useRealTimers(); }); - it('basic', () => { + it('basic', async () => { const wrapper = mount( data={getData(6)} @@ -37,7 +37,7 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(100, 20); // [0][1][2][3][4][+2](5)(6) + await wrapper.initSize(100, 20); // [0][1][2][3][4][+2](5)(6) expect(wrapper.findItems()).toHaveLength(6); [true, true, true, true, false, false].forEach((display, i) => { expect(wrapper.findItems().at(i).props().display).toBe(display); @@ -49,7 +49,7 @@ describe('Overflow.Responsive', () => { ).toBeTruthy(); }); - it('only one', () => { + it('only one', async () => { const wrapper = mount( data={getData(1)} @@ -58,13 +58,13 @@ describe('Overflow.Responsive', () => { maxCount="responsive" />, ); - wrapper.initSize(100, 20); + await wrapper.initSize(100, 20); expect(wrapper.findItems()).toHaveLength(1); expect(wrapper.findRest().props().display).toBeFalsy(); }); - it('just fit', () => { + it('just fit', async () => { const wrapper = mount( data={getData(1)} @@ -73,13 +73,13 @@ describe('Overflow.Responsive', () => { maxCount="responsive" />, ); - wrapper.initSize(20, 20); + await wrapper.initSize(20, 20); expect(wrapper.findItems()).toHaveLength(1); expect(wrapper.findRest().props().display).toBeFalsy(); }); - it('remove to clean up', () => { + it('remove to clean up', async () => { const data = getData(6); const wrapper = mount( @@ -90,7 +90,7 @@ describe('Overflow.Responsive', () => { maxCount="responsive" />, ); - wrapper.initSize(100, 20); + await wrapper.initSize(100, 20); // Remove one (Just fit the container width) const newData = [...data]; @@ -115,7 +115,7 @@ describe('Overflow.Responsive', () => { expect(wrapper.findRest().props().display).toBeFalsy(); }); - it('none to overflow', () => { + it('none to overflow', async () => { const data = getData(5); const wrapper = mount( @@ -127,7 +127,7 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(100, 20); + await wrapper.initSize(100, 20); expect(wrapper.findItems()).toHaveLength(5); expect(wrapper.findRest().props().display).toBeFalsy(); @@ -147,12 +147,12 @@ describe('Overflow.Responsive', () => { expect(wrapper.findRest().props().display).toBeFalsy(); // Trigger resize, node ready - wrapper.triggerItemResize(0, 20); + await wrapper.triggerItemResize(0, 20); expect(wrapper.findItems()).toHaveLength(6); expect(wrapper.findRest().props().display).toBeTruthy(); }); - it('unmount no error', () => { + it('unmount no error', async () => { const wrapper = mount( data={getData(1)} @@ -162,7 +162,7 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(100, 20); + await wrapper.initSize(100, 20); wrapper.unmount(); @@ -172,7 +172,7 @@ describe('Overflow.Responsive', () => { }); describe('suffix', () => { - it('ping the position', () => { + it('ping the position', async () => { const wrapper = mount( data={getData(10)} @@ -183,7 +183,7 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(100, 20); + await wrapper.initSize(100, 20); expect(wrapper.findSuffix().props().style).toEqual( expect.objectContaining({ @@ -194,7 +194,7 @@ describe('Overflow.Responsive', () => { ); }); - it('too long to pin', () => { + it('too long to pin', async () => { const wrapper = mount( data={getData(1)} @@ -205,13 +205,13 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(100, 20); - wrapper.triggerItemResize(0, 90); + await wrapper.initSize(100, 20); + await wrapper.triggerItemResize(0, 90); expect(wrapper.findSuffix().props().style.position).toBeFalsy(); }); - it('long to short should keep correct position', () => { + it('long to short should keep correct position', async () => { const wrapper = mount( data={getData(3)} @@ -222,7 +222,7 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(20, 20); + await wrapper.initSize(20, 20); wrapper.setProps({ data: [] }); expect(wrapper.findRest()).toHaveLength(0); @@ -231,7 +231,7 @@ describe('Overflow.Responsive', () => { }); describe('prefix', () => { - it('should render prefix when provided', () => { + it('should render prefix when provided', async () => { const wrapper = mount( data={getData(5)} @@ -242,14 +242,14 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(100, 20); + await wrapper.initSize(100, 20); // Should render prefix expect(wrapper.findPrefix()).toHaveLength(1); expect(wrapper.findPrefix().text()).toBe('Label:'); }); - it('should not render prefix when not provided', () => { + it('should not render prefix when not provided', async () => { const wrapper = mount( data={getData(5)} @@ -259,12 +259,12 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(100, 20); + await wrapper.initSize(100, 20); expect(wrapper.findPrefix()).toHaveLength(0); }); - it('should show overflow with prefix taking space', () => { + it('should show overflow with prefix taking space', async () => { const wrapper = mount( data={getData(10)} @@ -276,21 +276,21 @@ describe('Overflow.Responsive', () => { ); // Very small container to ensure overflow - wrapper.initSize(60, 20); + await wrapper.initSize(60, 20); // Should have prefix expect(wrapper.findPrefix()).toHaveLength(1); - + // Should show rest due to limited space expect(wrapper.findRest()).toHaveLength(1); - + // Should show limited number of items expect(wrapper.findItems().length).toBeGreaterThan(0); expect(wrapper.findItems().length).toBeLessThan(10); }); }); - it('render rest directly', () => { + it('render rest directly', async () => { const wrapper = mount( data={getData(10)} @@ -307,7 +307,7 @@ describe('Overflow.Responsive', () => { />, ); - wrapper.initSize(100, 20); + await wrapper.initSize(100, 20); expect(wrapper.find('span.custom-rest').text()).toEqual('6'); }); diff --git a/tests/setup.js b/tests/setup.js index acb3228..5606718 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -1,52 +1,26 @@ -const Enzyme = require('enzyme'); -const Adapter = require('enzyme-adapter-react-16'); -const { act } = require('react-dom/test-utils'); +const { TextDecoder, TextEncoder } = require('util'); require('regenerator-runtime/runtime'); -window.requestAnimationFrame = (func) => { +window.requestAnimationFrame = func => { window.setTimeout(func, 16); }; -Enzyme.configure({ adapter: new Adapter() }); +const MockResizeObserver = class ResizeObserver { + observe() {} + unobserve() {} + disconnect() {} +}; + +global.ResizeObserver = MockResizeObserver; +window.ResizeObserver = MockResizeObserver; -Object.assign(Enzyme.ReactWrapper.prototype, { - triggerResize(clientWidth) { - const target = this.find('ResizeObserver').first() - target.invoke('onResize')({}, { clientWidth }) - act(() => { - jest.runAllTimers(); - }) - this.update() - }, - triggerItemResize(index, offsetWidth) { - const target = this.find('Item').at(index).find('ResizeObserver') - target.invoke('onResize')({ offsetWidth }); - act(() => { - jest.runAllTimers(); - }) - this.update() - }, - initSize(width, itemWidth) { - this.triggerResize(width); - this.find('Item').forEach((_, index) => { - this.triggerItemResize(index, itemWidth); - }); - }, - findItems() { - return this.find('Item').filterWhere( - (item) => - item.props().className !== 'rc-overflow-item-rest' && - item.props().className !== 'rc-overflow-item-prefix' && - item.props().className !== 'rc-overflow-item-suffix', - ); - }, - findRest() { - return this.find('Item.rc-overflow-item-rest'); - }, - findPrefix() { - return this.find('Item.rc-overflow-item-prefix'); - }, - findSuffix() { - return this.find('Item.rc-overflow-item-suffix'); - }, +Object.defineProperty(global, 'TextEncoder', { + value: TextEncoder, }); + +Object.defineProperty(global, 'TextDecoder', { + value: TextDecoder, +}); + +global.MessageChannel = undefined; +window.MessageChannel = undefined; diff --git a/tests/ssr.spec.tsx b/tests/ssr.spec.tsx index 50c9798..af4a6b8 100644 --- a/tests/ssr.spec.tsx +++ b/tests/ssr.spec.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render } from 'enzyme'; +import { renderToStaticMarkup } from 'react-dom/server'; import Overflow from '../src'; interface ItemType { @@ -28,7 +28,8 @@ describe('Overflow.SSR', () => { }); it('basic', () => { - const wrapper = render( + const container = document.createElement('div'); + container.innerHTML = renderToStaticMarkup( data={getData(2)} renderItem={renderItem} @@ -37,6 +38,6 @@ describe('Overflow.SSR', () => { />, ); - expect(wrapper).toMatchSnapshot(); + expect(container.firstChild).toMatchSnapshot(); }); }); diff --git a/tests/wrapper.ts b/tests/wrapper.ts index 65a66c2..1f99d6f 100644 --- a/tests/wrapper.ts +++ b/tests/wrapper.ts @@ -1,18 +1,248 @@ -import type { ReactWrapper } from 'enzyme'; -import { mount as enzymeMount } from 'enzyme'; - -export type MountParam = Parameters; - -export interface WrapperType extends ReactWrapper { - triggerResize: (offsetWidth: number) => WrapperType; - triggerItemResize: (index: number, offsetWidth: number) => WrapperType; - initSize: (width: number, itemWidth: number) => WrapperType; - findItems: () => WrapperType; - findRest: () => WrapperType; - findPrefix: () => WrapperType; - findSuffix: () => WrapperType; +import './setup'; +import React from 'react'; +import { act, render } from '@testing-library/react'; +import { _rs as onResize } from '@rc-component/resize-observer'; + +function setElementSize( + element: HTMLElement, + size: Partial>, +) { + Object.entries(size).forEach(([key, value]) => { + Object.defineProperty(element, key, { + configurable: true, + value, + }); + }); +} + +async function flushResize() { + await act(async () => { + await Promise.resolve(); + }); + + act(() => { + jest.runAllTimers(); + }); + + await act(async () => { + await Promise.resolve(); + }); +} + +function normalizeStyle(style: CSSStyleDeclaration) { + const styleObj: Record = {}; + + Array.from(style).forEach(key => { + const value = style.getPropertyValue(key); + const camelKey = key.replace(/-([a-z])/g, (_, char: string) => + char.toUpperCase(), + ); + + styleObj[camelKey] = value.endsWith('px') + ? Number.parseFloat(value) + : value; + }); + + return styleObj; } -export function mount(...args: MountParam) { - return enzymeMount(...args) as WrapperType; +class NodeCollection { + private nodes: HTMLElement[]; + + constructor(nodes: HTMLElement[]) { + this.nodes = nodes; + } + + get length() { + return this.nodes.length; + } + + at(index: number) { + return new NodeCollection([this.nodes[index]].filter(Boolean)); + } + + last() { + return this.at(this.nodes.length - 1); + } + + find(selector: string) { + const matchNodes = this.nodes.flatMap(node => { + const nodes: HTMLElement[] = []; + + if (node.matches(selector)) { + nodes.push(node); + } + + nodes.push(...Array.from(node.querySelectorAll(selector))); + return nodes; + }); + + return new NodeCollection(matchNodes); + } + + text() { + return this.nodes.map(node => node.textContent).join(''); + } + + props() { + const element = this.nodes[0]; + + if (!element) { + return {}; + } + + const hidden = element.getAttribute('aria-hidden') === 'true'; + + return { + display: !hidden && element.style.opacity !== '0', + style: normalizeStyle(element.style), + }; + } + + prop(name: string) { + const element = this.nodes[0]; + + if (!element) { + return undefined; + } + + if (name === 'aria-hidden') { + return element.getAttribute(name) === 'true' || undefined; + } + + return element.getAttribute(name); + } + + [Symbol.iterator]() { + return this.nodes[Symbol.iterator](); + } + + forEach(callback: (node: NodeCollection, index: number) => void) { + this.nodes.forEach((_, index) => { + callback(this.at(index), index); + }); + } +} + +export function mount(element: React.ReactElement) { + let mergedElement = element; + const result = render(mergedElement); + + const getOverflow = () => + result.container.querySelector('.rc-overflow'); + + const queryItems = () => + Array.from( + result.container.querySelectorAll( + '.rc-overflow-item:not(.rc-overflow-item-rest):not(.rc-overflow-item-prefix):not(.rc-overflow-item-suffix)', + ), + ); + + const queryOverflowItems = () => + Array.from( + result.container.querySelectorAll('.rc-overflow-item'), + ); + + const triggerElementResize = async ( + target: HTMLElement, + offsetWidth: number, + ) => { + setElementSize(target, { offsetWidth }); + act(() => { + onResize([{ target } as any]); + }); + await flushResize(); + }; + + const wrapper = { + ...result, + find(selector: string) { + if (selector === 'ResizeObserver') { + return new NodeCollection([]); + } + + if (selector === 'Item') { + return new NodeCollection(queryItems()); + } + + return new NodeCollection( + Array.from(result.container.querySelectorAll(selector)), + ); + }, + findItems() { + return new NodeCollection(queryItems()); + }, + findRest() { + return new NodeCollection( + Array.from( + result.container.querySelectorAll( + '.rc-overflow-item-rest', + ), + ), + ); + }, + findPrefix() { + return new NodeCollection( + Array.from( + result.container.querySelectorAll( + '.rc-overflow-item-prefix', + ), + ), + ); + }, + findSuffix() { + return new NodeCollection( + Array.from( + result.container.querySelectorAll( + '.rc-overflow-item-suffix', + ), + ), + ); + }, + async triggerResize(clientWidth: number) { + const target = getOverflow(); + + if (target) { + setElementSize(target, { clientWidth }); + act(() => { + onResize([{ target } as any]); + }); + await flushResize(); + } + + return wrapper; + }, + async triggerItemResize(index: number, offsetWidth: number) { + const target = queryItems()[index]; + + if (target) { + await triggerElementResize(target, offsetWidth); + } + + return wrapper; + }, + async initSize(width: number, itemWidth: number) { + await wrapper.triggerResize(width); + + const overflowItems = queryOverflowItems(); + for (let index = 0; index < overflowItems.length; index += 1) { + await triggerElementResize(overflowItems[index], itemWidth); + } + + return wrapper; + }, + setProps(props: Record) { + mergedElement = React.cloneElement(mergedElement, props); + result.rerender(mergedElement); + return wrapper; + }, + update() { + return wrapper; + }, + render() { + return result.container.firstChild; + }, + }; + + return wrapper; }