Replies: 4 comments 2 replies
-
Sameeee..... |
Beta Was this translation helpful? Give feedback.
-
I wrote an article that may help you https://dev.to/weamadel/configure-playwright-with-nextjs-mock-apis-for-testing-44oh |
Beta Was this translation helpful? Give feedback.
-
@Mochitto did you ever manage to solve this? I'm surprised there isn't a we'll documented solution in the NextJS docs on this. "Just use e2e testing" can't seriously be the goto recommended approach for server actions. |
Beta Was this translation helpful? Give feedback.
-
I felt this pain. I've just created a tool that solves this problem https://docs.mockybalboa.com/. There's first class support for Next.js as well as Playwright and Cypress. It allows you to write your fixtures declaratively within your tests without having to modify any application logic. No proxy servers, no static fixtures, and it supports running tests in parallel. Fixtures are scoped to the client, which means no risk of leaking fixtures outside the tests they were written for. Here's the example from the Playwright docs on how the mocks are written in the tests. The client guide has more complete documentation on how you can mock requests. It's very similar to and was inspired by the Playwright route API for client side mocking. import { test, expect } from "@playwright/test";
import { createClient } from "@mocky-balboa/playwright";
test("my page loads", async ({ page, context }) => {
// Create our Mocky Balboa client and establish a connection with the server
const client = await createClient(context);
// Register our fixture on routes matching '**/api/users'
client.route("**/api/users", (route) => {
return route.fulfill({
status: 200,
body: JSON.stringify([
{ id: "user-1", name: "John Doe" },
{ id: "user-2", name: "Jane Doe" }
]),
headers: {
"Content-Type": "application/json"
},
});
});
// Visit the page of our application in the browser
await page.goto("http://localhost:3000");
// Our mock above should have been returned on our server
await expect(page.getByText("John Doe")).toBeVisible();
}); |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
Hello!
In the last two days, I've tried to write e2e tests for a simple form status (idle, loading, success, error) using playwright.
This form uses a server-action (not linked to a form, but triggered by a button click) that sends mails.
The return value of this server-action is a simple "success" or "error".
I wanted to intercept the server-action's POST request to avoid getting spammed by test mails and manipulate the response to emulate errors, but it seems very finicky to get to work...
I make use of the
useTransition
hook to keep track of the pending state and the server-action is contained in a function called "submitForm", which is called usingstartTransition
on submit button click. (part of the code in the "Additional information").What does work:
Removing the server-action and using a normal
route.js
POST endpoint works as expected with the basic@playwright/test
(using theroute
handler), without even needing to use the experimental proxy.Funnily enough, since I was lazy, this
route.js
endpoint is just a wrapper to the server-action, but this doesn't seem to be a problem (probably because we are already in the server, so it really is just a normal function).I understand that this is functionally the same, but I would like to follow the good pattern of using server-actions whenever I don't need to expose the endpoints to the public, so I'd like to find a solution to this problem, also for the future (if I can't mock server-actions, I would probably move away from them, and I really like the DEV-X they bring).
Things I tried:
This successfully intercepts the POST request and returns the correct values when inspecting the network but the server action returns
undefined
whenconsole.debug
ing the output.Nothing really happens and the calls get through, without being intercepted.
Nothing changes.
My suspicion:
Server actions seem to make use of a RPC architecture.
If I understand correctly, this entails that there is one endpoint which "handles" the different calls and returns values using websockets/streams.
This means that when I intercept the call, the server-action closes said connection, making the server-action throw said "Connection closed" error.
As written previously, this DOES NOT happen with normal
route.js
endpoints and testing proceeds as expected.How could I solve this?
I'm also confused about the use-case of the testmode functionality, as playwright's handler seems to intercept the calls correctly (but maybe just if they are server-actions?).
Tagging people that worked on the experimental testmode:
@ijjk @kevva @samcx @agadzik
Additional information
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions