Skip to content

Commit fc3c2ca

Browse files
committed
e2e: hardening by accepting both 200 and 204 for article/comments deletion
1 parent ca2a97d commit fc3c2ca

2 files changed

Lines changed: 72 additions & 0 deletions

File tree

e2e/articles.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,42 @@ test.describe('Articles', () => {
8282
await expect(page.locator(`h1:has-text("${article.title}")`)).not.toBeVisible();
8383
});
8484

85+
/**
86+
* Verifies the frontend handles HTTP 200 for article deletion.
87+
*
88+
* The RealWorld spec uses 204 No Content for DELETE operations, which is
89+
* semantically correct (success with no response body). However, HTTP clients
90+
* should accept ANY 2XX status as success per RFC 9110.
91+
*
92+
* This test mocks a 200 response to verify the frontend doesn't break when
93+
* an implementation returns 200 instead of 204. This is good engineering
94+
* practice: clients should handle status code classes, not specific codes.
95+
*/
96+
test('should delete an article when server returns 200 instead of 204', async ({ page }) => {
97+
const article = generateUniqueArticle();
98+
99+
await createArticle(page, article);
100+
101+
// Intercept DELETE requests and respond with 200 instead of 204
102+
await page.route('**/api/articles/*', async route => {
103+
if (route.request().method() === 'DELETE') {
104+
await route.fulfill({
105+
status: 200,
106+
contentType: 'application/json',
107+
body: JSON.stringify({}),
108+
});
109+
} else {
110+
await route.continue();
111+
}
112+
});
113+
114+
// Delete the article
115+
await deleteArticle(page);
116+
117+
// Should be redirected to home (frontend should handle 200 the same as 204)
118+
await expect(page).toHaveURL('/');
119+
});
120+
85121
test('should favorite an article', async ({ page }) => {
86122
// Use an existing article from the demo backend (can't favorite own articles)
87123
// Go to global feed to see all articles

e2e/comments.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,42 @@ test.describe('Comments', () => {
4545
await expect(page.locator(`.card:not(.comment-form) .card-block:has-text("${commentText}")`)).not.toBeVisible();
4646
});
4747

48+
/**
49+
* Verifies the frontend handles HTTP 200 for comment deletion.
50+
*
51+
* The RealWorld spec uses 204 No Content for DELETE operations, which is
52+
* semantically correct (success with no response body). However, HTTP clients
53+
* should accept ANY 2XX status as success per RFC 9110.
54+
*
55+
* This test mocks a 200 response to verify the frontend doesn't break when
56+
* an implementation returns 200 instead of 204. This is good engineering
57+
* practice: clients should handle status code classes, not specific codes.
58+
*/
59+
test('should delete comment when server returns 200 instead of 204', async ({ page }) => {
60+
const commentText = 'Comment to test 200 status';
61+
await addComment(page, commentText);
62+
// Comment should be visible
63+
await expect(page.locator(`.card:not(.comment-form) .card-block:has-text("${commentText}")`)).toBeVisible();
64+
65+
// Intercept DELETE requests to comments and respond with 200 instead of 204
66+
await page.route('**/api/articles/*/comments/*', async route => {
67+
if (route.request().method() === 'DELETE') {
68+
await route.fulfill({
69+
status: 200,
70+
contentType: 'application/json',
71+
body: JSON.stringify({}),
72+
});
73+
} else {
74+
await route.continue();
75+
}
76+
});
77+
78+
// Delete the comment
79+
await deleteComment(page, commentText);
80+
// Comment should no longer be visible (frontend should handle 200 the same as 204)
81+
await expect(page.locator(`.card:not(.comment-form) .card-block:has-text("${commentText}")`)).not.toBeVisible();
82+
});
83+
4884
test('should display multiple comments', async ({ page }) => {
4985
const comment1 = 'First comment';
5086
const comment2 = 'Second comment';

0 commit comments

Comments
 (0)