0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Playwright component testでログイン状態をテストする方法

0
Posted at

はじめに

playwrightの実験的機能であるコンポーネントテストでの、ログイン状態の再現について他に類似する記事が存在しなかったため、備忘録として残させていただきます。

以下の内容はclient componentでのみ動作の確認が取れています。

環境

  • React 19.0.0
  • Next.js 15.1.6
  • Auth.js 5.0.0-beta.25
  • @playwright/experimental-ct-react 1.50.1
  • @playwright/test 1.50.1

client componentでのsessionの取得例

セッションを取得したいコンポーネントをSessionProviderで囲む

layout

/app/layout.tsx
import { SessionProvider } from "next-auth/react";
import { ClientComponent } from "@/app/ui/ClientComponent"

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <SessionProvider>
      <html lang="ja">
        <body>
          <ClientComponent />
          {children}
        </body>
      </html>
    </SessionProvider>
  );
}

client components

app/ui/ClientComponent.tsx
"use client"
import { useSession } from "next-auth/react"
 
export default function ClientComponent() {
  const { data: session } = useSession()
  // ログイン状況に応じて、Sessionもしくはnullが返却される
 
  if (session) {
    return <p>under signin</p>
  }
 
  return <p>You are not authenticated</p>
}

上記のようなコンポーネントにおいてセッションを取得する際、/api/auth/sessionへのリクエストが発生し、json形式にてsession情報が返却されます

component testにおける対応

以下の2点の対応が必要です

  • /api/auth/sessionへのリクエストへのモック実装
  • /playwright/index.tsxへのSessionProviderの追加

モック実装

playwirghtのモック機能を利用し対応
複数のテストファイル間で利用するためヘルパーとして実装

tests/__helpers__/signin.ts
import { Page } from "@playwright/test";
import type { Session } from "next-auth";

export const mockClientSession = async (page: Page, json: Session | null) => {
  await page.route("*/**/api/auth/session", async (route) => {
    await route.fulfill({ json, contentType: "application/json" });
  });
};

/playwright/index.tsx

/playwright/index.tsx
import { beforeMount } from "@playwright/experimental-ct-react/hooks";
import { AppRouterCacheProvider } from "@mui/material-nextjs/v15-appRouter";

import theme from "@/theme";
import { SessionProvider } from "next-auth/react";

beforeMount(({ App }) => {
  return Promise.resolve(
    <SessionProvider>
      <App />
    </SessionProvider>,
  );
});

実際のテストでの利用

tests/ClinentComponent.spec.tsx
import { test, expect } from "@playwright/experimental-ct-react";
import ClientComponent from "@/app/ui/ClientComponent";
import { mockClientSession } from "./__helpers__/signin";

test.describe("Drawer", () => {
  test.describe("before login", () => {
    test.beforeEach(async ({ page }) => {
      // ログアウト状態の場合はnullを渡す
      await mockClientSession(page, null);
    });

    test("should allow me to show not authenticated text", async ({ mount }) => {
      const component = await mount(<ClientComponent />);
      
      const text = await page.getByRole("paragraph", {
        name: "You are not authenticated" 
      });
      await expect(text).toBeVisible();
    });
  });
  
  test.describe("after login", () => {
    test.beforeEach(async ({ page }) => {
      const json = {
        user: {
          name: "testuser",
          email: "test_user@example.com",
          picture: "https://avatars.githubusercontent.com/u/000000",
          nickname: "test nickname",
        },
        expires: "dummy",
        idToken: "dummy",
      };
      await mockClientSession(page, json);
    });
    
    test("should allow me to show authenticated text", async ({ mount }) => {
       const component = await mount(<ClientComponent />);
      
      const text = await page.getByRole("paragraph", {
        name: "under signin" 
      });
      await expect(text).toBeVisible();
    });
  });
});

上記のように対応することでコンポーネントテストにおいてログイン、ログアウト状態それぞれのテストを実施することができました

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?