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
42 changes: 38 additions & 4 deletions apps/netscli-gui/e2e/tauri-render/scenarios/helpers/menu.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,52 @@ async function assertEmptyWorkspaceState(driver) {
assert.doesNotMatch(state.status, /v\d+\./i, 'Version should live in About, not the footer');
}

async function assertExitMenuItemNeutralUntilHover(driver) {
/* A destructive item is marked before you aim at it, not once you have.
*
* This asserted the opposite until now -- "Exit icon should be neutral before
* hover" -- which was correct until #296 moved the red to rest, on the
* reasoning that a warning arriving after you have already aimed at the item
* is too late to redirect you. That PR touched four source files and no e2e
* file, so the assertion kept encoding the behaviour it replaced and failed
* on a run of the current app.
*
* The expected colour is read from `--red` rather than written as a hex, so
* this holds in both themes: the token is #f47582 dark and #c6293d light. A
* probe element resolves it through getComputedStyle, which normalises it to
* the same `rgb(...)` form the icon's own computed colour is reported in.
*
* The probe goes inside `.container`, not on `document.body`. tokens.css
* declares the palette on `.container` (and `.container.theme-light`), not on
* `:root`, so a probe on the body resolves `var(--red)` to nothing and
* inherits white. `rawRed` is asserted non-empty below to catch that directly
* rather than through a confusing colour mismatch, which is how it was found.
*/
async function assertDestructiveMenuItemMarkedAtRest(driver) {
await openMenu(driver, 'File');
const colors = await driver.executeScript(`
const items = Array.from(document.querySelectorAll('.menu-popover-item'));
const normal = items.find((button) => button.textContent.trim() === 'New Port Scan')?.querySelector('svg');
const exit = items.find((button) => button.textContent.trim() === 'Exit')?.querySelector('svg');
const scope = document.querySelector('.container');
const probe = document.createElement('span');
probe.style.cssText = 'color: var(--red); position: absolute; visibility: hidden;';
scope.appendChild(probe);
const danger = getComputedStyle(probe).color;
probe.remove();
return {
normalIcon: normal ? getComputedStyle(normal).color : '',
exitIcon: exit ? getComputedStyle(exit).color : '',
danger,
rawRed: getComputedStyle(scope).getPropertyValue('--red').trim(),
};
`);
assert.equal(colors.exitIcon, colors.normalIcon, 'Exit icon should be neutral before hover');
assert.notEqual(colors.rawRed, '', '--red should resolve on .container; if empty, the probe is in the wrong scope');
assert.equal(colors.exitIcon, colors.danger, 'Exit icon should be danger-coloured at rest');
assert.notEqual(colors.normalIcon, colors.danger, 'A non-destructive item should not be danger-coloured');

// Hover must not take the marking away. menu.css covers hover as "a subset"
// of at-rest, so a rule that reverted here would be a regression the
// at-rest check alone would not see.
const exitButton = await driver.findElement(By.xpath("//button[contains(@class, 'menu-popover-item') and normalize-space()='Exit']"));
await driver.actions({ async: true }).move({ origin: exitButton }).perform();
const hoverColor = await driver.executeScript(`
Expand All @@ -95,7 +129,7 @@ async function assertExitMenuItemNeutralUntilHover(driver) {
?.querySelector('svg');
return exit ? getComputedStyle(exit).color : '';
`);
assert.notEqual(hoverColor, colors.exitIcon, 'Exit icon should become danger-colored on hover');
assert.equal(hoverColor, colors.danger, 'Exit icon should stay danger-coloured on hover');
}

async function assertMenuItemDisabled(driver, menuLabel, itemLabel, expected) {
Expand Down Expand Up @@ -225,8 +259,8 @@ async function assertToolbarButtonDisabled(driver, title, expected) {
}

export {
assertDestructiveMenuItemMarkedAtRest,
assertEmptyWorkspaceState,
assertExitMenuItemNeutralUntilHover,
assertInterfaceReadinessReflectsSelection,
assertMenuIncludes,
assertMenuItemDisabled,
Expand Down
4 changes: 2 additions & 2 deletions apps/netscli-gui/e2e/tauri-render/scenarios/shell.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { assertCommand, assertNoErrorStrip, assertTheme, clickButtonText, replac
import { assertExportArtifactsCreated, countExportArtifacts } from './helpers/export.mjs';
import { assertAboutDialogPolish, assertEmptyStateCentered, assertTrafficArrowsAreLedStyle, forceTabOverflow } from './helpers/polish.mjs';
import { assertCommandStatusAlignment, assertInteractiveCursorTreatment, assertSuppressesNativeContextMenu, assertThemedTooltips, assertToastHasTimeoutBar } from './helpers/interaction.mjs';
import { assertEmptyWorkspaceState, assertExitMenuItemNeutralUntilHover, assertInterfaceReadinessReflectsSelection, assertMenuIncludes, assertMenuItemDisabled, assertMenuItems, assertMenuKeyboardNavigation, assertToolbarButtonDisabled, clickMenuItem, countTabs, ensureTrafficIndicatorsVisible, getActiveTabText, waitForTabCount } from './helpers/menu.mjs';
import { assertDestructiveMenuItemMarkedAtRest, assertEmptyWorkspaceState, assertInterfaceReadinessReflectsSelection, assertMenuIncludes, assertMenuItemDisabled, assertMenuItems, assertMenuKeyboardNavigation, assertToolbarButtonDisabled, clickMenuItem, countTabs, ensureTrafficIndicatorsVisible, getActiveTabText, waitForTabCount } from './helpers/menu.mjs';
import { assertSettingsDialog, closeSettingsDialog, openSettingsDialog } from './helpers/settingsDialog.mjs';
import { assertActiveTabVisible, assertDetailPaneCanFillWorkspace, assertEmptyToolLauncherVisible, assertOverflowTabClickSelection, assertTabAddControlPlacement, assertTabOverflowTreatment, assertTabToolPopoverTopLayer, assertTabToolPopoverVisible } from './helpers/tabs.mjs';

Expand Down Expand Up @@ -111,7 +111,7 @@ export async function exerciseMenusAndToolbar(driver) {

await assertMenuItemDisabled(driver, 'File', 'Export JSON', false);
await assertMenuItemDisabled(driver, 'File', 'Export CSV', false);
await assertExitMenuItemNeutralUntilHover(driver);
await assertDestructiveMenuItemMarkedAtRest(driver);
await assertMenuItemDisabled(driver, 'History', 'Clear History', false);
await assertMenuItemDisabled(driver, 'Scan', 'Run Active Tab', false);
await assertMenuItemDisabled(driver, 'Scan', 'Cancel Active Tab', true);
Expand Down