Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions webapp/e2e/fixtures/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Which of the two navigations the viewport draws, asked once it has drawn one.

import type { Page } from "@playwright/test";

/**
* Whether the page shows the phone's bottom navigation rather than the
* sidebar.
*
* `isVisible()` answers at once, without waiting. Asked while the shell was
* still mounting, it saw neither navigation, and a test on a phone then looked
* for its links in the sidebar a phone never draws, until it timed out — on a
* loaded machine, now and then. This waits for whichever one the viewport
* draws, then asks.
*/
export async function onPhoneNavigation(page: Page): Promise<boolean> {
await page
.locator(".mobile-navigation:visible, .primary-navigation:visible")
.first()
.waitFor();
return page.locator(".mobile-navigation").isVisible();
}
3 changes: 2 additions & 1 deletion webapp/e2e/fixtures/radio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import type { Page } from "@playwright/test";

import { silentWav } from "./media";
import { onPhoneNavigation } from "./navigation";
import { mock } from "./state";

/**
Expand All @@ -12,7 +13,7 @@ import { mock } from "./state";
*/
export async function navigateWithin(page: Page, name: string) {
const sidebar = page.locator(".sidebar");
if (await sidebar.isVisible()) {
if (!(await onPhoneNavigation(page))) {
await sidebar.getByRole("link", { name, exact: true }).click();
return;
}
Expand Down
11 changes: 6 additions & 5 deletions webapp/e2e/library-cache.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { expect, test } from "@playwright/test";

import { resetAndMockApi } from "./fixtures/api";
import { albums, session, track } from "./fixtures/catalogue";
import { onPhoneNavigation } from "./fixtures/navigation";
import { mock } from "./fixtures/state";

test.beforeEach(resetAndMockApi);
Expand Down Expand Up @@ -31,7 +32,7 @@ test("keeps the current tab visible while the next tab loads", async ({

await page.goto("/");
await expect(page.getByRole("heading", { name: "Albums" })).toBeVisible();
const mobile = await page.locator(".mobile-navigation").isVisible();
const mobile = await onPhoneNavigation(page);
const genresLink = mobile
? page.locator('.more-sheet a[href="/genres"]')
: page.locator(".primary-navigation").getByRole("link", { name: "Genres" });
Expand Down Expand Up @@ -76,7 +77,7 @@ test("shows the next tab with its wait when the answer is slow", async ({

await page.goto("/");
await expect(page.getByRole("heading", { name: "Albums" })).toBeVisible();
const mobile = await page.locator(".mobile-navigation").isVisible();
const mobile = await onPhoneNavigation(page);
if (mobile) {
await page
.locator(".mobile-navigation")
Expand All @@ -102,7 +103,7 @@ test("shows the next tab with its wait when the answer is slow", async ({
test("takes the current tab back to its plain address", async ({ page }) => {
await page.goto("/playing?view=lyrics");
await expect(page).toHaveURL(/\/playing\?view=lyrics$/);
const navigation = (await page.locator(".mobile-navigation").isVisible())
const navigation = (await onPhoneNavigation(page))
? page.locator(".mobile-navigation")
: page.locator(".primary-navigation");
await navigation.getByRole("link", { name: "Now playing" }).click();
Expand All @@ -128,7 +129,7 @@ test("draws the random tab once when switching to it", async ({ page }) => {

await page.goto("/");
await expect(page.getByRole("heading", { name: "Albums" })).toBeVisible();
if (await page.locator(".mobile-navigation").isVisible()) {
if (await onPhoneNavigation(page)) {
await page.locator(".mobile-navigation").getByRole("button", { name: "More" }).click();
await page.locator('.more-sheet a[href="/random"]').click();
} else {
Expand Down Expand Up @@ -170,7 +171,7 @@ test("leaves a tab switch behind when the visitor moves on while it loads", asyn

await page.goto("/");
await expect(page.getByRole("heading", { name: "Albums" })).toBeVisible();
const mobile = await page.locator(".mobile-navigation").isVisible();
const mobile = await onPhoneNavigation(page);
if (mobile) {
await page.locator(".mobile-navigation").getByRole("button", { name: "More" }).click();
}
Expand Down
4 changes: 3 additions & 1 deletion webapp/e2e/smart-playlists-and-podcasts.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import AxeBuilder from "@axe-core/playwright";
import { expect, type Page, test } from "@playwright/test";

import { onPhoneNavigation } from "./fixtures/navigation";

/**
* Smart playlists and podcasts (RFC-025), against a mock that keeps what it is
* sent: an editor that saved nothing, or a download that changed nothing,
Expand Down Expand Up @@ -646,7 +648,7 @@ function episodeElement(page: Page, ticket: string) {
*/
async function navigateWithin(page: Page, name: string) {
const sidebar = page.locator(".sidebar");
if (await sidebar.isVisible()) {
if (!(await onPhoneNavigation(page))) {
await sidebar.getByRole("link", { name, exact: true }).click();
return;
}
Expand Down
Loading