Cypress and NextJS using React Server Actions
I'm trying to intercept the client side request that's done by React Server Components for my tests in Cypress.
I thought it should be as simple as looking at and copying the request response (including headers) in the network tab and copy that to Cypress' intercept
function, but I keep getting the error Connection closed
and the request result in my front end code logs undefined
.
Any ideas?
My current intercept
implementation in my Cypress test:
cy.intercept("POST", "/account/register", {
statusCode: 200,
headers: {
"x-action-revalidated": "[[],0,0]",
"content-type": "text/x-component",
},
body: `0:["$@1",["development",null]]\n1:{"result":"success","status":200,"data":{"id":"91ffe221-ace9-40a1-98d5-2851cb071cbd","name":"Test User","email":"[email protected]","createdAt":"$D2024-05-26T16:32:11.280Z","updatedAt":"$D2024-05-26T14:32:11.288Z"}}`,
}).as("registerRequest");
The error message in my console:
index-3fe21bb9.js:133640 Error: The following error originated from your application code, not from Cypress. It was caused by an unhandled promise rejection.
> Connection closed.
When Cypress detects uncaught errors originating from your application it will automatically fail the current test.
This behavior is configurable, and you can choose to turn this off by listening to the `uncaught:exception` event.
at close (webpack-internal:///app-pages-browser/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:2131:31)
at progress (webpack-internal:///app-pages-browser/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:2148:7)
From previous event:
at Promise.longStackTracesCaptureStackTrace [as _captureStackTrace] (http://localhost:3000/__cypress/runner/cypress_runner.js:3486:19)
at Promise._then (http://localhost:3000/__cypress/runner/cypress_runner.js:1239:17)
at Promise._passThrough (http://localhost:3000/__cypress/runner/cypress_runner.js:4110:17)
at Promise.lastly.Promise.finally (http://localhost:3000/__cypress/runner/cypress_runner.js:4119:17)
at Object.onRunnableRun (http://localhost:3000/__cypress/runner/cypress_runner.js:162793:53)
at $Cypress.action (http://localhost:3000/__cypress/runner/cypress_runner.js:41042:28)
at Runnable.run (http://localhost:3000/__cypress/runner/cypress_runner.js:145381:13)
at Runner.runTest (http://localhost:3000/__cypress/runner/cypress_runner.js:155323:10)
at http://localhost:3000/__cypress/runner/cypress_runner.js:155449:12
at next (http://localhost:3000/__cypress/runner/cypress_runner.js:155232:14)
at http://localhost:3000/__cypress/runner/cypress_runner.js:155242:7
at next (http://localhost:3000/__cypress/runner/cypress_runner.js:155144:14)
at http://localhost:3000/__cypress/runner/cypress_runner.js:155210:5
at timeslice (http://localhost:3000/__cypress/runner/cypress_runner.js:145721:27)
Answer
I've figured it out. There are two things to note when intercepting and returning a custom response for a React Server Action request:
- Make sure the header
Content-Type: "text/x-component"
is present on the response - Make sure the response body has a new line on the end of the content
The second one is what I was missing.
This example interception does work:
cy.intercept("POST", "/account/register", {
headers: {
"content-type": "text/x-component",
},
body: `0:["$@1",["development",null]]\n1:{"result":"success","status":200,"data":{"id":"982310j2","name":"Test User","email":"[email protected]","createdAt":"$D2024-05-26T16:32:11.280Z","updatedAt":"$D2024-05-26T14:32:11.288Z"}}\n`,
}).as("registerRequest");
I published a repository example cypress test using React Server Actions, so if anyone still has problems with mocking the response of a server action in cypress, they can look at my implementation here: https://github.com/terrabythia/cypress-server-action-test-example