Skip to content

Commit 4741b09

Browse files
authored
test: actions, params and csrf to unit test (#15984)
1 parent c93b4a0 commit 4741b09

28 files changed

Lines changed: 1645 additions & 898 deletions

packages/astro/src/core/app/middlewares.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function createOriginCheckMiddleware(): MiddlewareHandler {
5454
});
5555
}
5656

57-
function hasFormLikeHeader(contentType: string | null): boolean {
57+
export function hasFormLikeHeader(contentType: string | null): boolean {
5858
if (contentType) {
5959
for (const FORM_CONTENT_TYPE of FORM_CONTENT_TYPES) {
6060
if (contentType.toLowerCase().includes(FORM_CONTENT_TYPE)) {

packages/astro/test/actions.test.js

Lines changed: 0 additions & 272 deletions
Original file line numberDiff line numberDiff line change
@@ -49,136 +49,6 @@ describe('Astro Actions', () => {
4949
assert.equal($('body').text().trim(), 'No cookie found.');
5050
});
5151

52-
it('Exposes subscribe action', async () => {
53-
const res = await fixture.fetch('/_actions/subscribe', {
54-
method: 'POST',
55-
body: JSON.stringify({ channel: 'bholmesdev' }),
56-
headers: {
57-
'Content-Type': 'application/json',
58-
},
59-
});
60-
61-
assert.equal(res.ok, true);
62-
assert.equal(res.headers.get('Content-Type'), 'application/json+devalue');
63-
const data = devalue.parse(await res.text());
64-
65-
assert.equal(data.channel, 'bholmesdev');
66-
assert.equal(data.subscribeButtonState, 'smashed');
67-
});
68-
69-
it('Rejects oversized JSON action body', async () => {
70-
const largeActionPayload = JSON.stringify({
71-
channel: 'a'.repeat(2 * 1024 * 1024),
72-
});
73-
const res = await fixture.fetch('/_actions/subscribe', {
74-
method: 'POST',
75-
body: largeActionPayload,
76-
headers: {
77-
'Content-Type': 'application/json',
78-
},
79-
});
80-
81-
assert.equal(res.ok, false);
82-
assert.equal(res.status, 413);
83-
assert.equal(res.headers.get('Content-Type'), 'application/json');
84-
85-
const data = await res.json();
86-
assert.equal(data.code, 'CONTENT_TOO_LARGE');
87-
});
88-
89-
it('Exposes comment action', async () => {
90-
const formData = new FormData();
91-
formData.append('channel', 'bholmesdev');
92-
formData.append('comment', 'Hello, World!');
93-
const res = await fixture.fetch('/_actions/comment', {
94-
method: 'POST',
95-
body: formData,
96-
});
97-
98-
assert.equal(res.ok, true);
99-
assert.equal(res.headers.get('Content-Type'), 'application/json+devalue');
100-
101-
const data = devalue.parse(await res.text());
102-
assert.equal(data.channel, 'bholmesdev');
103-
assert.equal(data.comment, 'Hello, World!');
104-
});
105-
106-
it('Raises validation error on bad form data', async () => {
107-
const formData = new FormData();
108-
formData.append('channel', 'bholmesdev');
109-
const res = await fixture.fetch('/_actions/comment', {
110-
method: 'POST',
111-
body: formData,
112-
});
113-
114-
assert.equal(res.ok, false);
115-
assert.equal(res.status, 400);
116-
assert.equal(res.headers.get('Content-Type'), 'application/json');
117-
118-
const data = await res.json();
119-
assert.equal(data.type, 'AstroActionInputError');
120-
});
121-
122-
it('Exposes plain formData action', async () => {
123-
const formData = new FormData();
124-
formData.append('channel', 'bholmesdev');
125-
formData.append('comment', 'Hello, World!');
126-
const res = await fixture.fetch('/_actions/commentPlainFormData', {
127-
method: 'POST',
128-
body: formData,
129-
});
130-
131-
assert.equal(res.ok, true);
132-
assert.equal(res.headers.get('Content-Type'), 'application/json+devalue');
133-
134-
const data = devalue.parse(await res.text());
135-
assert.equal(data.success, true);
136-
assert.equal(data.isFormData, true, 'Should receive plain FormData');
137-
});
138-
139-
it('Handles special characters in action names', async () => {
140-
for (const name of ['with%2Fslash', 'with%20space']) {
141-
const res = await fixture.fetch(`/_actions/${name}`, {
142-
method: 'POST',
143-
body: JSON.stringify({ name: 'ben' }),
144-
headers: {
145-
'Content-Type': 'application/json',
146-
},
147-
});
148-
assert.equal(res.ok, true);
149-
const text = await res.text();
150-
assert.equal(res.headers.get('Content-Type'), 'application/json+devalue');
151-
const data = devalue.parse(text);
152-
assert.equal(data, 'Hello, ben!');
153-
}
154-
});
155-
156-
it('Returns 404 for nonexistent action', async () => {
157-
const res = await fixture.fetch('/_actions/nonExistent', {
158-
method: 'POST',
159-
body: JSON.stringify({}),
160-
headers: {
161-
'Content-Type': 'application/json',
162-
},
163-
});
164-
assert.equal(res.status, 404);
165-
const data = await res.json();
166-
assert.equal(data.code, 'NOT_FOUND');
167-
});
168-
169-
it('Returns 404 for prototype methods used as action names', async () => {
170-
for (const name of ['constructor', '__proto__', 'toString', 'valueOf']) {
171-
const res = await fixture.fetch(`/_actions/${name}`, {
172-
method: 'POST',
173-
body: JSON.stringify({}),
174-
headers: {
175-
'Content-Type': 'application/json',
176-
},
177-
});
178-
assert.equal(res.status, 404, `Expected 404 for /_actions/${name}`);
179-
}
180-
});
181-
18252
it('Should fail when calling an action without using Astro.callAction', async () => {
18353
const res = await fixture.fetch('/invalid/');
18454
assert.equal(res.status, 500);
@@ -465,37 +335,6 @@ describe('Astro Actions', () => {
465335
assert.equal(data?.age, '42');
466336
});
467337

468-
it('Sets status to 204 when content-length is 0', async () => {
469-
const req = new Request('http://example.com/_actions/fireAndForget', {
470-
method: 'POST',
471-
headers: {
472-
'Content-Length': '0',
473-
},
474-
});
475-
const res = await app.render(req);
476-
assert.equal(res.status, 204);
477-
});
478-
479-
it('Sets status to 204 when content-type is omitted', async () => {
480-
const req = new Request('http://example.com/_actions/fireAndForget', {
481-
method: 'POST',
482-
});
483-
const res = await app.render(req);
484-
assert.equal(res.status, 204);
485-
});
486-
487-
it('Sets status to 415 when content-type is unexpected', async () => {
488-
const req = new Request('http://example.com/_actions/fireAndForget', {
489-
method: 'POST',
490-
body: 'hey',
491-
headers: {
492-
'Content-Type': 'text/plain',
493-
},
494-
});
495-
const res = await app.render(req);
496-
assert.equal(res.status, 415);
497-
});
498-
499338
it('Is callable from the server with rewrite', async () => {
500339
const req = new Request('http://example.com/rewrite');
501340
const res = await app.render(req);
@@ -507,54 +346,6 @@ describe('Astro Actions', () => {
507346
assert.equal($('[data-channel]').text(), 'bholmesdev');
508347
});
509348

510-
it('Returns content when the value is 0', async () => {
511-
const req = new Request('http://example.com/_actions/zero', {
512-
method: 'POST',
513-
headers: {
514-
'Content-Type': 'application/json',
515-
'Content-Length': '0',
516-
},
517-
});
518-
const res = await app.render(req);
519-
assert.equal(res.status, 200);
520-
const value = devalue.parse(await res.text());
521-
assert.equal(value, 0);
522-
});
523-
524-
it('Returns content when the value is false', async () => {
525-
const req = new Request('http://example.com/_actions/false', {
526-
method: 'POST',
527-
headers: {
528-
'Content-Type': 'application/json',
529-
'Content-Length': '0',
530-
},
531-
});
532-
const res = await app.render(req);
533-
assert.equal(res.status, 200);
534-
535-
const value = devalue.parse(await res.text());
536-
assert.equal(value, false);
537-
});
538-
539-
it('Supports complex values: Date, Set, URL', async () => {
540-
const req = new Request('http://example.com/_actions/complexValues', {
541-
method: 'POST',
542-
headers: {
543-
'Content-Type': 'application/json',
544-
'Content-Length': '0',
545-
},
546-
});
547-
const res = await app.render(req);
548-
assert.equal(res.status, 200);
549-
assert.equal(res.headers.get('Content-Type'), 'application/json+devalue');
550-
551-
const value = devalue.parse(await res.text(), {
552-
URL: (href) => new URL(href),
553-
});
554-
assert.ok(value.date instanceof Date);
555-
assert.ok(value.set instanceof Set);
556-
});
557-
558349
it('Supports discriminated union for different form fields', async () => {
559350
const formData = new FormData();
560351
formData.set('type', 'first-chunk');
@@ -587,52 +378,6 @@ describe('Astro Actions', () => {
587378
const dataRest = devalue.parse(await resRest.text());
588379
assert.equal('fake', dataRest?.uploadId);
589380
});
590-
591-
it('Handles special characters in action names', async () => {
592-
for (const name of ['with%2Fslash', 'with%20space']) {
593-
const req = new Request(`http://example.com/_actions/${name}`, {
594-
method: 'POST',
595-
body: JSON.stringify({ name: 'ben' }),
596-
headers: {
597-
'Content-Type': 'application/json',
598-
},
599-
});
600-
const res = await app.render(req);
601-
assert.equal(res.ok, true);
602-
const text = await res.text();
603-
assert.equal(res.headers.get('Content-Type'), 'application/json+devalue');
604-
const data = devalue.parse(text);
605-
assert.equal(data, 'Hello, ben!');
606-
}
607-
});
608-
609-
it('Returns 404 for nonexistent action', async () => {
610-
const req = new Request('http://example.com/_actions/nonExistent', {
611-
method: 'POST',
612-
headers: {
613-
'Content-Type': 'application/json',
614-
},
615-
body: JSON.stringify({}),
616-
});
617-
const res = await app.render(req);
618-
assert.equal(res.status, 404);
619-
const data = await res.json();
620-
assert.equal(data.code, 'NOT_FOUND');
621-
});
622-
623-
it('Returns 404 for prototype methods used as action names', async () => {
624-
for (const name of ['constructor', '__proto__', 'toString', 'valueOf']) {
625-
const req = new Request(`http://example.com/_actions/${name}`, {
626-
method: 'POST',
627-
headers: {
628-
'Content-Type': 'application/json',
629-
},
630-
body: JSON.stringify({}),
631-
});
632-
const res = await app.render(req);
633-
assert.equal(res.status, 404, `Expected 404 for /_actions/${name}`);
634-
}
635-
});
636381
});
637382
});
638383

@@ -718,23 +463,6 @@ it('Should support trailing slash', async () => {
718463
await devServer.stop();
719464
});
720465

721-
it('getActionPath() should return the right path', async () => {
722-
const fixture = await loadFixture({
723-
root: './fixtures/actions/',
724-
adapter: testAdapter(),
725-
base: '/base',
726-
trailingSlash: 'always',
727-
});
728-
const devServer = await fixture.startDevServer();
729-
const res = await fixture.fetch('/base/get-action-path/');
730-
731-
assert.equal(res.ok, true);
732-
const html = await res.text();
733-
let $ = cheerio.load(html);
734-
assert.equal($('[data-path]').text(), '/base/_actions/transformFormInput/');
735-
await devServer.stop();
736-
});
737-
738466
/**
739467
* Follow an expected redirect response.
740468
*

packages/astro/test/astro-class-list.test.js

Lines changed: 0 additions & 63 deletions
This file was deleted.

0 commit comments

Comments
 (0)