Playwright – 期望错误 – 如何处理?

huangapple go评论110阅读模式
英文:

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:

  1. on the homepage: http://localhost:3000/ it checks if the user is
    validated (has the token in the cookies)
  2. If yes, then it shows the normal pages
  3. 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 fine
  • page.waitForSelector locator('text="Unauthorized"') also works fine (the log says locator resolved to visible <p>Unauthorized</p>)
  • however in the previous page.waitForSelector locator('text="Unauthorized"') if I go to the Console tab, I see Failed 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.

huangapple
  • 本文由 发表于 2023年6月27日 19:11:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76564267.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定