Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
5 changes: 4 additions & 1 deletion src/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -820,8 +820,11 @@ export class Navigation {
* @returns whether keyboard navigation is currently allowed.
*/
canCurrentlyNavigate(workspace: Blockly.WorkspaceSvg) {
const accessibilityMode = workspace.isFlyout
? workspace.targetWorkspace?.keyboardAccessibilityMode
: workspace.keyboardAccessibilityMode;
return (
workspace.keyboardAccessibilityMode &&
!!accessibilityMode &&
this.getState(workspace) !== Constants.STATE.NOWHERE
);
}
Expand Down
65 changes: 65 additions & 0 deletions test/webdriverio/test/actions_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import * as chai from 'chai';
import {Key} from 'webdriverio';
import {
checkActionPrecondition,
moveToToolboxCategory,
PAUSE_TIME,
setCurrentCursorNodeById,
tabNavigateToWorkspace,
testFileLocations,
testSetup,
} from './test_setup.js';

suite('Menus test', function () {
// Setting timeout to unlimited as these tests take longer time to run
this.timeout(0);

// Clear the workspace and load start blocks
setup(async function () {
this.browser = await testSetup(testFileLocations.BASE);
await this.browser.pause(PAUSE_TIME);
});

test('Menu action returns true normally', async function () {
// Navigate to draw_circle_1.
await tabNavigateToWorkspace(this.browser);
await setCurrentCursorNodeById(this.browser, 'draw_circle_1');
chai.assert.isTrue(
await checkActionPrecondition(this.browser, 'menu'),
'The menu should be openable on a block',
);
});

test('Menu action returns true in the toolbox', async function () {
// Navigate to draw_circle_1.
await tabNavigateToWorkspace(this.browser);
await setCurrentCursorNodeById(this.browser, 'draw_circle_1');
// Navigate to a toolbox category
await moveToToolboxCategory(this.browser, 'Functions');
// Move to flyout.
await this.browser.keys(Key.ArrowRight);

chai.assert.isTrue(
await checkActionPrecondition(this.browser, 'menu'),
'The menu should be openable on a block in the toolbox',
);
});

test('Menu action returns false during drag', async function () {
// Navigate to draw_circle_1.
await tabNavigateToWorkspace(this.browser);
await setCurrentCursorNodeById(this.browser, 'draw_circle_1');
// Start moving the block
await this.browser.keys('m');
chai.assert.isFalse(
await checkActionPrecondition(this.browser, 'menu'),
'The menu should not be openable during a move',
);
});
});
37 changes: 37 additions & 0 deletions test/webdriverio/test/test_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,3 +431,40 @@ export async function isDragging(
return workspaceSvg.isDragging();
});
}

/**
* Returns the result of the specificied action precondition.
*
* @param browser The active WebdriverIO Browser object.
* @param action The action to check the precondition for.
*/
export async function checkActionPrecondition(
browser: WebdriverIO.Browser,
action: string,
): Promise<boolean> {
return await browser.execute((action) => {
const node = Blockly.getFocusManager().getFocusedNode();
let workspace;
if (node instanceof Blockly.BlockSvg) {
workspace = node.workspace as Blockly.WorkspaceSvg;
} else if (node instanceof Blockly.Workspace) {
workspace = node as Blockly.WorkspaceSvg;
} else if (node instanceof Blockly.Field) {
workspace = node.getSourceBlock()?.workspace as Blockly.WorkspaceSvg;
}

if (!workspace) {
throw new Error('Unable to derive workspace from focused node');
}
const actionItem = Blockly.ShortcutRegistry.registry.getRegistry()[action];
if (!actionItem || !actionItem.preconditionFn) {
throw new Error(
`No registered action or missing precondition: ${action}`,
);
}
return actionItem.preconditionFn(workspace, {
focusedNode:
Blockly.FocusManager.getFocusManager().getFocusedNode() ?? undefined,
});
}, action);
}
Loading