0de77f7871
Co-authored-by: Kandev Agent <agent@kandev.dev>
57 lines
2.9 KiB
TypeScript
57 lines
2.9 KiB
TypeScript
/**
|
|
* E2E: a plugin row opens its settings page from a phone.
|
|
*
|
|
* The row used to carry its link on the plugin name alone, styled like the
|
|
* headings around it and underlined only on hover, so a touch device got no
|
|
* affordance at all. The whole card is the target now, with a chevron. This is
|
|
* the phone half of that: `e2e/playwright.config.ts` routes only
|
|
* `mobile-*.spec.ts` at the Pixel 5 project, so the desktop coverage in
|
|
* plugins.spec.ts cannot catch phone wrapping, stacking, or hit-target
|
|
* regressions in the row.
|
|
*
|
|
* One test rather than several: installing the fixture plugin is the expensive
|
|
* part of the setup and every assertion here is about the same rendered row.
|
|
*/
|
|
import { expect, test } from "../../fixtures/test-base";
|
|
import { PLUGIN_ID, installFixturePlugin } from "../../helpers/plugin-fixture";
|
|
|
|
test("mobile plugin row: whole card opens settings, controls still act", async ({ testPage }) => {
|
|
test.setTimeout(180_000);
|
|
|
|
await installFixturePlugin(testPage);
|
|
const pluginRow = testPage.getByTestId(`plugin-row-${PLUGIN_ID}`);
|
|
await expect(pluginRow).toBeVisible({ timeout: 30_000 });
|
|
|
|
// The fixture declares a required api_token nobody has filled in, so the row
|
|
// advertises the page it wants opened. It has to survive the phone's badge
|
|
// wrapping, not just fit on a desktop title row.
|
|
await expect(pluginRow.getByTestId(`plugin-setup-required-${PLUGIN_ID}`)).toBeVisible({
|
|
timeout: 15_000,
|
|
});
|
|
|
|
// The overlay link is the whole affordance on touch, where nothing hovers,
|
|
// so it has to actually cover the card. It is inset by the row's 1px border,
|
|
// hence the 2px slack; a `space-y-*` margin landing on it once cost the
|
|
// bottom strip of the card.
|
|
const linkBox = await pluginRow.getByTestId(`plugin-row-link-${PLUGIN_ID}`).boundingBox();
|
|
const rowBox = await pluginRow.boundingBox();
|
|
if (!linkBox || !rowBox) throw new Error("plugin row or its overlay link has no layout box");
|
|
expect(linkBox.width).toBeGreaterThanOrEqual(rowBox.width - 2);
|
|
expect(linkBox.height).toBeGreaterThanOrEqual(rowBox.height - 2);
|
|
|
|
// Every control sits above the overlay. If one slipped below it the tap would
|
|
// navigate instead of acting, and on a phone there is no hover state to
|
|
// reveal which is which.
|
|
const disable = pluginRow.getByRole("button", { name: "Disable" });
|
|
expect((await disable.boundingBox())?.height).toBeGreaterThanOrEqual(44);
|
|
await disable.tap();
|
|
await expect(pluginRow.getByText("Disabled", { exact: true })).toBeVisible({ timeout: 15_000 });
|
|
await expect(testPage).toHaveURL(/\/settings\/plugins$/);
|
|
|
|
// Tapping the card body rather than the name is the whole point of the
|
|
// change; keep clear of the row's own controls.
|
|
await pluginRow.tap({ position: { x: 12, y: 12 } });
|
|
await expect(testPage).toHaveURL(new RegExp(`/settings/plugins/${PLUGIN_ID}$`));
|
|
await expect(testPage.getByTestId(`plugin-detail-${PLUGIN_ID}`)).toBeVisible();
|
|
});
|