Тестирую первый раз в жизни. У меня есть приложение секундомера, и я хочу проверить, работает ли секундомер. Я делаю это, нажимая кнопку и проверяя, что 00:00:00 все еще там.
Проблема в том, что 00:00:00 все еще находятся в промежутке после нажатия кнопки. Программа работает нормально, никаких проблем. В чем проблема с этим триггерином?
У меня есть кнопка START
для этого:
class SecondTimer extends React.Component {
constructor(props) {
super(props);
this.state = {
running: false, // Format to false, so when start a program clock is not running
currentTimeMs: 0,
currentTimeSec: 0,
currentTimeMin: 0,
};
}
start = () => {
if (!this.state.running) {
this.setState({ running: true });
this.watch = setInterval(() => this.pace(), 10);
}
};
{this.state.running === false && (
<Button className = {"start-stop-reset-nappi"} variant = "success" size = "lg" onClick=
{this.start}>START</Button>
)}
И у меня есть span
, где показано время (значение перед запуском 00:00:00, изображение ниже).
<span>
{this.props.formatTime(this.props.currentTimeMin)}:
{this.props.formatTime(this.props.currentTimeSec)}:
{this.props.formatTime(this.props.currentTimeMs)}
</span>
Тогда у меня есть этот тест:
import { render, screen, fireEvent } from '@testing-library/react';
import SecondTimer from '../components/SecondTimer.jsx';
test('Test - Secondmeter running or not', () => {
render(<SecondTimer />);
const start = screen.getByText("START") // Here I'll check is there button (text) like START
fireEvent.click(start); // Then I "Click" it
const numbers = screen.getByText(/00:00:00/i) // Check is the 00:00:00 still on screen after triggering the button
expect(numbers).toBeInTheDocument()
});
Полный код компонента:
import React from 'react';
import SecondTimerNumbers from './SecondTimerNumbers.jsx';
import SecondTimerList from './SecondTimerList.jsx';
import { Button } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
class SecondTimer extends React.Component {
constructor(props) {
super(props);
// Start funktio määrittää running arvon -> true, joka kertoo sen, että kello käy. Tallentaa tänne ajan, josta SeconTimerNumber hakee tiedon
this.state = {
running: false, // Alustettu falseksi, eli ohjelman avatessa kello ei käy
currentTimeMs: 0,
currentTimeSec: 0,
currentTimeMin: 0,
};
}
// Muuttaa kelloajan numeraaliset luvut stringiksi, sekä lisää yhdet nollat lukuun, jotta luvut ei ns. pompi silmillä.
formatTime = (val, ...rest) => {
let value = val.toString();
if (value.length < 2) {
value = '0' + value;
}
if (rest[0] === 'ms' && value.length < 3) {
value = '0' + value;
}
return value;
};
// Start napista painalla käynnistää tämän funktion. Muuttaa state running trueksi, eli kello käy. SetInterval on Reactin oma sekuntikello, ja this.pace 10 määrittelee sadasosasekunnit
start = () => {
if (!this.state.running) {
this.setState({ running: true });
this.watch = setInterval(() => this.pace(), 10);
}
};
// Stop painikkeesta muuttaa running staten falseksi -> kello pysähtyy, sekä tyhjentää sekuntikellon (pysäyttää).
stop = () => {
this.setState({ running: false });
clearInterval(this.watch);
};
// Määrittelee kellon toiminnan
pace = () => {
this.setState({ currentTimeMs: this.state.currentTimeMs + 10 }); // Lisää 10ms kerrallaan
// Kun millisekunteja 1000, lisää yhden sekunnin, sekä muuttaa millisekuntien arvoksi 0 kierroksen jälkeen
if (this.state.currentTimeMs >= 1000) {
this.setState({ currentTimeSec: this.state.currentTimeSec + 1 });
this.setState({ currentTimeMs: 0 });
}
// Kun sekunteja on 60, lisää yhden minuutin, sekä muuttaa sekuntien arvoksi 0 kierroksen jälkeen
if (this.state.currentTimeSec >= 60) {
this.setState({ currentTimeMin: this.state.currentTimeMin + 1 });
this.setState({ currentTimeSec: 0 });
}
};
// Määrittää (resetoi) staten allaolevat arvot nollaksi, jolloin sekuntikello voidaan taas aloittaa alusta
resetTime = () => {
this.setState({
currentTimeMs: 0,
currentTimeSec: 0,
currentTimeMin: 0,
});
};
// UserInterface eli käyttöliittymä renderöityy tässä
render() {
return (
<div className = {'main-div'}>
<div className = {'left'}>
{this.state.running === false && (
<Button className = {"start-stop-reset-nappi"} variant = "success" size = "lg" onClick = {this.start}>START</Button>
)}
{this.state.running === true && (
<Button className = {'start-stop-reset-nappi'} variant = "warning" size = "lg" onClick = {this.stop}>PAUSE</Button>
)}
<Button className = {'start-stop-reset-nappi'} variant = "danger" size = "lg" onClick = {this.resetTime}>RESET</Button>
<div className = {'tulostaulu-main'}>
<SecondTimerNumbers
ref = "display"
{...this.state}
formatTime = {this.formatTime}
/>
</div>
</div>
<div className = {'right'}>
<SecondTimerList clickResetTime = {this.resetTime} {...this.state} formatTime = {this.formatTime} />
</div>
</div>
);// Yllä oleva ClickResetTime funktio on tämän sivut resetTime funktio.
// Tällä saan kutsuttua funktiota toisesta componentista, tavallaan "injektoin" funktion tähän componenttiin.
}
}
export default SecondTimer;
Похоже, время отображения текста 00:00:00
всегда отображается в зависимости от нажатия кнопки или нет. Можете ли вы поделиться всем кодом вашего компонента?
@tmhao2005 Добавлен код этого компонента. В тесте всегда 00:00:00, что fireEvent.click()
не работает? Приложение работает нормально, это только тестовая проблема. Когда вы нажимаете эту кнопку START
, часы должны начать работать, но это не так.
Итак, вы ожидаете, что таймер будет работать, то есть 00:00:00
НЕ должен отображаться?
Я действительно не знаю, в чем проблема с вашим тестом. Я создал небольшой тест на основе вашего текущего, который работает очень хорошо.
Идея теста довольно проста. Когда я нажал кнопку, я ожидаю увидеть изменение в секундах. Ключевым моментом является использование waitFor
API с указанной опцией timeout
, чтобы убедиться, что тестовая библиотека разрешает изменение вашего пользовательского интерфейса.
Вот фрагмент:
import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import { SecondTimer } from "./App";
test("should work", async () => {
render(<SecondTimer />);
const start = screen.getByText("START");
fireEvent.click(start);
await waitFor(() => screen.getByText(/00:02:00/i), {
timeout: 2000 // wait 2s
});
const numbers = screen.getByText(/00:02:00/i);
expect(numbers).toBeInTheDocument();
});
Вот codesanbox, который я создал специально для вас (настройка для запуска теста основана на скрипте create-react-app
):
https://codesandbox.io/s/morning-browser-92uks?file=/src/App.test.js
ПРИМЕЧАНИЕ. Чтобы запустить тест, щелкните вкладку Tests
рядом с Browser
в области предварительного просмотра.
Спасибо! Я немного изменил ваш код, timeout: 2000
было недостаточно. Почему-то этот скрипт работает медленно или что-то в этом роде, span получил только 00:01:290
по истечении тайм-аута. Я увеличил тайм-аут до 3000
, затем он ждет еще одну секунду и получает 00:02:00
. Теперь работает :)) Спасибо!
Не могли бы вы уточнить ожидаемое поведение и наблюдаемое поведение?