У меня есть компонент, который отображает текст и показывает show more
ссылку с многоточием ...
, если текст переполняется. Когда пользователь нажимает show more
, ссылка изменяется на show less
, и весь текст отображается без многоточия ...
.
TestApp.tsx
import React from 'react';
import './styles.css';
export default function App(props: any) {
const ref: any = React.createRef();
const [showMore, setShowMore] = React.useState(false);
const [showLink, setShowLink] = React.useState(false);
React.useLayoutEffect(() => {
if (ref.current.clientWidth < ref.current.scrollWidth) {
setShowLink(true);
}
}, [ref]);
const onClickMore = () => {
setShowMore(!showMore);
};
const renderMore = () => {
return (
<span className='link' onClick={onClickMore}>
{showMore ? 'show less' : 'show more'}
</span>
);
};
return (
<div>
<div ref={ref} className={showMore ? '' : 'container'}>
{props.list.join(', ')}
</div>
{showLink && renderMore()}
</div>
);
}
стили. css
.container {
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 200px;
}
.link {
text-decoration: underline;
cursor: pointer;
color: #0d6aa8;
}
Я хочу протестировать этот компонент. Ниже приведены утверждения, которые я хочу сделать
Given that text is not overflowing
1. Show more link should not be displayed
2. Entire text should be displayed
Given that text is overflowing
1. Show more link should be displayed
2. Entire text should not be displayed
When show more link is clicked
1. Show less link should be displayed
2. Show more link should not be displayed
3. Entire text should be displayed
When show less link is clicked
1. Show more link should be displayed
2. Show less link should not be displayed
3. Entire text should not be displayed
Теперь тестирование сценария, в котором текст не переполняется, достаточно просто. Но тестирование сценария, в котором текст переполняется, оказывается трудным. Поскольку я показываю show more
ссылку, когда clientWidth < scrollWidth
компонента и во время тестирования, оба эти значения кажутся равными 0. Я обнаружил проблему github в repo реагирующей-библиотеки-репозитории , и я попытался проверить это следующими способами
TestApp.test.tsx
import { fireEvent, render } from '@testing-library/react';
import React from 'react';
import App from './TestApp';
describe('When user views list', () => {
describe('When text does not overflow', () => {
test('that show more text is not displayed', async () => {
const props = { list: ['value1', 'value2', 'value3'] };
const { queryByText } = render(<App {...props} />);
expect(queryByText('show more')).toBeNull();
});
test('that entire violation text is shown', async () => {
const props = { list: ['value1', 'value2', 'value3'] };
const { getByText } = render(<App {...props} />);
expect(getByText(props.list.join(', '))).toBeDefined();
});
});
describe('When text overflows', () => {
let props: any;
let list: string[];
let text: string;
let getByText: any;
let queryByText: any;
const showMoreText = 'show more';
const showLessText = 'show less';
beforeEach(() => {
list = Array.from({ length: 20 }, (_, index) => `value${index}`);
props = { list };
text = list.join(', ');
});
beforeAll(() => {
Object.defineProperty(window.HTMLHtmlElement.prototype, 'clientWidth', { configurable: true, value: 100 });
Object.defineProperty(window.HTMLHtmlElement.prototype, 'scrollWidth', { configurable: true, value: 200 });
const component = render(<App {...props} />);
getByText = component.getByText;
queryByText = component.queryByText;
});
afterAll(() => {
Object.defineProperty(window.HTMLHtmlElement.prototype, 'clientWidth', { configurable: true, value: 0 });
Object.defineProperty(window.HTMLHtmlElement.prototype, 'scrollWidth', { configurable: true, value: 0 });
});
test('that show more link is displayed', async () => {
expect(getByText(showMoreText)).toBeDefined();
});
test('that entire text is not displayed', async () => {
expect(queryByText(list)).toBeNull();
});
describe('When user clicks on show more link', () => {
beforeAll(() => {
fireEvent.click(getByText(showMoreText));
});
test('that show more link is not displayed anymore', async () => {
expect(queryByText(showMoreText)).toBeNull();
});
test('that show less link is displayed', async () => {
expect(getByText(showLessText)).toBeDefined();
});
test('that entire text is displayed', async () => {
expect(getByText(text)).toBeDefined();
});
describe('When user clicks on show less link', () => {
beforeAll(() => {
fireEvent.click(getByText(showLessText));
});
test('that show less link is not displayed anymore', async () => {
expect(queryByText(showLessText)).toBeNull();
});
test('that show more link is displayed again', async () => {
expect(getByText(showMoreText)).toBeDefined();
});
test('that entire text is not displayed', async () => {
expect(queryByText(text)).toBeNull();
});
});
});
});
});
Но это не работает. Как правильно проверить этот компонент?