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
32 changes: 27 additions & 5 deletions e2e/lib/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
import { browser } from "@wdio/globals";

import { pressKey } from "./input.js";
import { waitFor } from "./proc.js";

const present = (selector) =>
Expand Down Expand Up @@ -36,6 +37,31 @@ export async function intoList(click, token) {
}
}

/**
* Open a menu by its title, from whatever state the menubar was left in.
*
* A click on a menu title **toggles** it, so a menu somebody left open makes the next open close it
* instead, and the caller then waits out its whole timeout for an item that was one click away.
* Closing first costs one query when nothing is open. Written as a hazard removed rather than a
* cause proved: `language.spec.js` went red on the runner waiting thirty seconds for the View menu,
* with both of the app's beats regular through it, and this is the one way that can happen from
* outside the app. See BACKLOG.md N174.
*/
export async function openMenu(click, menu) {
if (await present(".menubar__menu")) {
pressKey("Escape");
await waitFor(async () => ((await present(".menubar__menu")) ? null : 1), {
timeout: 15000,
message: "the menu that was already open to close before another one is asked for",
});
}
await click(`.menubar__title--${menu}`);
await waitFor(() => present(".menubar__menu"), {
timeout: 15000,
message: `the ${menu} menu to open`,
});
}

/**
* Run a command from the menu that draws it, given the caller's own clicker.
*
Expand All @@ -45,11 +71,7 @@ export async function intoList(click, token) {
* for the button that happens to carry it today.
*/
export async function runFromMenu(click, menu, token) {
await click(`.menubar__title--${menu}`);
await waitFor(() => present(".menubar__menu"), {
timeout: 15000,
message: `the ${menu} menu to open`,
});
await openMenu(click, menu);
await intoList(click, token);
await click(`.menubar__item--${token}`);
await waitFor(async () => ((await present(".menubar__menu")) ? null : 1), {
Expand Down
3 changes: 2 additions & 1 deletion e2e/specs/language.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { browser, expect } from "@wdio/globals";

import { clickAt, focusWindow, pressKey } from "../lib/input.js";
import { windowHeight, windowWidth } from "../lib/paths.js";
import { openMenu } from "../lib/menu.js";
import { waitFor } from "../lib/proc.js";
import { findToplevel } from "../lib/x11.js";

Expand Down Expand Up @@ -48,7 +49,7 @@ async function clickElement(toplevel, selector) {
}

async function openLanguage(toplevel) {
await clickElement(toplevel, ".menubar__title--view");
await openMenu((css) => clickElement(toplevel, css), "view");
await waitFor(() => present(".menubar__item--view-language"), {
timeout: 15000,
message: "the View menu to open on its Language item",
Expand Down
18 changes: 18 additions & 0 deletions e2e/specs/menu-submenus.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { browser, expect } from "@wdio/globals";
import { answerChooser, waitForChooser } from "../lib/chooser.js";
import { clickAt, focusWindow, hoverAt, pressKey } from "../lib/input.js";
import { takeCommands, watchCommands } from "../lib/ipc.js";
import { openMenu } from "../lib/menu.js";
import { repoRoot, windowHeight, windowWidth } from "../lib/paths.js";
import { waitFor } from "../lib/proc.js";
import { findToplevel } from "../lib/x11.js";
Expand Down Expand Up @@ -280,4 +281,21 @@ describe("a menu row that opens a list of its own", () => {

await closeMenus();
});

it("opens a menu that is already open, rather than toggling it shut", async () => {
// A click on the title of the menu that is **already** open closes it: clicking another title
// switches, which is why this check names the same one twice. A caller that asked for a menu
// somebody had left open would then wait out its whole timeout for an item one click away.
// `openMenu` closes first and opens after, so the answer does not depend on what came before.
await clickElement(toplevel, ".menubar__title--timing");
await waitFor(() => present(".menubar__menu"), {
timeout: 15000,
message: "the Timing menu to be left open, which is this check's own precondition",
});

await openMenu((css) => clickElement(toplevel, css), "timing");
expect(await present(".menubar__menu")).toBe(true);

await closeMenus();
});
});
2 changes: 1 addition & 1 deletion e2e/wdio.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
* Every spec that exists must run. WebdriverIO does not reliably fail a run that executed nothing,
* so the count is asserted here. Bump it when you add a test; see e2e/README.md.
*/
const EXPECTED_TESTS = 514;
const EXPECTED_TESTS = 515;

/** How long mocha lets one test live. Every wait inside a test must be shorter. See N165. */
const TEST_LIMIT_MS = 60000;
Expand Down
Loading