[🐞] Error: Actions can not be invoked within the server during SSR.
Which component is affected?
Qwik Runtime
Describe the bug
When attempting to vitest a component that invokes a routeAction$ I'm getting the error:
Error: Actions can not be invoked within the server during SSR.
Action.run() can only be called on the browser, for example when a user clicks a button, or submits a form.
at Proxy.routeActionQrl_action_submit_A5bZC7WO00A
I thought that vitest would render using the node environment and thus SSR and I could mock out the HTTP API call that my action is ultimately making. This is not the case though and I can't find any good documentation on how to do this.
test('Should successfully remove users', async () => {
const Wrapper = component$(() => {
const removeDialogRef = useSignal<HTMLElement>();
const onClose$ = $(onCloseSpy);
return (
<QwikCityMockProvider>
<RemoveUsers
ref={removeDialogRef}
selectedUsers={selectedUsers}
close={onClose$}
/>
</QwikCityMockProvider>
);
});
const { render, userEvent } = await createDOM();
await render(<Wrapper />);
await userEvent('.vi-submit-remove', 'click');
});
Where within the RemoveUsers component it calls action.submit(data as unknown as FormData) which ultimately makes an HTTP POST call.
Reproduction
http://no.repro.url
Steps to reproduce
No response
System Info
System:
OS: macOS 14.3.1
CPU: (20) arm64 Apple M1 Ultra
Memory: 212.80 MB / 64.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.10.0 - ~/.nvm/versions/node/v20.10.0/bin/node
npm: 10.2.3 - ~/.nvm/versions/node/v20.10.0/bin/npm
bun: 1.0.7 - /opt/homebrew/bin/bun
Browsers:
Chrome: 113.0.5672.126
Safari: 17.3.1
npmPackages:
@builder.io/qwik: ^1.4.3 => 1.4.3
@builder.io/qwik-auth: 0.1.3 => 0.1.3
@builder.io/qwik-city: ^1.4.3 => 1.4.3
@builder.io/qwik-react: 0.5.0 => 0.5.0
undici: 5.28.2 => 5.28.2
vite: 5.0.12 => 5.0.12
Additional Information
No response
Hmm, so the QwikCityMockProvider should somehow make it so that actions run locally? Or should they be mocked entirely?
Sounds feasible but needs a good think about the API. PRs very welcome.
That's correct, in this context I'd want to mock the fetch calls for testing, however that doesn't mean there isn't a scenario in which one would want the action to run as normal as well.
@wmertens Help me understand the QwikCityMockProvider. If I look at https://github.com/QwikDev/qwik/blob/main/packages/qwik-city/runtime/src/qwik-city-component.tsx#L130 and https://github.com/QwikDev/qwik/blob/main/packages/qwik-city/runtime/src/qwik-city-component.tsx#L578 the actionState is added as a context so theoretically actions should be able to be called. If I look at the error itself it happens here and I assume the error is thrown because HTMLFormElement is not available from a SSR based action call.
Can you provide more thoughts on how this would be implemented? I'm happy to do some work here but I need to understand what exactly is missing and what needs to be either mocked out or filled it, in isn't exactly clear.
The huge windfall here would be the ability to rapidly test one's app with mocked data. The speed we could test if this was in place would be an order of magnitude faster vs cypress or playwright or any of the e2e testing libraries.
@wmertens I believe i've found a creative way to resolve this issue. I have a PR out for this (#7606 ). Can this issue be assigned to me?
@Matt-Williams1 so it looks like the problem is that the test is running code that is built for the server. That's wrong, even if it's running in node.
What should happen is that this test code runs the client build, and there's a bridge behind the scenes that lets actions work.
However, @thejackshelton has been working on vitest browser mode and it looks to be way faster than playwright right now, and then there's no flaky workarounds needed