Created
February 18, 2021 05:09
-
-
Save nishio/06249db25dafef81646d961ec9c0c70e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Dispatch } from "react"; | |
import { act, render, screen } from "@testing-library/react"; | |
import { MyComponent } from "./MyComponent"; | |
import { MyAsyncComponent, resolve, userTrigger } from "./MyAsyncComponent"; | |
import { useState as originalUseState } from "react"; | |
test("MyComponent1", () => { | |
type TSetState = React.Dispatch<React.SetStateAction<number>>; | |
let setValue: TSetState | undefined; | |
const exportSetValue = (s: TSetState) => { | |
setValue = s; | |
}; | |
render(<MyComponent exportSetValue={exportSetValue} />); | |
expect(screen.getByText("0")).toBeTruthy(); | |
expect(setValue).toBeTruthy(); | |
act(() => { | |
setValue!(1); | |
}); | |
expect(screen.queryByText("0")).toBeNull(); | |
expect(screen.getByText("1")).toBeTruthy(); | |
}); | |
test("MyComponent2", async () => { | |
type TSetState = React.Dispatch<React.SetStateAction<number>>; | |
let setValue: TSetState | undefined; | |
const exportSetValue = (s: TSetState) => { | |
setValue = s; | |
}; | |
const asyncUpdate: Promise<number> = new Promise((resolve) => { | |
resolve(1); | |
}); | |
render(<MyComponent exportSetValue={exportSetValue} />); | |
expect(screen.getByText("0")).toBeTruthy(); | |
expect(setValue).toBeTruthy(); | |
console.log(1); | |
// act(() => { | |
// console.log(2); | |
// asyncUpdate.then((x) => { | |
// console.log(5); | |
// setValue!(x); | |
// }); | |
// console.log(3); | |
// }); | |
// console.log(4); | |
// expect(screen.queryByText("0")).toBeNull(); // fails | |
// expect(screen.getByText("1")).toBeTruthy(); | |
}); | |
test("MyComponent3", async () => { | |
let setValue: React.Dispatch<React.SetStateAction<number>> | undefined; | |
const exportSetValue = (s: React.Dispatch<React.SetStateAction<number>>) => { | |
setValue = s; | |
}; | |
const asyncUpdate: Promise<number> = new Promise((resolve) => { | |
resolve(1); | |
}); | |
render(<MyComponent exportSetValue={exportSetValue} />); | |
expect(screen.getByText("0")).toBeTruthy(); | |
expect(setValue).toBeTruthy(); | |
await asyncUpdate.then((x) => { | |
act(() => { | |
setValue!(x); | |
}); | |
}); | |
expect(screen.queryByText("0")).toBeNull(); // OK | |
expect(screen.getByText("1")).toBeTruthy(); | |
}); | |
test("MyComponent4", () => { | |
let setValue: React.Dispatch<React.SetStateAction<number>> | undefined; | |
const exportSetValue = (s: React.Dispatch<React.SetStateAction<number>>) => { | |
setValue = s; | |
}; | |
const asyncUpdate: Promise<number> = new Promise((resolve) => { | |
resolve(1); | |
}); | |
render(<MyComponent exportSetValue={exportSetValue} />); | |
expect(screen.getByText("0")).toBeTruthy(); | |
expect(setValue).toBeTruthy(); | |
return asyncUpdate | |
.then((x) => { | |
act(() => { | |
setValue!(x); | |
}); | |
}) | |
.then(() => { | |
expect(screen.queryByText("0")).toBeNull(); // OK | |
expect(screen.getByText("1")).toBeTruthy(); | |
}); | |
}); | |
test("MyComponent5", async () => { | |
let setValue: React.Dispatch<React.SetStateAction<number>> | undefined; | |
const exportSetValue = (s: React.Dispatch<React.SetStateAction<number>>) => { | |
setValue = s; | |
}; | |
const asyncUpdate: Promise<number> = new Promise((resolve) => { | |
resolve(1); | |
}); | |
const userEventHandler = () => { | |
asyncUpdate.then((x) => { | |
setValue!(x); | |
}); | |
}; | |
render(<MyComponent exportSetValue={exportSetValue} />); | |
expect(screen.getByText("0")).toBeTruthy(); | |
expect(setValue).toBeTruthy(); | |
userEventHandler(); // Here | |
// expect(screen.queryByText("0")).toBeNull(); // fails | |
// expect(screen.getByText("1")).toBeTruthy(); | |
}); | |
test("MyAsyncComponent1", async () => { | |
jest.spyOn(React, "useState").mockImplementation((arg?: unknown): [ | |
unknown, | |
Dispatch<unknown> | |
] => { | |
const [s, setS] = originalUseState(arg); | |
return [ | |
s, | |
(arg: unknown) => { | |
act(() => { | |
setS(arg); | |
}); | |
}, | |
]; | |
}); | |
render(<MyAsyncComponent />); | |
expect(screen.getByText("0")).toBeTruthy(); | |
console.log(3); | |
userTrigger(); | |
console.log(5); | |
expect(screen.getByText("0")).toBeTruthy(); | |
await resolve(1); | |
console.log(7); | |
expect(screen.queryByText("0")).toBeNull(); | |
expect(screen.getByText("1")).toBeTruthy(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState } from "react"; | |
export type TUserTrigger = () => Promise<void>; | |
export type TResolve = (value: number) => void; | |
export let userTrigger: TUserTrigger; | |
export let resolve: TResolve; | |
export const MyAsyncComponent = () => { | |
const [value, setValue] = useState(0); | |
console.log(1); | |
userTrigger = () => { | |
console.log(4); | |
return new Promise<number>((res) => { | |
resolve = res; | |
}).then((x) => { | |
console.log(6); | |
setValue(x); | |
}); | |
}; | |
console.log(2); | |
return <span>{value}</span>; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState } from "react"; | |
export const MyComponent = (props: { | |
exportSetValue: ( | |
setValue: React.Dispatch<React.SetStateAction<number>> | |
) => void; | |
}) => { | |
const [value, setValue] = useState(0); | |
props.exportSetValue(setValue); | |
return <span>{value}</span>; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment