英文:
Playwright - expect error - how to do it?
问题
I'll provide a summary of the issue and possible solutions for your Playwright test:
Issue:
Your Playwright test is failing due to a network error when trying to access a resource with a status of 401 (Unauthorized). This is expected behavior because your application redirects unauthorized users to /login
using the useMe
hook.
Solution:
To handle this situation in your Playwright test, you can use Playwright's route interception feature to intercept network requests and control their responses. Here's a basic example of how you can modify your test to handle this:
import { test, expect } from "@playwright/test";
test("unauthorized users should be redirected to /login", async ({ page }) => {
// Intercept network requests to "/users/me"
await page.route("**/users/me", (route) => {
// Simulate a 401 response for the "/users/me" request
route.fulfill({
status: 401,
body: "Unauthorized",
});
});
// Go to the homepage
await page.goto("/");
// Wait for the redirection to /login
await page.waitForURL("/login");
// Verify that the page has been redirected to /login
const url = page.url();
expect(url).toBe("/login");
});
In this modified test, we intercept the network request to /users/me
and simulate a 401 response, which should trigger the redirect to /login
. Then, we wait for the URL to change to /login
and assert that it has redirected correctly.
This approach allows you to test the behavior of your application when handling unauthorized users without encountering the network error.
Make sure to adjust the code as needed to fit your specific Playwright setup and application structure.
英文:
I am writing my first e2e tests in Playwright. Before I was using Cypress.
This is a Next.js app.
I have an app that:
- on the homepage: http://localhost:3000/ it checks if the user is
validated (has the token in the cookies) - If yes, then it shows the normal pages
- If not, it redirects the user to the /login
This is controlled in the _app.tsx
file with Authguard:
const AuthGuard = ({ children }: { children: React.ReactNode }) => {
const { isLoading, isValidating, error } = useMe();
if (isLoading || isValidating) return <Spinner belowText="Loading..." />;
if (error) {
if (error.response && error.response.status === 401)
return <Spinner belowText="Unauthorized" />;
if (!error.response && error.code === "ERR_NETWORK")
return (
<Spinner belowText="Network error. Check if you are connected to the VPN" />
);
return <p>Unknown error, redirecting to login...</p>;
}
return <>{children}</>;
};
...
const isAuthRequired = Component.auth ?? true;
...
<EmotionThemeProvider theme={theme}>
<CssBaseline />
{isAuthRequired ? (
<AuthGuard>
<Component {...pageProps} />
</AuthGuard>
) : (
<Component {...pageProps} />
)}
</EmotionThemeProvider>
...
And this is my test:
import { test } from "@playwright/test";
test("unauthorized users should be redirected to /login", async ({ page }) => {
// Go to the homepage
await page.goto("/");
// Wait for the Unauthorized spinner
const spinner = await page.waitForSelector('text="Unauthorized"', { timeout: 10000 });
// Verify that the spinner was found
if (spinner) {
// Check that the page has been redirected to /login
const url = page.url();
expect(url).toContain("/login");
} else {
throw new Error('Unauthorized spinner not found');
}
});
The problem I am facing is:
When I run npx playwright test --ui
I see that:
page.goto /
works finepage.waitForSelector locator('text="Unauthorized"')
also works fine (the log sayslocator resolved to visible <p>Unauthorized</p>
)- however in the previous
page.waitForSelector locator('text="Unauthorized"')
if I go to the Console tab, I seeFailed to load resource: the server responded with a status of 401 (Unauthorized)
which is normal, because the user is not logged in yet.
The test should not fail. Should redirect to /login
and PASS. But the test fails because of that network error.
The hook useMe
is the one that makes the redirect to /login
:
const useMe = () => {
const router = useRouter();
return useSWR(
"/users/me",
(url: string) => axios.get<MeResponse>(url).then((res) => res.data),
{
revalidateOnFocus: false,
onError: () => {
router.push("/login");
},
}
);
};
export { useMe };
How can I solve this?
答案1
得分: 0
使用toHaveURL断言。
await expect(page).toHaveURL(/.*login/);
这样它会等待URL重定向并在更改之前不会立即验证URL。
英文:
> How to wait for url to redirect and then verify?
Use toHaveURL assertion.
await expect(page).toHaveURL(/.*login/)
;
So that it will wait for url to redirect and does not verify the url immediately before the change.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论