ابزارهای تست
ایمپورت کردن
import ReactTestUtils from 'react-dom/test-utils'; // ES6
var ReactTestUtils = require('react-dom/test-utils'); // ES5 with npm
بررسی اجمالی
ReactTestUtils
عملیات تست کامپوننتهای ریاکت را در فریموورک موردنظرتان ساده میکند. ما در فیسبوک از Jest برای تست کردن جاوااسکریپتی بدون دردسر استفاده میکنیم. برای اینکه یاد بگیرید از کجا شروع کنید از React Tutorial سایت Jest استفاده نمایید.
نکته:
ما استفاده از React Testing Library را پیشنهاد میکنیم، از آنجا که طراحی آن با هدف قادر ساختن و تشویق شما به نوشتن تست به گونهای است که کاربر نهایی کامپوننت شما را استفاده میکند.
برای نسخههای ریاکت <= 16، کتابخانه Enzyme بررسی، دستکاری و ارزیابی خروجی کامپوننتهای ریاکت شما را ساده میکند.
act()
mockComponent()
isElement()
isElementOfType()
isDOMComponent()
isCompositeComponent()
isCompositeComponentWithType()
findAllInRenderedTree()
scryRenderedDOMComponentsWithClass()
findRenderedDOMComponentWithClass()
scryRenderedDOMComponentsWithTag()
findRenderedDOMComponentWithTag()
scryRenderedComponentsWithType()
findRenderedComponentWithType()
renderIntoDocument()
Simulate
مرجع
act()
برای آمادهسازی یک کامپوننت برای اثبات، کدی که آن را رندر و بهروز رسانی میکند را درون یک فراخوانی act()
قرار دهید. اینکار باعث میشود تست شما به روش کارکرد ریاکت در مرورگر نزدیکتر شود.
نکته
اگر از
react-test-renderer
استفاده میکنید، یک خروجیact
که به همین شکل رفتار میکند برایتان فراهم میکند.
برای مثال، اجازه دهید بگوییم این کامپوننت Counter
را داریم:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
handleClick() {
this.setState(state => ({
count: state.count + 1,
}));
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.handleClick}>
Click me
</button>
</div>
);
}
}
به این شکل آن را تست میکنیم:
import React from 'react';
import ReactDOM from 'react-dom/client';
import { act } from 'react-dom/test-utils';import Counter from './Counter';
let container;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
it('can render and update a counter', () => {
// Test first render and componentDidMount
act(() => { ReactDOM.createRoot(container).render(<Counter />); }); const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('You clicked 0 times');
expect(document.title).toBe('You clicked 0 times');
// Test second render and componentDidUpdate
act(() => { button.dispatchEvent(new MouseEvent('click', {bubbles: true})); }); expect(label.textContent).toBe('You clicked 1 times');
expect(document.title).toBe('You clicked 1 times');
});
- فراموش نکنید که توضیع (dispatch) رویدادهای DOM تنها زمانی که DOM container به
document
اضافه شدهباشد کار میکند. شما میتوانید از یک کتابخانه مانند React Testing Library برای کاهش کدهای تکراری (boilerplate) استفاده کنید. - سند دستورالعملها شامل اطلاعات بیشتری در مورد چگونگی رفتار
act()
، با مثالها و کاربردها میباشد.
mockComponent()
mockComponent(
componentClass,
[mockTagName]
)
یک ماژول کامپوننت mock شده به این متد پاس دهید تا آن را به متدهای سودمندی که به آن اجازه میدهند که به عنوان یک کامپوننت ساختگی ریاکت استفاده شود تبدیل کنید. به جای اینکه مثل همیشه رندر شود، کامپوننت یک <div>
ساده (یا تگ دیگری اگر mockTagName
فراهم شده باشد) خواهد شد که هر فرزندی را که فراهم شدهباشد، دربر میگیرد.
نکته:
mockComponent()
یک API قدیمی است. ما استفاده ازjest.mock()
به عنوان جایگزین توصیه میکنیم.
isElement()
isElement(element)
اگر element
هر المنت ریاکتی باشد true
برمیگرداند.
isElementOfType()
isElementOfType(
element,
componentClass
)
اگر element
یک المنت ریاکت که از نوع componentClass
ریاکت است باشد، true
بازمیگرداند.
isDOMComponent()
isDOMComponent(instance)
اگر instance
یک کامپوننت DOM باشد (مانند یک <div>
یا <span>
) مقدار true
برمیگرداند.
isCompositeComponent()
isCompositeComponent(instance)
اگر instance
یک کامپوننت تعریف شده توسط کاربر مانند یک کلاس یا یک تابع باشد، مقدار true
را برمیگرداند.
isCompositeComponentWithType()
isCompositeComponentWithType(
instance,
componentClass
)
اگر instance
یک کامپوننت از نوع componentClass
ریاکت باشد مقدار true
را برمیگرداند.
findAllInRenderedTree()
findAllInRenderedTree(
tree,
test
)
از تمامی کامپوننت ها در tree
عبور میکند و تمام کامپوننتهایی که test(component)
آنها مقدار true
دارد را ذخیره میکند. به تنهایی کاربردی ندارد، اما به عنوان یک قدم اولیه برای دیگر ابزارهای تست استفاده میشود.
scryRenderedDOMComponentsWithClass()
scryRenderedDOMComponentsWithClass(
tree,
className
)
تمامی المنتهای DOM در کامپوننتهای درخت رندر شده را که کامپوننتهایی هستند که نام کلاسشان با className
برابر است را پیدا میکند.
findRenderedDOMComponentWithClass()
findRenderedDOMComponentWithClass(
tree,
className
)
شبیه scryRenderedDOMComponentsWithClass()
است اما انتظار دارد که تنها یک نتیجه وجود داشته باشد، یا اگر هر تعدادی به غیر از یک نتیجه پیدا کند یک خطا میاندازد.
scryRenderedDOMComponentsWithTag()
scryRenderedDOMComponentsWithTag(
tree,
tagName
)
تمامی المنتهای DOM در کامپوننتهای درخت رندر شده را که کامپوننتهایی هستند که نام تگشان با tagName
برابر است را پیدا میکند.
findRenderedDOMComponentWithTag()
findRenderedDOMComponentWithTag(
tree,
tagName
)
شبیه scryRenderedDOMComponentsWithTag()
است اما انتظار دارد که تنها یک نتیجه وجود داشته باشد، یا اگر هر تعدادی به غیر از یک نتیجه پیدا کند یک خطا میاندازد.
scryRenderedComponentsWithType()
scryRenderedComponentsWithType(
tree,
componentClass
)
تمامی instance های کامپوننتها با نوع componentClass
را پیدا میکند.
findRenderedComponentWithType()
findRenderedComponentWithType(
tree,
componentClass
)
مانند scryRenderedComponentsWithType()
است اما انتظار دارد که تنها یک نتیجه وجود داشته باشد، یا اگر هر تعدادی به غیر از یک نتیجه پیدا کند یک خطا باز میگرداند.
renderIntoDocument()
renderIntoDocument(element)
یک المنت ریاکت را در یک نود DOM جدا شده در document رندر میکند. این تابع یک DOM نیاز دارد. معادل است با:
const domContainer = document.createElement('div');
ReactDOM.createRoot(domContainer).render(element);
نکته:
شما به
window
،window.document
وwindow.document.createElement
قبل از اینکهReact
را ایمپورت کنید و با دسترسی عمومی نیاز خواهید داشت. در غیر اینصورت ریاکت فکر میکند که نمیتواند به DOM دسترسی پیدا کند و متدهایی مانندsetState
کار نخواهند کرد.
دیگر ابزارها
Simulate
Simulate.{eventName}(
element,
[eventData]
)
توزیع یک رویداد روی یک نود DOM با eventData
داده اختیاری برای رویداد شبیهسازی میکند.
Simulate
یک متد برای هر رویدادی که ریاکت میفهمد دارد.
کلیک کردن روی یک المنت
// <button ref={(node) => this.button = node}>...</button>
const node = this.button;
ReactTestUtils.Simulate.click(node);
تغییر مقدار یک فیلد ورودی و سپس فشردن ENTER.
// <input ref={(node) => this.textInput = node} />
const node = this.textInput;
node.value = 'giraffe';
ReactTestUtils.Simulate.change(node);
ReactTestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
نکته
شما باید هرگونه ویژگی رویدادی که در کامپوننتان استفاه میکنید (مانند keyCode, which, etc…) را فراهم کنید چرا که ریاکت هیچ یک از انها را برای شما ایجاد نمیکند.