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
2 changes: 1 addition & 1 deletion src/shortcut_formatting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function getMenuItem(labelText: string, action: string): HTMLElement {
label.textContent = labelText;
const shortcut = document.createElement('span');
shortcut.className = 'blocklyShortcut';
shortcut.textContent = getShortActionShortcut(action);
shortcut.textContent = ` ${getShortActionShortcut(action)}`;
container.appendChild(label);
container.appendChild(shortcut);
return container;
Expand Down
2 changes: 1 addition & 1 deletion test/webdriverio/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ function createWorkspace(): Blockly.WorkspaceSvg {
KeyboardNavigation.registerKeyboardNavigationStyles();
const workspace = Blockly.inject(blocklyDiv, injectOptions);

new KeyboardNavigation(workspace);
Blockly.ContextMenuItems.registerCommentOptions();
new KeyboardNavigation(workspace);

// Disable blocks that aren't inside the setup or draw loops.
workspace.addChangeListener(Blockly.Events.disableOrphans);
Expand Down
93 changes: 84 additions & 9 deletions test/webdriverio/test/actions_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
testFileLocations,
testSetup,
keyRight,
contextMenuItems,
} from './test_setup.js';

suite('Menus test', function () {
Expand All @@ -27,20 +28,47 @@ suite('Menus test', function () {
await this.browser.pause(PAUSE_TIME);
});

test('Menu action opens menu', async function () {
test('Menu on block', async function () {
// Navigate to draw_circle_1.
await tabNavigateToWorkspace(this.browser);
await focusOnBlock(this.browser, 'draw_circle_1');
await this.browser.pause(PAUSE_TIME);
await this.browser.keys([Key.Ctrl, Key.Return]);
await this.browser.pause(PAUSE_TIME);
chai.assert.isTrue(
await contextMenuExists(this.browser, 'Collapse Block'),
'The menu should be openable on a block',

chai.assert.deepEqual(
process.platform === 'darwin'
? [
{'text': 'Duplicate D'},
{'text': 'Add Comment'},
{'text': 'External Inputs'},
{'text': 'Collapse Block'},
{'text': 'Disable Block'},
{'text': 'Delete 2 Blocks Delete'},
{'text': 'Move Block M'},
{'text': 'Edit Block contents Right'},
{'text': 'Cut ⌘ X'},
{'text': 'Copy ⌘ C'},
{'disabled': true, 'text': 'Paste ⌘ V'},
]
: [
{'text': 'Duplicate D'},
{'text': 'Add Comment'},
{'text': 'External Inputs'},
{'text': 'Collapse Block'},
{'text': 'Disable Block'},
{'text': 'Delete 2 Blocks Delete'},
{'text': 'Move Block M'},
{'text': 'Edit Block contents Right'},
{'text': 'Cut Ctrl + X'},
{'text': 'Copy Ctrl + C'},
{'disabled': true, 'text': 'Paste Ctrl + V'},
],
await contextMenuItems(this.browser),
);
});

test('Menu action returns true in the toolbox', async function () {
test('Menu on block in the toolbox', async function () {
// Navigate to draw_circle_1.
await tabNavigateToWorkspace(this.browser);
await focusOnBlock(this.browser, 'draw_circle_1');
Expand All @@ -51,13 +79,60 @@ suite('Menus test', function () {
await this.browser.keys([Key.Ctrl, Key.Return]);
await this.browser.pause(PAUSE_TIME);

chai.assert.isTrue(
await contextMenuExists(this.browser, 'Help'),
'The menu should be openable on a block in the toolbox',
chai.assert.deepEqual(
process.platform === 'darwin'
? [
{'text': 'Help'},
{'disabled': true, 'text': 'Move Block M'},
{'disabled': true, 'text': 'Cut ⌘ X'},
{'text': 'Copy ⌘ C'},
{'disabled': true, 'text': 'Paste ⌘ V'},
]
: [
{'text': 'Help'},
{'disabled': true, 'text': 'Move Block M'},
{'disabled': true, 'text': 'Cut Ctrl + X'},
{'text': 'Copy Ctrl + C'},
{'disabled': true, 'text': 'Paste Ctrl + V'},
],
await contextMenuItems(this.browser),
);
});

test('Menu on workspace', async function () {
// Navigate to draw_circle_1.
await tabNavigateToWorkspace(this.browser);
await this.browser.keys('w');
await this.browser.keys([Key.Ctrl, Key.Return]);
await this.browser.pause(PAUSE_TIME);

chai.assert.deepEqual(
process.platform === 'darwin'
? [
{'disabled': true, 'text': 'Undo'},
{'disabled': true, 'text': 'Redo'},
{'text': 'Clean up Blocks'},
{'text': 'Collapse Blocks'},
{'disabled': true, 'text': 'Expand Blocks'},
{'text': 'Delete 4 Blocks'},
{'text': 'Add Comment'},
{'disabled': true, 'text': 'Paste ⌘ V'},
]
: [
{'disabled': true, 'text': 'Undo'},
{'disabled': true, 'text': 'Redo'},
{'text': 'Clean up Blocks'},
{'text': 'Collapse Blocks'},
{'disabled': true, 'text': 'Expand Blocks'},
{'text': 'Delete 4 Blocks'},
{'text': 'Add Comment'},
{'disabled': true, 'text': 'Paste Ctrl + V'},
],
await contextMenuItems(this.browser),
);
});

test('Menu action returns false during drag', async function () {
test('Menu on block during drag is not shown', async function () {
// Navigate to draw_circle_1.
await tabNavigateToWorkspace(this.browser);
await focusOnBlock(this.browser, 'draw_circle_1');
Expand Down
34 changes: 32 additions & 2 deletions test/webdriverio/test/test_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,8 +589,10 @@ export async function checkActionPrecondition(
/**
* Wait for the specified context menu item to exist.
*
* Does not check the shortcut.
*
* @param browser The active WebdriverIO Browser object.
* @param itemText The display text of the context menu item to click.
* @param itemText The display text of the context menu item without shortcut.
* @param reverse Whether to check for non-existence instead.
* @return A Promise that resolves when the actions are completed.
*/
Expand All @@ -599,10 +601,38 @@ export async function contextMenuExists(
itemText: string,
reverse = false,
): Promise<boolean> {
const item = await browser.$(`div=${itemText}`);
// XPath so as not to care if there's a shortcut which adds DOM structure.
const item = await browser.$(
`//div[contains(@class, "blocklyMenuItem")]//*[text()="${itemText}"]`,
);
return await item.waitForExist({timeout: 200, reverse: reverse});
}

/**
* Wait for the context menu and return a representation of its contents.
*
* The text field includes the shortcut if present.
*
* @param browser The active WebdriverIO Browser object.
* @returns The context menu items.
*/
export async function contextMenuItems(browser: WebdriverIO.Browser): Promise<
Array<{
text: string;
disabled?: true;
}>
> {
await browser.$('.blocklyContextMenu').waitForExist();
const items = await browser
.$$('.blocklyContextMenu .blocklyMenuItem')
.map(async (item) => {
const text = await item.getComputedLabel();
const disabled = (await item.getAttribute('aria-disabled')) === 'true';
return disabled ? {text, disabled} : {text};
});
return items;
}

/**
* Find a clickable element on the block and click it.
* We can't always use the block's SVG root because clicking will always happen
Expand Down
31 changes: 20 additions & 11 deletions test/webdriverio/test/workspace_comment_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import * as chai from 'chai';
import * as Blockly from 'blockly';
import {
contextMenuExists,

Check warning on line 10 in test/webdriverio/test/workspace_comment_test.ts

View workflow job for this annotation

GitHub Actions / Eslint check

'contextMenuExists' is defined but never used
focusOnBlock,
getCurrentFocusNodeId,
getFocusedBlockType,
Expand All @@ -19,6 +19,7 @@
keyRight,
keyDown,
keyUp,
contextMenuItems,
} from './test_setup.js';
import {Key} from 'webdriverio';

Expand Down Expand Up @@ -175,17 +176,25 @@
test('Action menu can be displayed for a workspace comment', async function () {
await focusOnWorkspaceComment(this.browser, this.commentId1);
await sendKeyAndWait(this.browser, [Key.Ctrl, Key.Return]);
chai.assert.isTrue(
await contextMenuExists(this.browser, 'Duplicate Comment'),
'The menu should be openable on a workspace comment',
);
chai.assert.isTrue(
await contextMenuExists(this.browser, 'Remove Comment'),
'The menu should be openable on a workspace comment',
);
chai.assert.isTrue(
await contextMenuExists(this.browser, 'Move CommentM'),
'The menu should be openable on a workspace comment',
chai.assert.deepEqual(
process.platform === 'darwin'
? [
{'text': 'Duplicate Comment D'},
{'text': 'Remove Comment'},
{'text': 'Move Comment M'},
{'text': 'Cut ⌘ X'},
{'text': 'Copy ⌘ C'},
{'disabled': true, 'text': 'Paste ⌘ V'},
]
: [
{'text': 'Duplicate Comment D'},
{'text': 'Remove Comment'},
{'text': 'Move Comment M'},
{'text': 'Cut Ctrl + X'},
{'text': 'Copy Ctrl + C'},
{'disabled': true, 'text': 'Paste Ctrl + V'},
],
await contextMenuItems(this.browser),
);
});

Expand Down