我在測驗領域嘗試了一些冒險,特別是我想測驗一些基本的 React 組件,但我在第一步卡住了。這是我在應用程式中使用的簡化形式。
該表格正在作業。我正在努力測驗 atm 視圖。
我想要的是:
我想測驗沒有容器的視圖和帶有視圖的容器。
我寫了一些基本的測驗,我認為它們應該看起來像
- 視圖:測驗是否
change使用正確的資料呼叫 - 演示者:在
change被呼叫后測驗輸入的值是什么 <-這是有效的,因此不是在代碼中而是在要點中
我期望發生的事情:
如果我打電話fireEvent參加考試,我希望他考試通過。
怎么了:
第一個測驗正在作業(顯然),因為組件被初始化為空值。onChange容器組件中的測驗也正常作業。將onChange在我看來試驗中損壞,該型別的事件不匹配。
我如何測驗這個或實作正確的型別?
代碼:
LoginView.ts(演示者)
import { ChangeEvent, createElement, FunctionComponent } from "react";
export interface LoginViewProps {
username: string;
password: string;
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
onSubmit: () => void;
}
export const LoginView: FunctionComponent<LoginViewProps> = (props: LoginViewProps) => {
return createElement("div", {},
createElement("label", {
htmlFor: "username",
},
"Username:",
),
createElement("input", {
"data-testid": "username",
type: "text",
name: "username",
id: "username",
value: props.username,
onChange: props.onChange,
}),
createElement("label", {
htmlFor: "password",
},
"Password:",
),
createElement("input", {
"data-testid": "password",
type: "password",
name: "password",
id: "password",
value: props.password,
onChange: props.onChange,
}),
createElement("button", {
type: "button",
"data-testid": "submit",
onClick: props.onSubmit,
},
"Sign in",
),
);
};
export default LoginView;
LoginView.test.ts - 測驗視圖
import "@testing-library/jest-dom";
import { createElement } from "react";
import { render, fireEvent, cleanup } from "@testing-library/react";
import LoginView, { LoginViewProps } from "./LoginView";
afterEach(cleanup);
describe("Login Presenter", () => {
/**
* This works, more coincidence than knowledge
*/
it("should display div with blank values", async () => {
const { findByTestId } = renderLoginForm();
const username = await findByTestId("username");
const password = await findByTestId("password");
expect(username).toHaveValue("");
expect(password).toHaveValue("");
});
/**
* This is not working
*/
it("should allow entering a username", async () => {
const onChange = jest.fn();
const { findByTestId } = renderLoginForm({
onChange,
});
const username = await findByTestId("username");
fireEvent.change(username, {
target: {
id: "username",
value: "test",
},
});
/**
* This expect is wrong,
* received: Object {...}
* expected: SyntheticBaseEvent {...}
*/
expect(onChange).toHaveBeenCalledWith({
target: {
id: "username",
value: "test",
},
});
});
/**
* This is not working
*/
it("should allow entering a password", async () => {
const onChange = jest.fn();
const { findByTestId } = renderLoginForm({
onChange,
});
const password = await findByTestId("password");
fireEvent.change(password, {
target: {
id: "password",
value: "test",
},
});
/**
* This expect is wrong,
* received: Object {...}
* expected: SyntheticBaseEvent {...}
*/
expect(onChange).toHaveBeenCalledWith({
target: {
id: "password",
value: "test",
},
});
});
it("should submit the form with username, password", async () => {
/**
* What to write here?
*
* How can i test the values that i provided
*/
});
});
function renderLoginForm(props: Partial<LoginViewProps> = {}) {
const defaultProps: LoginViewProps = {
username: "",
password: "",
onChange() {
return;
},
onSubmit() {
return;
},
};
return render(createElement(LoginView, {
...defaultProps,
...props,
}));
}
錯誤:
> jest
FAIL src/react/LoginForm/LoginView.test.ts
● Login Presenter ? should allow entering a username
expect(jest.fn()).toHaveBeenCalledWith(...expected)
- Expected
Received
- Object {
- "target": Object {
- "id": "username",
- "value": "test",
SyntheticBaseEvent {
"_reactName": "onChange",
"_targetInst": null,
"bubbles": true,
"cancelable": false,
"currentTarget": null,
"defaultPrevented": false,
"eventPhase": 3,
"isDefaultPrevented": [Function functionThatReturnsFalse],
"isPropagationStopped": [Function functionThatReturnsFalse],
"isTrusted": false,
"nativeEvent": Event {
"isTrusted": false,
},
"target": <input
data-testid="username"
id="username"
name="username"
type="text"
value=""
/>,
"timeStamp": 1640165302072,
"type": "change",
},
Number of calls: 1
31 | });
32 |
> 33 | expect(onChange).toHaveBeenCalledWith({
| ^
34 | target: {
35 | id: "username",
36 | value: "test",
at _callee2$ (src/react/LoginForm/LoginView.test.ts:33:20)
at tryCatch (node_modules/regenerator-runtime/runtime.js:63:40)
at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:294:22)
at Generator.next (node_modules/regenerator-runtime/runtime.js:119:21)
at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
● Login Presenter ? should allow entering a password
expect(jest.fn()).toHaveBeenCalledWith(...expected)
- Expected
Received
- Object {
- "target": Object {
- "id": "password",
- "value": "test",
SyntheticBaseEvent {
"_reactName": "onChange",
"_targetInst": null,
"bubbles": true,
"cancelable": false,
"currentTarget": null,
"defaultPrevented": false,
"eventPhase": 3,
"isDefaultPrevented": [Function functionThatReturnsFalse],
"isPropagationStopped": [Function functionThatReturnsFalse],
"isTrusted": false,
"nativeEvent": Event {
"isTrusted": false,
},
"target": <input
data-testid="password"
id="password"
name="password"
type="password"
value=""
/>,
"timeStamp": 1640165302102,
"type": "change",
},
Number of calls: 1
53 | });
54 |
> 55 | expect(onChange).toHaveBeenCalledWith({
| ^
56 | target: {
57 | id: "password",
58 | value: "test",
at _callee3$ (src/react/LoginForm/LoginView.test.ts:55:20)
at tryCatch (node_modules/regenerator-runtime/runtime.js:63:40)
at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:294:22)
at Generator.next (node_modules/regenerator-runtime/runtime.js:119:21)
at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
PASS src/react/LoginForm/Login.test.ts
Test Suites: 1 failed, 1 passed, 2 total
Tests: 2 failed, 6 passed, 8 total
Snapshots: 0 total
Time: 4.035 s
Ran all test suites.
npm ERR! Test failed. See above for more details.
要旨:
https://gist.github.com/simann/9cbf01f28602d59ba988ef608df99bc0
最后說明:
除了上面的錯誤,我仍然需要對該submit功能進行一些測驗,如果有人能提供一些資訊,我將不勝感激。
也歡迎任何其他提示或改進。
編輯
為了澄清起見,我還將添加容器的代碼
登錄.ts
import { ChangeEvent, Component, createElement } from "react";
import LoginForm from "./LoginView";
interface LoginState {
password: string;
username: string;
}
export class Login extends Component<null, LoginState> {
constructor(props: null) {
super(props);
this.state = {
password: "",
username: "",
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(event: ChangeEvent<HTMLInputElement>) {
const { id, value } = event.target;
this.setState({
...this.state,
[id]: value,
});
}
onSubmit() {
console.log(this.state.username, this.state.password);
/**
* Do a websocket request with the values
*/
}
render() {
return createElement(LoginForm, {
password: this.state.password,
username: this.state.username,
onChange: this.onChange,
onSubmit: this.onSubmit,
});
}
}
export default Login;
登錄.test.ts
import "@testing-library/jest-dom";
import { createElement } from "react";
import { render, fireEvent, cleanup } from "@testing-library/react";
import Login from "./Login";
afterEach(cleanup);
describe("Login Container", () => {
it("should display a blank login form with blank values", async () => {
const { findByTestId } = renderLogin();
const username = await findByTestId("username");
const password = await findByTestId("password");
expect(username).toHaveValue("");
expect(password).toHaveValue("");
});
it("should allow entering a username", async () => {
const { findByTestId } = renderLogin();
const username = await findByTestId("username");
fireEvent.change(username, {
target: {
id: "username",
value: "test",
},
});
expect(username).toHaveValue("test");
});
it("should allow entering a password", async () => {
const { findByTestId } = renderLogin();
const password = await findByTestId("password");
fireEvent.change(password, {
target: {
id: "password",
value: "test",
},
});
expect(password).toHaveValue("test");
});
it("should submit the form with username, password", async () => {
/**
* What to write here?
*
* How do i test the values that are in my state?
*/
});
});
function renderLogin() {
return render(createElement(Login));
}
uj5u.com熱心網友回復:
測驗失敗主要是因為您正在比較兩個不同的物件。
React 傳遞給事件處理程式的物件是 SyntheticEvent 的一個實體,它是瀏覽器本機事件的包裝器,比您與之比較的物件更復雜。
盡管具有與原生事件類似的介面,但 SyntheticEvent 類是 React 的一個實作細節,您應該避免圍繞其結構實作測驗,尤其是物件匹配測驗。
更好的方法是將您的onChange道具包裝在另一個函式中,該函式將呼叫它僅傳遞事件值。
...
createElement("input", {
"data-testid": "username",
type: "text",
name: "username",
id: "username",
value: props.username,
onChange: (event) => {
props.onChange(event.target.value);
},
})
...
然后,在您的測驗中,您可以撰寫:
...
fireEvent.change(password, {
target: {
value: "test",
},
});
expect(onChange).toHaveBeenCalledWith("test");
...
要測驗提交的值,請使用 ReactuseState保存輸入欄位的值。
...
const [username, setUsername] = React.useState("");
const [password, setPassword] = React.useState("");
...
createElement("input", {
"data-testid": "username",
type: "text",
name: "username",
id: "username",
value: props.username,
onChange: (event) => {
setUsername(event.target.value);
props.onChange(event.target.value);
},
}),
createElement("input", {
"data-testid": "password",
type: "password",
name: "password",
id: "password",
value: props.password,
onChange: () => {
setPassword(event.target.value);
props.onChange(event.target.value);
},
}),
createElement("button", {
type: "button",
"data-testid": "submit",
onClick: () => {
props.onSubmit(username, password)
},
},
"Sign in",
)
然后在你的測驗中你可以
it("should submit the form with username, password", async () => {
const onSubmit = jest.fn();
const { findByTestId } = renderLoginForm({
onSubmit,
});
const username = await findByTestId("username");
const password = await findByTestId("password");
const submit = await findByTestId("submit");
fireEvent.change(username, { target: { value: "username" } });
fireEvent.change(password, { target: { value: "password" } });
fireEvent.click(submit);
expect(onSubmit).toHaveBeenCalledWith("username", "password");
});
除此之外,您應該使用 JSX 來創建組件而不是createElement. ??
uj5u.com熱心網友回復:
通過您當前的組件代碼并測驗
expect(onChange).toHaveBeenCalledWith({
target: {
id: "username",
value: "test",
},
});
您實際上想要檢查“存在包含的物件,target: { id: "username", value: "test" }而當前您檢查“正是該物件”。這里有expect.objectContaining幫助:
expect(onChange).toHaveBeenCalledWith(
expect.objectContaining({
target: {
id: "username",
value: "test",
},
})
);
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/391806.html
