Skip to content

Commit efa7743

Browse files
committed
test: 報告書プロフィール年度切り替えバグの再発防止E2Eテストを追加
年度切り替え(YearSelector による router.push)が発生した際、 ReportProfileForm のクライアント state が新しい年度の initialData で 再初期化され、以下の性質を満たすことを検証する。 - 別年度に切り替えると前年度の入力値がフォームに残らない - ある年度で保存しても、他の年度のプロフィールを上書きしない - 年度を行き来しても、各年度の保存内容がそれぞれ独立して保持される https://claude.ai/code/session_01EP5uiLH44LPCFmHX3AE19i
1 parent b70f2ac commit efa7743

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { test, expect } from "@playwright/test";
2+
3+
test.describe("報告書プロフィール", () => {
4+
test.beforeEach(async ({ page }) => {
5+
await page.goto("/login");
6+
await page.getByLabel("Email").fill("foo@example.com");
7+
await page.getByLabel("Password").fill("foo@example.com");
8+
await page.getByRole("button", { name: "ログイン" }).click();
9+
await expect(page).toHaveURL("/");
10+
});
11+
12+
test.describe("年度切り替え", () => {
13+
test("年度を切り替えてもフォームが正しく同期し、他の年度を上書きしない", async ({ page }) => {
14+
// 既存シードや他テストと干渉しないよう、テスト専用の政治団体を作成
15+
const uniqueSlug = `report-profile-year-${Date.now()}`;
16+
const orgName = `年度切替テスト団体 ${Date.now()}`;
17+
18+
await page.goto("/political-organizations/new");
19+
await page.getByLabel(//).fill(orgName);
20+
await page.getByLabel(//).fill(uniqueSlug);
21+
await page.getByRole("button", { name: "作成" }).click();
22+
await expect(page).toHaveURL("/political-organizations");
23+
24+
// 作成した政治団体の報告書プロフィール画面へ遷移
25+
const orgCard = page
26+
.locator("h3")
27+
.filter({ hasText: orgName })
28+
.locator("xpath=ancestor::div[contains(@class, 'border')]");
29+
await orgCard.getByRole("link", { name: "編集" }).click();
30+
await page.getByRole("link", { name: "報告書プロフィール" }).click();
31+
32+
await expect(
33+
page.getByRole("heading", { name: new RegExp(`${orgName}.*報告書プロフィール`) }),
34+
).toBeVisible();
35+
36+
// YearSelector の select(Label「報告年」の直後の要素)
37+
const yearSelect = page.locator(
38+
'xpath=//label[normalize-space()="報告年"]/following-sibling::select[1]',
39+
);
40+
41+
// YearSelector の選択肢は currentYear から過去10年。
42+
// 実行年に依存しないよう、currentYear-1 と currentYear-2 を使う。
43+
const options = await yearSelect.locator("option").all();
44+
const yearA = await options[1].getAttribute("value");
45+
const yearB = await options[2].getAttribute("value");
46+
expect(yearA).toBeTruthy();
47+
expect(yearB).toBeTruthy();
48+
49+
// 団体名称は Label に htmlFor が無いため、placeholder で一意に特定
50+
const officialNameInput = page.getByPlaceholder("政治団体の正式名称");
51+
const saveButton = page.getByRole("button", { name: /^/ });
52+
53+
// yearA で新規保存
54+
await yearSelect.selectOption(yearA!);
55+
await expect(page).toHaveURL(new RegExp(`year=${yearA}`));
56+
await expect(officialNameInput).toHaveValue("");
57+
58+
const yearAName = `${yearA}年の団体名 ${Date.now()}`;
59+
await officialNameInput.fill(yearAName);
60+
await saveButton.click();
61+
await expect(page.getByText("保存しました")).toBeVisible();
62+
63+
// yearB に切り替え → フォームが空になっていること
64+
// (バグ再発時は yearA の入力値が残り、保存で yearA が上書きされる)
65+
await yearSelect.selectOption(yearB!);
66+
await expect(page).toHaveURL(new RegExp(`year=${yearB}`));
67+
await expect(officialNameInput).toHaveValue("");
68+
69+
// yearB で別の値を保存
70+
const yearBName = `${yearB}年の団体名 ${Date.now()}`;
71+
await officialNameInput.fill(yearBName);
72+
await saveButton.click();
73+
await expect(page.getByText("保存しました")).toBeVisible();
74+
75+
// yearA に戻す → yearA の保存内容が残っていること
76+
// (バグ再発時は yearB の保存で yearA が上書きされて yearBName が表示される)
77+
await yearSelect.selectOption(yearA!);
78+
await expect(page).toHaveURL(new RegExp(`year=${yearA}`));
79+
await expect(officialNameInput).toHaveValue(yearAName);
80+
81+
// yearB に戻す → yearB の保存内容も残っていること
82+
await yearSelect.selectOption(yearB!);
83+
await expect(page).toHaveURL(new RegExp(`year=${yearB}`));
84+
await expect(officialNameInput).toHaveValue(yearBName);
85+
});
86+
});
87+
});

0 commit comments

Comments
 (0)