使用createRemixStub时无法触发路由action的问题排查
问题:Remix测试中Action无法触发(浏览器中正常)
路由代码
export async function loader(_args: LoaderFunctionArgs, _emailService?: EmailService) { const emailService = _emailService ?? new EmailFixtureService(); // do stuff return json({ eventRowsJson }); } export async function action(args: ActionFunctionArgs, distanceService?: DistanceService) { console.log("BEFORE BEFORE BEFORE"); await distanceService?.getDistanceInfo({ from: "", to: "" }); console.log("AFTER AFTER AFTER"); return { hello: "world" }; } export default function Events() { const { eventRowsJson } = useLoaderData<typeof loader>(); return <EventsPage eventRows={eventRowsJson} />; };
EventsPage渲染结构
eventRows.map<FullGigUI /><GetDistanceInfoButton />
按钮组件代码
function GetDistanceInfoButton({ location }: { location: string }) { return ( <form method="post" > <input name="location" type="hidden" value={location} /> <Button data-testid="GET_DISTANCE_INFO_BUTTON"> Get distance info </Button> </form> ); } export function Button(props: ButtonHTMLAttributes<HTMLButtonElement> & { "data-testid"?: string }) { return ( <div className="grid place-items-center h-full" data-testid={props["data-testid"] ?? "saveButton"}> <button type="submit" className="p-2 bg-gray-200 border-black border"> {props.children} </button> </div> ); }
测试目标流程
- 页面渲染两个无距离数据的“事件”
- 点击“Get Distance Info”按钮
- action从DistanceService获取距离信息
- 路由展示距离信息
问题现象与测试代码
目前loader和页面功能正常,但测试中action无法触发。设置loaderSpy和actionSpy排查后,loaderSpy被调用,但actionSpy从未触发(无论是否使用waitFor)。浏览器中点击按钮可正常触发action,尝试过将data-testid移至button本身、为form指定action属性,测试仍无法触发action。
测试代码如下:
it("Fetches the distance info and updates the event ui", async () => { const RemixStub = createRemixStub([ { path: EventsRoute.PATH, loader: (args) => EventsRoute.loader(args, new EmailServiceMock()), action: (args) => EventsRoute.action(args, mockDistanceService), Component: eventsRoute } ]); const loaderSpy = vi.spyOn(EventsRoute, "loader"); const actionSpy = vi.spyOn(EventsRoute, "action"); expect(loaderSpy).not.toHaveBeenCalled(); render(<RemixStub initialEntries={[EventsRoute.PATH]} />); await waitFor(() => screen.findByTestId("EVENTS_PAGE")); expect(loaderSpy).toHaveBeenCalled(); const getDistanceInfoButtons = screen.getAllByTestId("GET_DISTANCE_INFO_BUTTON"); // neither event has distance info yet expect(getDistanceInfoButtons).toHaveLength(2); expect(mockDistanceService.getDistanceInfo).not.toHaveBeenCalled(); fireEvent.click(getDistanceInfoButtons[0]); await waitFor(() => { expect(actionSpy).toHaveBeenCalled(); // FAIL!!! (with or without waitFor) }); });
内容的提问来源于stack exchange,提问作者Jonathan Tuzman
相关产品推荐
相关产品推荐

