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
212 changes: 212 additions & 0 deletions test/webdriverio/test/delete_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

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

suite('Deleting Blocks', function () {
// Setting timeout to unlimited as these tests take a longer time to run than most mocha test
this.timeout(0);

setup(async function () {
this.browser = await testSetup(testFileLocations.NAVIGATION_TEST_BLOCKS);
await this.browser.pause(PAUSE_TIME);
});

test('Deleting block selects previous connection', async function () {
await tabNavigateToWorkspace(this.browser);
await this.browser.pause(PAUSE_TIME);
await setCurrentCursorNodeById(this.browser, 'controls_if_2');
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'controls_if_2'))
.equal(true);

await this.browser.keys(Key.Backspace);
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'controls_if_2'))
.equal(false);

chai
.expect(await getCurrentFocusNodeId(this.browser))
.to.include('controls_if_1_connection_');
});

test('Cutting block selects previous connection', async function () {
await tabNavigateToWorkspace(this.browser);
await this.browser.pause(PAUSE_TIME);
await setCurrentCursorNodeById(this.browser, 'controls_if_2');
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'controls_if_2'))
.equal(true);

await this.browser.keys([Key.Ctrl, 'x']);
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'controls_if_2'))
.equal(false);

chai
.expect(await getCurrentFocusNodeId(this.browser))
.to.include('controls_if_1_connection_');
});

test('Deleting block also deletes children and inputs', async function () {
await tabNavigateToWorkspace(this.browser);
await this.browser.pause(PAUSE_TIME);
await setCurrentCursorNodeById(this.browser, 'controls_if_2');
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'logic_boolean_1'))
.equal(true);
chai.expect(await blockIsPresent(this.browser, 'text_print_1')).equal(true);

await this.browser.keys(Key.Backspace);
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'logic_boolean_1'))
.equal(false);
chai
.expect(await blockIsPresent(this.browser, 'text_print_1'))
.equal(false);
});

test('Cutting block also removes children and inputs', async function () {
await tabNavigateToWorkspace(this.browser);
await this.browser.pause(PAUSE_TIME);
await setCurrentCursorNodeById(this.browser, 'controls_if_2');
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'logic_boolean_1'))
.equal(true);
chai.expect(await blockIsPresent(this.browser, 'text_print_1')).equal(true);

await this.browser.keys([Key.Ctrl, 'x']);
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'logic_boolean_1'))
.equal(false);
chai
.expect(await blockIsPresent(this.browser, 'text_print_1'))
.equal(false);
});

test('Deleting inline input selects parent connection', async function () {
await tabNavigateToWorkspace(this.browser);
await this.browser.pause(PAUSE_TIME);
await setCurrentCursorNodeById(this.browser, 'logic_boolean_1');
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'logic_boolean_1'))
.equal(true);

await this.browser.keys(Key.Backspace);
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'logic_boolean_1'))
.equal(false);

chai
.expect(await getCurrentFocusNodeId(this.browser))
.to.include('controls_if_2_connection_');
});

test('Cutting inline input selects parent connection', async function () {
await tabNavigateToWorkspace(this.browser);
await this.browser.pause(PAUSE_TIME);
await setCurrentCursorNodeById(this.browser, 'logic_boolean_1');
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'logic_boolean_1'))
.equal(true);

await this.browser.keys([Key.Ctrl, 'x']);
await this.browser.pause(PAUSE_TIME);

chai
.expect(await blockIsPresent(this.browser, 'logic_boolean_1'))
.equal(false);

chai
.expect(await getCurrentFocusNodeId(this.browser))
.to.include('controls_if_2_connection_');
});

test('Deleting stranded block selects workspace', async function () {
await tabNavigateToWorkspace(this.browser);
await this.browser.pause(PAUSE_TIME);

// The test workspace doesn't already contain a stranded block, so add one.
await moveToToolboxCategory(this.browser, 'Math');
await this.browser.pause(PAUSE_TIME);
// Move to flyout.
await this.browser.keys(Key.ArrowRight);
await this.browser.pause(PAUSE_TIME);
// Select number block.
await this.browser.keys(Key.Enter);
await this.browser.pause(PAUSE_TIME);
// Confirm move.
await this.browser.keys(Key.Enter);
await this.browser.pause(PAUSE_TIME);

chai.assert.equal('math_number', await getFocusedBlockType(this.browser));

await this.browser.keys(Key.Backspace);
await this.browser.pause(PAUSE_TIME);

chai.expect(await currentFocusIsMainWorkspace(this.browser)).equal(true);
});

test('Cutting stranded block selects workspace', async function () {
await tabNavigateToWorkspace(this.browser);
await this.browser.pause(PAUSE_TIME);

// The test workspace doesn't already contain a stranded block, so add one.
await moveToToolboxCategory(this.browser, 'Math');
await this.browser.pause(PAUSE_TIME);
// Move to flyout.
await this.browser.keys(Key.ArrowRight);
await this.browser.pause(PAUSE_TIME);
// Select number block.
await this.browser.keys(Key.Enter);
await this.browser.pause(PAUSE_TIME);
// Confirm move.
await this.browser.keys(Key.Enter);
await this.browser.pause(PAUSE_TIME);

chai.assert.equal('math_number', await getFocusedBlockType(this.browser));

await this.browser.keys([Key.Ctrl, 'x']);
await this.browser.pause(PAUSE_TIME);

chai.expect(await currentFocusIsMainWorkspace(this.browser)).equal(true);
});
});
19 changes: 2 additions & 17 deletions test/webdriverio/test/insert_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
*/

import * as chai from 'chai';
import {Browser, Key} from 'webdriverio';
import {Key} from 'webdriverio';
import {
getFocusedBlockType,
moveToToolboxCategory,
PAUSE_TIME,
setCurrentCursorNodeById,
tabNavigateToWorkspace,
Expand Down Expand Up @@ -44,19 +45,3 @@ suite('Insert test', function () {
);
});
});

async function moveToToolboxCategory(browser: Browser, category: string) {
await browser.keys('t');
const categoryIndex = await browser.execute((category) => {
const all = Array.from(
document.querySelectorAll('.blocklyToolboxCategoryLabel'),
).map((node) => node.textContent);
return all.indexOf(category);
}, category);
if (categoryIndex < 0) {
throw new Error(`No category found: ${category}`);
}
if (categoryIndex > 0) {
await browser.keys(Key.ArrowDown.repeat(categoryIndex));
}
}
58 changes: 57 additions & 1 deletion test/webdriverio/test/test_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,62 @@ export async function focusWorkspace(browser: WebdriverIO.Browser) {
await workspaceElement.click();
}

/**
* Focuses the toolbox category with the given name.
*
* @param browser The active WebdriverIO Browser object.
* @param category The name of the toolbox category to focus.
*/
export async function moveToToolboxCategory(
browser: WebdriverIO.Browser,
category: string,
) {
await browser.keys('t');
const categoryIndex = await browser.execute((category) => {
const all = Array.from(
document.querySelectorAll('.blocklyToolboxCategoryLabel'),
).map((node) => node.textContent);
return all.indexOf(category);
}, category);
if (categoryIndex < 0) {
throw new Error(`No category found: ${category}`);
}
if (categoryIndex > 0) {
await browser.keys(webdriverio.Key.ArrowDown.repeat(categoryIndex));
}
}

/**
* Returns whether the workspace contains a block with the given id.
*
* @param browser The active WebdriverIO Browser object.
* @param blockId The id of the block.
*/
export async function blockIsPresent(
browser: WebdriverIO.Browser,
blockId: string,
): Promise<boolean> {
return await browser.execute((blockId) => {
const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg;
const block = workspaceSvg.getBlockById(blockId);
return block !== null;
}, blockId);
}

/**
* Returns whether the main workspace is the current focus.
*
* @param browser The active WebdriverIO Browser object.
*/
export async function currentFocusIsMainWorkspace(
browser: WebdriverIO.Browser,
): Promise<boolean> {
return await browser.execute(() => {
const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg;
return Blockly.getFocusManager().getFocusedNode() === workspaceSvg;
});
}

/**
* Select a block with the given id as the current cursor node.
*
Expand All @@ -191,7 +247,7 @@ export async function setCurrentCursorNodeById(
}

/**
* Select a block with the given id as the current cursor node.
* Select a block's field with the given block id and field name.
*
* @param browser The active WebdriverIO Browser object.
* @param blockId The id of the block to select.
Expand Down
Loading