|
1 | | -import { test, expect } from "@playwright/test"; |
| 1 | +import { test, expect, Page, Locator } from "@playwright/test"; |
2 | 2 |
|
3 | 3 | import { gotoHome, navigateToSong } from "../../navigators"; |
| 4 | +import { ensureNotNullish } from "@/helpers/errorHelper"; |
4 | 5 |
|
5 | 6 | test.beforeEach(gotoHome); |
6 | 7 |
|
| 8 | +function getSequencer(page: Page) { |
| 9 | + return page.getByLabel("シーケンサ"); |
| 10 | +} |
| 11 | + |
| 12 | +async function addNotes(page: Page, count: number) { |
| 13 | + await test.step(`ノートを${count}つ追加`, async () => { |
| 14 | + const sequencer = getSequencer(page); |
| 15 | + for (let i = 0; i < count; i++) { |
| 16 | + await sequencer.click({ position: { x: (i + 1) * 100, y: 171 } }); |
| 17 | + } |
| 18 | + const notes = sequencer.locator(".note"); |
| 19 | + await expect(notes).toHaveCount(count); |
| 20 | + }); |
| 21 | +} |
| 22 | + |
| 23 | +/** Locator の配列を x 座標でソートする */ |
| 24 | +async function toSortedLocator(locators: Locator[]): Promise<Locator[]> { |
| 25 | + const locatorsWithPosition = await Promise.all( |
| 26 | + locators.map(async (locator) => ({ |
| 27 | + locator, |
| 28 | + x: ensureNotNullish(await locator.boundingBox()).x, |
| 29 | + })), |
| 30 | + ); |
| 31 | + locatorsWithPosition.sort((a, b) => a.x - b.x); |
| 32 | + return locatorsWithPosition.map(({ locator }) => locator); |
| 33 | +} |
| 34 | + |
| 35 | +async function getSortedNotes(page: Page): Promise<Locator[]> { |
| 36 | + return await test.step("ノートをソートして取得", async () => { |
| 37 | + const sequencer = getSequencer(page); |
| 38 | + const notes = await sequencer.locator(".note").all(); |
| 39 | + return toSortedLocator(notes); |
| 40 | + }); |
| 41 | +} |
| 42 | + |
| 43 | +async function getSortedNoteLylics(page: Page): Promise<string[]> { |
| 44 | + return await test.step("ノートをソートして歌詞を取得", async () => { |
| 45 | + const sequencer = getSequencer(page); |
| 46 | + const lyrics = await sequencer.locator(".note-lyric").all(); |
| 47 | + const sortedLyrics = await toSortedLocator(lyrics); |
| 48 | + return Promise.all( |
| 49 | + sortedLyrics.map(async (lyric) => |
| 50 | + ensureNotNullish(await lyric.textContent()), |
| 51 | + ), |
| 52 | + ); |
| 53 | + }); |
| 54 | +} |
| 55 | + |
| 56 | +async function editNoteLyric(page: Page, note: Locator, lyric: string) { |
| 57 | + await test.step("ノートをダブルクリックして歌詞を入力", async () => { |
| 58 | + await note.dblclick(); |
| 59 | + |
| 60 | + const sequencer = getSequencer(page); |
| 61 | + const lyricInput = sequencer.locator(".lyric-input"); |
| 62 | + await expect(lyricInput).toBeVisible(); |
| 63 | + await lyricInput.fill(lyric); |
| 64 | + await lyricInput.press("Enter"); |
| 65 | + await expect(lyricInput).not.toBeVisible(); |
| 66 | + }); |
| 67 | +} |
| 68 | + |
7 | 69 | test("ダブルクリックで歌詞を編集できる", async ({ page }) => { |
8 | 70 | await navigateToSong(page); |
9 | 71 |
|
10 | | - const sequencer = page.getByLabel("シーケンサ"); |
11 | | - |
12 | | - const getCurrentNoteLyric = async () => |
13 | | - await sequencer.locator(".note-lyric").first().textContent(); |
| 72 | + await addNotes(page, 1); |
| 73 | + const note = (await getSortedNotes(page))[0]; |
| 74 | + const beforeLyric = (await getSortedNoteLylics(page))[0]; |
14 | 75 |
|
15 | | - // ノートを追加し、表示されるまで待つ |
16 | | - await sequencer.click({ position: { x: 107, y: 171 } }); |
17 | | - await page.waitForSelector(".note"); |
| 76 | + await editNoteLyric(page, note, "あ"); |
18 | 77 |
|
19 | | - // ノートの歌詞を取得 |
20 | | - const note = sequencer.locator(".note").first(); |
21 | | - const beforeLyric = await getCurrentNoteLyric(); |
| 78 | + await test.step("歌詞が変更されていることを確認", async () => { |
| 79 | + const afterLyric = await getSortedNoteLylics(page); |
| 80 | + expect(afterLyric[0]).not.toEqual(beforeLyric); |
| 81 | + expect(afterLyric[0]).toEqual("あ"); |
| 82 | + }); |
| 83 | +}); |
22 | 84 |
|
23 | | - // ノートをダブルクリックし、入力フィールドが表示されるまで待つ |
24 | | - await note.dblclick(); |
25 | | - await page.waitForSelector(".lyric-input"); |
| 85 | +test("複数ノートの歌詞を一度に編集できる", async ({ page }) => { |
| 86 | + await navigateToSong(page); |
26 | 87 |
|
27 | | - // 歌詞を入力し、Enterキーを押す |
28 | | - const lyricInput = sequencer.locator(".lyric-input"); |
29 | | - await lyricInput.fill("あ"); |
30 | | - await lyricInput.press("Enter"); |
| 88 | + await addNotes(page, 3); |
31 | 89 |
|
32 | | - // 変更が反映されるまで待つ |
33 | | - await page.waitForFunction(() => { |
34 | | - const lyricElement = document.querySelector(".note-lyric"); |
35 | | - return lyricElement && lyricElement.textContent === "あ"; |
| 90 | + await editNoteLyric(page, (await getSortedNotes(page))[0], "あいう"); |
| 91 | + await test.step("全てのノートの歌詞が変更されていることを確認", async () => { |
| 92 | + const afterLyrics = await getSortedNoteLylics(page); |
| 93 | + expect(afterLyrics).toEqual(["あ", "い", "う"]); |
36 | 94 | }); |
37 | 95 |
|
38 | | - // 歌詞が変更されたことを確認 |
39 | | - const afterLyric = await getCurrentNoteLyric(); |
40 | | - expect(afterLyric).not.toEqual(beforeLyric); |
41 | | - expect(afterLyric).toEqual("あ"); |
| 96 | + await editNoteLyric(page, (await getSortedNotes(page))[0], "かきくけこ"); |
| 97 | + await test.step("最後のノートに残りの文字が入力されていることを確認", async () => { |
| 98 | + const afterLyrics = await getSortedNoteLylics(page); |
| 99 | + expect(afterLyrics).toEqual(["か", "き", "くけこ"]); |
| 100 | + }); |
42 | 101 | }); |
0 commit comments