mock: 長押しにループ方式とリスト方式を入れ、ツールバーで切り替える(T-30 単位7b)

どちらも押した位置に円形インジケータを、少し離して選択先のリストを出す。
間隔は600msで始まり1000msごとに進む(500ms/450msは早いという所感への対応)。
リスト方式は、ポインタがリストに入ると巡回を止め、離したときに指している行で確定する。
リストへ向かう動きをドラッグと取り違えないよう、リスト方式では長押し後のドラッグをしない。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ShoEXYqi8PWTjB9E86Ltot
This commit is contained in:
2026-10-23 21:07:04 +09:00
co-authored by Claude Opus 5.5
parent 37ed6d5186
commit b383fcf844
7 changed files with 258 additions and 50 deletions
+42 -2
View File
@@ -201,7 +201,7 @@ test("長押しでクラスターを選び、ダブルクリックでフォー
const b = await key.boundingBox();
await page.mouse.move(b!.x + b!.width / 2, b!.y + b!.height / 2);
await page.mouse.down();
await expect(page.locator(".long-label")).toContainText("Cluster", { timeout: 2000 });
await expect(page.locator(".hold-row.active")).toContainText("Cluster", { timeout: 2000 });
await page.mouse.up();
await expect(page.locator(`[data-tree-id="${clusterId}"]`).first()).toHaveClass(/chosen/);
await page.locator(`[data-tree-id="${clusterId}"]`).first().click();
@@ -588,7 +588,7 @@ test("長押し候補は離すまで選択を変えず、離すとクラスタ
const b = await cluster.locator('[data-node-type="key"]').first().boundingBox();
await page.mouse.move(b!.x + b!.width / 2, b!.y + b!.height / 2);
await page.mouse.down();
await expect(page.locator(".long-label")).toContainText("2/", { timeout: 1800 });
await expect(page.locator(".hold-row.active")).toContainText("Cluster", { timeout: 1800 });
await expect(
page.locator(`[data-sel-id="${await keys.nth(4).getAttribute("data-node-id")}"]`),
).toBeVisible();
@@ -597,6 +597,46 @@ test("長押し候補は離すまで選択を変えず、離すとクラスタ
await expect(page.locator(`[data-tree-id="${clusterId}"]`).first()).toHaveClass(/chosen/);
});
test("リスト方式では、リストに入ると巡回が止まり、指した行で離すと確定する", async ({ page }) => {
const cluster = await makeCluster(page);
await page.getByRole("button", { name: "長押し: ループ" }).click();
await expect(page.getByRole("button", { name: "長押し: リスト" })).toBeVisible();
const key = cluster.locator('[data-node-type="key"]').first();
const keyId = await key.getAttribute("data-node-id");
const b = await key.boundingBox();
await page.mouse.move(b!.x + b!.width / 2, b!.y + b!.height / 2);
await page.mouse.down();
await expect(page.locator(".hold-row.active")).toContainText("Cluster", { timeout: 2000 });
const row = await page.locator(".hold-row", { hasText: "キー" }).boundingBox();
await page.mouse.move(row!.x + row!.width / 2, row!.y + row!.height / 2, { steps: 5 });
await expect(page.locator(".hold-row.active")).toHaveText("キー");
await expect(page.locator(".hold-ring")).toHaveCount(0);
await page.waitForTimeout(1200);
await expect(page.locator(".hold-row.active")).toHaveText("キー");
await page.mouse.up();
await expect(page.locator(".hold-list")).toHaveCount(0);
await expect(page.locator(`[data-sel-id="${keyId}"]`)).toBeVisible();
// リストへ動かしてもキーはドラッグされない
expect(await key.boundingBox()).toEqual(b);
});
test("ループ方式では、長押しのあと動かすと選んだ先をドラッグする", async ({ page }) => {
const cluster = await makeCluster(page);
const clusterId = await cluster.getAttribute("data-node-id");
const keys = cluster.locator('[data-node-type="key"]');
const before = await keys.nth(1).boundingBox();
const b = (await keys.first().boundingBox())!;
await page.mouse.move(b.x + b.width / 2, b.y + b.height / 2);
await page.mouse.down();
await expect(page.locator(".hold-ring")).toBeVisible({ timeout: 2000 });
await page.mouse.move(b.x + b.width / 2 + 80, b.y + b.height / 2, { steps: 5 });
await expect(page.locator(".hold-list")).toHaveCount(0);
await page.mouse.up();
await expect(page.locator(`[data-tree-id="${clusterId}"]`).first()).toHaveClass(/chosen/);
// クラスターごと動くので、押していないキーも動く
expect((await keys.nth(1).boundingBox())!.x).toBeGreaterThan(before!.x + 40);
});
test("「その他」の部品はpartGroupを設定せず、選択後は追加メニューを戻す", async ({ page }) => {
const select = page.getByRole("combobox", { name: "部品を足す" });
await select.selectOption("その他");