Skip to content

Commit cfe3e12

Browse files
authored
test: test action returning components (#503)
1 parent 6e08bf3 commit cfe3e12

File tree

5 files changed

+79
-0
lines changed

5 files changed

+79
-0
lines changed

packages/react-server/examples/basic/e2e/basic.test.ts

+13
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,19 @@ test("ReactDom.useFormStatus", async ({ page }) => {
671671
await page.getByText("pending: false").click();
672672
});
673673

674+
test("action returning component", async ({ page }) => {
675+
await page.goto("/test/action");
676+
await waitForHydration(page);
677+
await page
678+
.getByTestId("action-return-component")
679+
.getByRole("button", { name: "Action" })
680+
.click();
681+
await page.getByText("[server] Loading...").click();
682+
await page.getByRole("button", { name: "[client] counter: 0" }).click();
683+
await page.getByRole("button", { name: "[client] counter: 1" }).click();
684+
await page.getByText("[server] OK!").click();
685+
});
686+
674687
test("use client > virtual module", async ({ page }) => {
675688
await page.goto("/test/deps");
676689
await page.getByText("TestVirtualUseClient").click();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"use server";
2+
3+
import { sleep } from "@hiogawa/utils";
4+
import React from "react";
5+
import { TestClientComponent } from "./_client2";
6+
7+
export async function actionReturnComponent() {
8+
return (
9+
<>
10+
<div>
11+
<TestClientComponent />
12+
</div>
13+
<div className="border px-2">
14+
[server]{" "}
15+
<React.Suspense fallback={"Loading..."}>
16+
<TestServerComponent />
17+
</React.Suspense>
18+
</div>
19+
</>
20+
);
21+
}
22+
23+
async function TestServerComponent() {
24+
await sleep(1000);
25+
return <>OK!</>;
26+
}

packages/react-server/examples/basic/src/routes/test/action/_client.tsx

+23
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
nonFormAction,
1313
slowAction,
1414
} from "./_action";
15+
import { actionReturnComponent } from "./_action2";
1516

1617
export function Chat(props: { messages: ReturnType<typeof getMessages> }) {
1718
// cf. https://react.dev/reference/react/useOptimistic#optimistically-updating-with-forms
@@ -203,3 +204,25 @@ function formDataToJson(data: FormData) {
203204
});
204205
return result;
205206
}
207+
208+
export function TestActionReturnComponent() {
209+
const [node, setNode] = React.useState<React.ReactNode>(null);
210+
return (
211+
<div
212+
className="flex flex-col gap-2 items-start"
213+
data-testid="action-return-component"
214+
>
215+
<h3 className="font-bold">TestActionReturnComponent</h3>
216+
<div className="flex items-center gap-2">
217+
<form
218+
action={async () => {
219+
setNode(await actionReturnComponent());
220+
}}
221+
>
222+
<button className="antd-btn antd-btn-default px-2">Action</button>
223+
</form>
224+
Result: {node ?? "(none)"}
225+
</div>
226+
</div>
227+
);
228+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use client";
2+
3+
import React from "react";
4+
5+
export function TestClientComponent() {
6+
const [count, setCount] = React.useState(0);
7+
return (
8+
<button
9+
className="antd-btn antd-btn-default px-2"
10+
onClick={() => setCount((c) => c + 1)}
11+
>
12+
[client] counter: {count}
13+
</button>
14+
);
15+
}

packages/react-server/examples/basic/src/routes/test/action/page.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
ClientActionBindTest,
1212
FormStateTest,
1313
NonFormActionTest,
14+
TestActionReturnComponent,
1415
} from "./_client";
1516

1617
export default async function Page() {
@@ -29,6 +30,7 @@ export default async function Page() {
2930
<div data-testid="action-bind">{getActionBindResult()}</div>
3031
</div>
3132
<FormStateTest />
33+
<TestActionReturnComponent />
3234
</div>
3335
);
3436
}

0 commit comments

Comments
 (0)