diff options
6 files changed, 42 insertions, 3 deletions
diff --git a/.changeset/selfish-pianos-notice.md b/.changeset/selfish-pianos-notice.md new file mode 100644 index 000000000..eec21f548 --- /dev/null +++ b/.changeset/selfish-pianos-notice.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes unexpected `undefined` value when calling an action from the client without a return value. diff --git a/packages/astro/e2e/actions-blog.test.js b/packages/astro/e2e/actions-blog.test.js index e3a8c7cf8..b1b5c33ec 100644 --- a/packages/astro/e2e/actions-blog.test.js +++ b/packages/astro/e2e/actions-blog.test.js @@ -125,4 +125,12 @@ test.describe('Astro Actions - Blog', () => { await expect(comments).toBeVisible(); await expect(comments).toContainText(body); }); + + test('Logout action redirects', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/blog/first-post/')); + + const logoutButton = page.getByTestId('logout-button'); + await logoutButton.click(); + await expect(page).toHaveURL(astro.resolveUrl('/blog/')); + }); }); diff --git a/packages/astro/e2e/fixtures/actions-blog/src/actions/index.ts b/packages/astro/e2e/fixtures/actions-blog/src/actions/index.ts index 0588f626c..7b640be51 100644 --- a/packages/astro/e2e/fixtures/actions-blog/src/actions/index.ts +++ b/packages/astro/e2e/fixtures/actions-blog/src/actions/index.ts @@ -3,11 +3,16 @@ import { ActionError, defineAction, z } from 'astro:actions'; import { getCollection } from 'astro:content'; export const server = { + logout: defineAction({ + handler: async () => { + await new Promise((r) => setTimeout(r, 500)); + }, + }), blog: { like: defineAction({ input: z.object({ postId: z.string() }), handler: async ({ postId }) => { - await new Promise((r) => setTimeout(r, 1000)); + await new Promise((r) => setTimeout(r, 500)); const { likes } = await db .update(Likes) @@ -30,7 +35,7 @@ export const server = { body: z.string().min(10), }), handler: async ({ postId, author, body }) => { - if (!(await getCollection('blog')).find(b => b.id === postId)) { + if (!(await getCollection('blog')).find((b) => b.id === postId)) { throw new ActionError({ code: 'NOT_FOUND', message: 'Post not found', diff --git a/packages/astro/e2e/fixtures/actions-blog/src/components/Logout.tsx b/packages/astro/e2e/fixtures/actions-blog/src/components/Logout.tsx new file mode 100644 index 000000000..737718d91 --- /dev/null +++ b/packages/astro/e2e/fixtures/actions-blog/src/components/Logout.tsx @@ -0,0 +1,16 @@ +import { actions } from 'astro:actions'; +import { navigate } from 'astro:transitions/client'; + +export function Logout() { + return ( + <button + data-testid="logout-button" + onClick={async () => { + const { error } = await actions.logout(); + if (!error) navigate('/blog/'); + }} + > + Logout + </button> + ); +} diff --git a/packages/astro/e2e/fixtures/actions-blog/src/pages/blog/[...slug].astro b/packages/astro/e2e/fixtures/actions-blog/src/pages/blog/[...slug].astro index 34c7d5840..ad4aea521 100644 --- a/packages/astro/e2e/fixtures/actions-blog/src/pages/blog/[...slug].astro +++ b/packages/astro/e2e/fixtures/actions-blog/src/pages/blog/[...slug].astro @@ -1,6 +1,7 @@ --- import { type CollectionEntry, getCollection, getEntry } from 'astro:content'; import BlogPost from '../../layouts/BlogPost.astro'; +import { Logout } from '../../components/Logout'; import { db, eq, Comment, Likes } from 'astro:db'; import { Like } from '../../components/Like'; import { PostComment } from '../../components/PostComment'; @@ -39,6 +40,8 @@ const commentPostIdOverride = Astro.url.searchParams.get('commentPostIdOverride' <BlogPost {...post.data}> <Like postId={post.id} initial={initialLikes?.likes ?? 0} client:load /> + <Logout client:load /> + <form> <input type="hidden" name="like" /> <button type="submit" aria-label="get-request">Like GET request</button> diff --git a/packages/astro/templates/actions.mjs b/packages/astro/templates/actions.mjs index 587f6ed9b..5efd31133 100644 --- a/packages/astro/templates/actions.mjs +++ b/packages/astro/templates/actions.mjs @@ -93,7 +93,9 @@ async function handleAction(param, path, context) { body, headers, }); - if (rawResult.status === 204) return; + if (rawResult.status === 204) { + return deserializeActionResult({ type: 'empty', status: 204 }); + } return deserializeActionResult({ type: rawResult.ok ? 'data' : 'error', |