0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

Actions: fix bad action result for actions with empty return value (#11813)

* fix: correctly handle empty action response

* fix(test): add logout button test

* chore: changeset
This commit is contained in:
Ben Holmes 2024-08-22 07:02:48 -04:00 committed by GitHub
parent 4db5c74dd1
commit 3f7630afd6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 42 additions and 3 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fixes unexpected `undefined` value when calling an action from the client without a return value.

View file

@ -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/'));
});
});

View file

@ -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',

View file

@ -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>
);
}

View file

@ -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>

View file

@ -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',