Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

はじめてのE2Eテストを作成する #42

Merged
merged 52 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
96010f7
conflict の解消
kazuma-naka Jan 8, 2025
28eff69
.env.local にEMAIL と PASSWORD を設定する手順をREADME に記載する
kazuma-naka Jan 5, 2025
0c04a73
ログインに失敗したときのテストも作成する
kazuma-naka Jan 5, 2025
1342460
script の conflict を解消
kazuma-naka Jan 8, 2025
cea11dd
dotenv を devDependencies に移動する
kazuma-naka Jan 6, 2025
144ab6d
package.json を修正する
kazuma-naka Jan 8, 2025
08e520d
npm run e2e で playwright が実行されるように修正する
kazuma-naka Jan 13, 2025
5dcb45d
Login と SignUp ページの pjord.svg の Image 内の height が設定されておらずエラーが起こるバグの修正
kazuma-naka Jan 13, 2025
6e8c23e
playwright を headless モードで実行するように修正する
kazuma-naka Jan 13, 2025
cc72100
開発環境の EMAIL と PASSWORD を隠さずにテストファイル内に定義する
kazuma-naka Jan 13, 2025
7edf3c8
npx playwright test のように npx を先頭につける
kazuma-naka Jan 13, 2025
bef31f5
CI のテストの修正. npm run test の前に npx playwright intall を実行する
kazuma-naka Jan 13, 2025
a97a415
test CI が通るようにテスト前に supabase, Next.js を起動する
kazuma-naka Jan 13, 2025
ab8a0a5
Playwright の公式ページを参考にテストの WorkFlow を修正
kazuma-naka Jan 13, 2025
4c6c4b7
test CI が通るようにテスト前に supabase, Next.js を起動する
kazuma-naka Jan 13, 2025
7eee630
test CI が通るようにテスト前に supabase, Next.js を起動する. Next.js が起動したら次の処理に移行する
kazuma-naka Jan 13, 2025
eac3386
npx wait-on localhost:3000 を削除する
kazuma-naka Jan 13, 2025
eb0d2e6
playwright.config の webServer のアンコメントを取り除く
kazuma-naka Jan 14, 2025
501ce1f
playwright を起動する際に Next.js をビルドしないとエラーが出るので Next.js をe2e テスト前にビルドするように修正
kazuma-naka Jan 14, 2025
6900b45
dotenv cli をインストールして supabase のURL と Anon Key をテスト時に読み込む
kazuma-naka Jan 14, 2025
da86d06
next build 時に .env を CI 環境で読み込むように修正
kazuma-naka Jan 14, 2025
ef14fc4
.env.local はリモートに含まれないため dotenv-cli を依存性から外す
kazuma-naka Jan 14, 2025
41a0126
ci.yml の test 内で Next.js をビルドするために .env.local を動的に作成する
kazuma-naka Jan 16, 2025
825d720
ci.yml の npm run start をバックグラウンドで実行する
kazuma-naka Jan 16, 2025
511ab84
seed.test.sql を作成してテスト環境のDBを構築する
kazuma-naka Jan 19, 2025
88678fd
seed.test.sql の path を設定する
kazuma-naka Jan 19, 2025
5a155a7
seed.test.sql の path を変更する
kazuma-naka Jan 19, 2025
9269167
seed.test.sql のタイポを修正
kazuma-naka Jan 19, 2025
ab67c7b
E2E テスト後に DB をリセットする
kazuma-naka Jan 19, 2025
ea65df4
E2E テスト後の処理のタイポを修正
kazuma-naka Jan 19, 2025
b5246d0
ci.yml のテーブルの一括削除の記述を消す
kazuma-naka Jan 20, 2025
a85d06e
global.setup.ts でテスト用のユーザーをサインアップして新規登録する
kazuma-naka Jan 20, 2025
d6cf2e8
[email protected] のユーザーをテストのために新規作成、テスト後に削除する
kazuma-naka Jan 20, 2025
b451d4f
service role key を ci のテスト環境でも.env.local に追加する
kazuma-naka Jan 20, 2025
9b8d07c
.env.local の変数 NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY に名前を変更する
kazuma-naka Jan 20, 2025
c0f43c9
ci.yml NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEYに修正
kazuma-naka Jan 20, 2025
527a40d
テスト用ユーザーの作成の実装をやめて元に戻す
kazuma-naka Jan 21, 2025
3e79739
E2E テスト用の DB のコンテナを別に用意する
kazuma-naka Jan 21, 2025
25ce5fb
setup.ts, teardown.ts playwright の設定を削除
kazuma-naka Jan 23, 2025
b285068
e2e 用の supabase の環境をローカルに構築する
kazuma-naka Jan 24, 2025
a9870f2
supabase を clone してローカルに構築する
kazuma-naka Jan 29, 2025
980cd0d
Supabase を git clone でローカル環境に構築することをキャンセルする
kazuma-naka Jan 30, 2025
3c248c2
supawright を使ってE2Eテストを実装する
kazuma-naka Jan 31, 2025
26f99ba
Supawright を追加
kazuma-naka Feb 3, 2025
1b7114b
Supawright をつかってテスト前にユーザーを作成する。Supawright は自動的にテスト内で作成されたテーブル、ユーザーを削除
kazuma-naka Feb 5, 2025
43a43d8
e2e テストとコンポネントテストを npm run test で両方とも実行するようにする
kazuma-naka Feb 6, 2025
7857c23
.env.test ファイルを削除
kazuma-naka Feb 6, 2025
52ede0c
不必要なものを .gitignore から削除する
kazuma-naka Feb 6, 2025
bd8ccc5
dotenv-cli を削除する
kazuma-naka Feb 6, 2025
04e64f5
supawright の createUser() で email を自動的に生成してくれるので生成された email を使用する
kazuma-naka Feb 6, 2025
e488be3
ci.yml の不必要な変数を削除
kazuma-naka Feb 6, 2025
02feb22
モデルの2重管理を解消
kazuma-naka Feb 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,35 @@ jobs:

test:
needs: setup
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
with:
node-version: ${{ env.NODE_VERSION }}
- run: npx playwright install --with-deps
- run: npx supabase start
- run: npx supabase db reset
- name: Generate .env.local for test environment
run: |
STATUS_OUTPUT=$(npx supabase status)
API_URL=$(echo "$STATUS_OUTPUT" | grep "API URL:" | awk '{print $3}')
ANON_KEY=$(echo "$STATUS_OUTPUT" | grep "anon key:" | awk '{print $3}')
echo "NEXT_PUBLIC_SUPABASE_URL=$API_URL" > .env.local
echo "NEXT_PUBLIC_SUPABASE_ANON_KEY=$ANON_KEY" >> .env.local
- run: npm run build
- run: npm run start &
- name: Wait Front Response
run: |
curl --retry 5 --max-time 5 http://localhost:3000
- name: Install PostgreSQL Client
run: sudo apt update && sudo apt install -y postgresql-client
- run: npm run test





- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30

5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
206 changes: 206 additions & 0 deletions e2e/database.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
export type Json =
| string
| number
| boolean
| null
| { [key: string]: Json | undefined }
| Json[]

export type Database = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: モデルが二重管理になっていますが、このファイルって必要でしょうか?
src/lib/database.types をimportしてもテストは動作していそうです。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/libのほうをimportすると Type 'Database' does not satisfy the constraint 'GenericDatabase'. というエラーになるんですが、もしかして型定義が古いためですか? このE2Eのほうをsrc/lib/の方で使えばよさそう

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

レビューありがとうございます😊
Supawright を使用するために Supabase の型のタイプを変更する必要がありました。
src/lib/databaase.types.ts に変更しました。

https://github.com/isaacharrisholt/supawright#:~:text=%2D%20export%20interface%20Database%20%7B%0A%2B%20export%20type%20Database%20%3D%20%7B

graphql_public: {
Tables: {
[_ in never]: never
}
Views: {
[_ in never]: never
}
Functions: {
graphql: {
Args: {
operationName?: string
query?: string
variables?: Json
extensions?: Json
}
Returns: Json
}
}
Enums: {
[_ in never]: never
}
CompositeTypes: {
[_ in never]: never
}
}
public: {
Tables: {
companies: {
Row: {
created_at: string
id: number
memo: string | null
name: string
website: string | null
}
Insert: {
created_at?: string
id?: number
memo?: string | null
name: string
website?: string | null
}
Update: {
created_at?: string
id?: number
memo?: string | null
name?: string
website?: string | null
}
Relationships: []
}
users: {
Row: {
date_of_birth: string | null
email: string
first_name: string | null
first_name_kana: string | null
id: string
last_name: string | null
last_name_kana: string | null
role: string | null
}
Insert: {
date_of_birth?: string | null
email: string
first_name?: string | null
first_name_kana?: string | null
id: string
last_name?: string | null
last_name_kana?: string | null
role?: string | null
}
Update: {
date_of_birth?: string | null
email?: string
first_name?: string | null
first_name_kana?: string | null
id?: string
last_name?: string | null
last_name_kana?: string | null
role?: string | null
}
Relationships: []
}
}
Views: {
[_ in never]: never
}
Functions: {
[_ in never]: never
}
Enums: {
[_ in never]: never
}
CompositeTypes: {
[_ in never]: never
}
}
}

type PublicSchema = Database[Extract<keyof Database, "public">]

export type Tables<
PublicTableNameOrOptions extends
| keyof (PublicSchema["Tables"] & PublicSchema["Views"])
| { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] &
Database[PublicTableNameOrOptions["schema"]]["Views"])
: never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
? (Database[PublicTableNameOrOptions["schema"]]["Tables"] &
Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends {
Row: infer R
}
? R
: never
: PublicTableNameOrOptions extends keyof (PublicSchema["Tables"] &
PublicSchema["Views"])
? (PublicSchema["Tables"] &
PublicSchema["Views"])[PublicTableNameOrOptions] extends {
Row: infer R
}
? R
: never
: never

export type TablesInsert<
PublicTableNameOrOptions extends
| keyof PublicSchema["Tables"]
| { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"]
: never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends {
Insert: infer I
}
? I
: never
: PublicTableNameOrOptions extends keyof PublicSchema["Tables"]
? PublicSchema["Tables"][PublicTableNameOrOptions] extends {
Insert: infer I
}
? I
: never
: never

export type TablesUpdate<
PublicTableNameOrOptions extends
| keyof PublicSchema["Tables"]
| { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"]
: never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends {
Update: infer U
}
? U
: never
: PublicTableNameOrOptions extends keyof PublicSchema["Tables"]
? PublicSchema["Tables"][PublicTableNameOrOptions] extends {
Update: infer U
}
? U
: never
: never

export type Enums<
PublicEnumNameOrOptions extends
| keyof PublicSchema["Enums"]
| { schema: keyof Database },
EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicEnumNameOrOptions["schema"]]["Enums"]
: never = never,
> = PublicEnumNameOrOptions extends { schema: keyof Database }
? Database[PublicEnumNameOrOptions["schema"]]["Enums"][EnumName]
: PublicEnumNameOrOptions extends keyof PublicSchema["Enums"]
? PublicSchema["Enums"][PublicEnumNameOrOptions]
: never

export type CompositeTypes<
PublicCompositeTypeNameOrOptions extends
| keyof PublicSchema["CompositeTypes"]
| { schema: keyof Database },
CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
schema: keyof Database
}
? keyof Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"]
: never = never,
> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database }
? Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName]
: PublicCompositeTypeNameOrOptions extends keyof PublicSchema["CompositeTypes"]
? PublicSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions]
: never

62 changes: 62 additions & 0 deletions e2e/login_then_logout.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { describe } from "node:test";
import { expect } from "@playwright/test";
import { withSupawright } from "supawright";
import type { Database } from "./database.types";

const test = withSupawright<Database, "public">(["public"]);

describe("Login and Logout E2E test", () => {
let validEmail: string | undefined;
const e2ePassword = "e2e_password";

test.beforeEach(async ({ supawright }) => {
const attributes = {
password: e2ePassword,
email_confirm: true,
};
const user = await supawright.createUser(attributes);
validEmail = user.email;
});

test("Should Success Login with valid Email and Password then Logout", async ({
page,
}) => {
await page.goto("http://localhost:3000/");
await page.getByRole("link", { name: "ログイン" }).click();

console.log(`valid email: ${validEmail}`);

await page.getByPlaceholder("[email protected]").fill(validEmail ?? "");
await page.getByLabel("Password").fill(e2ePassword);
await page.getByRole("button", { name: "ログイン" }).click();

const logoutButton = page.getByRole("link", { name: "ログアウト" });
await expect(logoutButton).toBeVisible();

/** 現在リロードしないと画面が更新されずログイン、サインインが表示されない **/
await logoutButton.click();
await page.waitForTimeout(1500);

await page.reload();

const loginButton = page.getByRole("link", { name: "ログイン" });
const signInButton = page.getByRole("link", { name: "ユーザー登録" });

await expect(loginButton).toBeVisible();
await expect(signInButton).toBeVisible();
});

test("Should Fail Login with Invalid Email and Password", async ({
page,
}) => {
await page.goto("http://localhost:3000/");
await page.getByRole("link", { name: "ログイン" }).click();

await page.getByPlaceholder("[email protected]").fill("[email protected]");
await page.getByLabel("Password").fill("invalidpassword");
await page.getByRole("button", { name: "ログイン" }).click();

const loginButton = page.getByRole("button", { name: "ログイン" });
await expect(loginButton).toBeVisible();
});
});
1 change: 1 addition & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const config: Config = {
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
},
testPathIgnorePatterns: ["/e2e/"],
};

export default createJestConfig(config);
Loading