diff --git a/test/index.html b/test/index.html index a528362f..bf0f5f13 100644 --- a/test/index.html +++ b/test/index.html @@ -164,6 +164,9 @@ +
diff --git a/test/loadTestBlocks.js b/test/loadTestBlocks.js index ce0bd347..3c6ddf14 100644 --- a/test/loadTestBlocks.js +++ b/test/loadTestBlocks.js @@ -220,7 +220,7 @@ const simpleCircle = { }, { 'type': 'p5_draw', - 'id': 'draw_root', + 'id': 'p5_draw_1', 'x': 0, 'y': 332, 'deletable': false, @@ -414,6 +414,162 @@ const moreBlocks = { }, }; +const navigationTestBlocks = { + 'blocks': { + 'languageVersion': 0, + 'blocks': [ + { + 'type': 'p5_setup', + 'id': 'p5_setup_1', + 'x': 0, + 'y': 75, + 'deletable': false, + 'inputs': { + 'STATEMENTS': { + 'block': { + 'type': 'p5_canvas', + 'id': 'p5_canvas_1', + 'deletable': false, + 'movable': false, + 'fields': { + 'WIDTH': 400, + 'HEIGHT': 400, + }, + }, + }, + }, + }, + { + 'type': 'p5_draw', + 'id': 'p5_draw_1', + 'x': 0, + 'y': 332, + 'deletable': false, + 'inputs': { + 'STATEMENTS': { + 'block': { + 'type': 'controls_if', + 'id': 'controls_if_1', + 'next': { + 'block': { + 'type': 'controls_if', + 'id': 'controls_if_2', + 'inputs': { + 'IF0': { + 'block': { + 'type': 'logic_boolean', + 'id': 'logic_boolean_1', + 'fields': { + 'BOOL': 'TRUE', + }, + }, + }, + 'DO0': { + 'block': { + 'type': 'text_print', + 'id': 'text_print_1', + 'inputs': { + 'TEXT': { + 'shadow': { + 'type': 'text', + 'id': 'text_1', + 'fields': { + 'TEXT': 'abc', + }, + }, + }, + }, + }, + }, + }, + 'next': { + 'block': { + 'type': 'controls_repeat', + 'id': 'controls_repeat_1', + 'fields': { + 'TIMES': 10, + }, + 'inputs': { + 'DO': { + 'block': { + 'type': 'draw_emoji', + 'id': 'draw_emoji_1', + 'fields': { + 'emoji': '❤️', + }, + 'next': { + 'block': { + 'type': 'simple_circle', + 'id': 'simple_circle_1', + 'inputs': { + 'COLOR': { + 'shadow': { + 'type': 'colour_picker', + 'id': 'colour_picker_1', + 'fields': { + 'COLOUR': '#ff0000', + }, + }, + }, + }, + }, + }, + }, + }, + }, + 'next': { + 'block': { + 'type': 'controls_repeat_ext', + 'id': 'controls_repeat_ext_1', + 'inputs': { + 'TIMES': { + 'shadow': { + 'type': 'math_number', + 'id': 'math_number_1', + 'fields': { + 'NUM': 10, + }, + }, + 'block': { + 'type': 'math_modulo', + 'id': 'math_modulo_1', + 'inputs': { + 'DIVIDEND': { + 'shadow': { + 'type': 'math_number', + 'id': 'math_number_2', + 'fields': { + 'NUM': 64, + }, + }, + }, + 'DIVISOR': { + 'shadow': { + 'type': 'math_number', + 'id': 'math_number_3', + 'fields': { + 'NUM': 10, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + ], + }, +}; + /** * Loads saved state from local storage into the given workspace. * @param {Blockly.Workspace} workspace Blockly workspace to load into. @@ -425,6 +581,7 @@ export const load = function (workspace, scenarioString) { 'sun': sunnyDay, 'simpleCircle': simpleCircle, 'moreBlocks': moreBlocks, + 'navigationTestBlocks': navigationTestBlocks, }; const data = JSON.stringify(scenarioMap[scenarioString]); diff --git a/test/webdriverio/test/basic_test.ts b/test/webdriverio/test/basic_test.ts index 6b142b0b..61d59d4b 100644 --- a/test/webdriverio/test/basic_test.ts +++ b/test/webdriverio/test/basic_test.ts @@ -7,11 +7,11 @@ import * as chai from 'chai'; import * as Blockly from 'blockly'; import { - focusWorkspace, setCurrentCursorNodeById, - getCurrentCursorNodeFieldName, - getCurrentCursorNodeId, - getCurrentCursorNodeType, + setCurrentCursorNodeByIdAndFieldName, + getCurrentFocusNodeId, + getFocusedConnectionType, + getFocusedFieldName, testSetup, testFileLocations, PAUSE_TIME, @@ -19,13 +19,13 @@ import { } from './test_setup.js'; import {Key} from 'webdriverio'; -suite('Keyboard navigation', function () { +suite('Keyboard navigation on Blocks', function () { // Setting timeout to unlimited as these tests take a longer time to run than most mocha test this.timeout(0); // Setup Selenium for all of the tests suiteSetup(async function () { - this.browser = await testSetup(testFileLocations.BASE); + this.browser = await testSetup(testFileLocations.NAVIGATION_TEST_BLOCKS); }); test('Default workspace', async function () { @@ -33,13 +33,13 @@ suite('Keyboard navigation', function () { return Blockly.getMainWorkspace().getAllBlocks(false).length; }); - chai.assert.equal(blockCount, 7); + chai.assert.equal(blockCount, 16); }); test('Selected block', async function () { await tabNavigateToWorkspace(this.browser); - for (let i = 0; i < 8; i++) { + for (let i = 0; i < 14; i++) { await this.browser.keys(Key.ArrowDown); await this.browser.pause(PAUSE_TIME); } @@ -47,94 +47,377 @@ suite('Keyboard navigation', function () { const selectedId = await this.browser.execute(() => { return Blockly.common.getSelected()?.id; }); - chai.assert.equal(selectedId, 'draw_circle_1'); + chai.assert.equal(selectedId, 'controls_repeat_1'); }); test('Down from statement block selects next connection', async function () { - await focusWorkspace(this.browser); + await tabNavigateToWorkspace(this.browser); await this.browser.pause(PAUSE_TIME); - await setCurrentCursorNodeById(this.browser, 'create_canvas_1'); + await setCurrentCursorNodeById(this.browser, 'p5_canvas_1'); await this.browser.pause(PAUSE_TIME); await this.browser.keys(Key.ArrowDown); await this.browser.pause(PAUSE_TIME); + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('p5_canvas_1_connection_'); + chai.assert.equal( - await getCurrentCursorNodeId(this.browser), - 'create_canvas_1', - ); - chai.assert.equal( - await getCurrentCursorNodeType(this.browser), - Blockly.ASTNode.types.NEXT, + await getFocusedConnectionType(this.browser), + Blockly.ConnectionType.NEXT_STATEMENT, ); }); test("Up from statement block selects previous block's connection", async function () { - await focusWorkspace(this.browser); + await tabNavigateToWorkspace(this.browser); await this.browser.pause(PAUSE_TIME); - await setCurrentCursorNodeById(this.browser, 'set_background_color_1'); + await setCurrentCursorNodeById(this.browser, 'simple_circle_1'); await this.browser.pause(PAUSE_TIME); await this.browser.keys(Key.ArrowUp); await this.browser.pause(PAUSE_TIME); + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('draw_emoji_1_connection_'); + chai.assert.equal( - await getCurrentCursorNodeId(this.browser), - 'create_canvas_1', - ); - chai.assert.equal( - await getCurrentCursorNodeType(this.browser), - Blockly.ASTNode.types.NEXT, + await getFocusedConnectionType(this.browser), + Blockly.ConnectionType.NEXT_STATEMENT, ); }); test('Down from parent block selects input connection', async function () { - await focusWorkspace(this.browser); + await tabNavigateToWorkspace(this.browser); await this.browser.pause(PAUSE_TIME); await setCurrentCursorNodeById(this.browser, 'p5_setup_1'); await this.browser.pause(PAUSE_TIME); await this.browser.keys(Key.ArrowDown); await this.browser.pause(PAUSE_TIME); + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('p5_setup_1_connection_'); - chai.assert.equal(await getCurrentCursorNodeId(this.browser), 'p5_setup_1'); chai.assert.equal( - await getCurrentCursorNodeType(this.browser), - Blockly.ASTNode.types.INPUT, + await getFocusedConnectionType(this.browser), + Blockly.ConnectionType.NEXT_STATEMENT, ); }); test('Up from child block selects input connection', async function () { - await focusWorkspace(this.browser); + await tabNavigateToWorkspace(this.browser); await this.browser.pause(PAUSE_TIME); - await setCurrentCursorNodeById(this.browser, 'create_canvas_1'); + await setCurrentCursorNodeById(this.browser, 'p5_canvas_1'); await this.browser.pause(PAUSE_TIME); await this.browser.keys(Key.ArrowUp); await this.browser.pause(PAUSE_TIME); + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('p5_setup_1_connection_'); - chai.assert.equal(await getCurrentCursorNodeId(this.browser), 'p5_setup_1'); chai.assert.equal( - await getCurrentCursorNodeType(this.browser), - Blockly.ASTNode.types.INPUT, + await getFocusedConnectionType(this.browser), + Blockly.ConnectionType.NEXT_STATEMENT, ); }); test('Right from block selects first field', async function () { - await focusWorkspace(this.browser); + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'p5_canvas_1'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowRight); + await this.browser.pause(PAUSE_TIME); + + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('p5_canvas_1_field_'); + + chai.assert.equal(await getFocusedFieldName(this.browser), 'WIDTH'); + }); + + test('Right from block selects first inline input', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'simple_circle_1'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowRight); + await this.browser.pause(PAUSE_TIME); + + chai.assert.equal( + await getCurrentFocusNodeId(this.browser), + 'colour_picker_1', + ); + }); + + test('Up from inline input selects statement block', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'math_number_2'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowUp); + await this.browser.pause(PAUSE_TIME); + + chai.assert.equal( + await getCurrentFocusNodeId(this.browser), + 'controls_repeat_ext_1', + ); + }); + + test('Left from first inline input selects block', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'math_number_2'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowLeft); + await this.browser.pause(PAUSE_TIME); + + chai.assert.equal( + await getCurrentFocusNodeId(this.browser), + 'math_modulo_1', + ); + }); + + test('Right from first inline input selects second inline input', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'math_number_2'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowRight); + await this.browser.pause(PAUSE_TIME); + + chai.assert.equal( + await getCurrentFocusNodeId(this.browser), + 'math_number_3', + ); + }); + + test('Left from second inline input selects first inline input', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'math_number_3'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowLeft); + await this.browser.pause(PAUSE_TIME); + + chai.assert.equal( + await getCurrentFocusNodeId(this.browser), + 'math_number_2', + ); + }); + + // Test will fail until we update to a newer version of field-colour + test.skip("Right from last inline input selects block's next connection", async function () { + await tabNavigateToWorkspace(this.browser); await this.browser.pause(PAUSE_TIME); - await setCurrentCursorNodeById(this.browser, 'create_canvas_1'); + await setCurrentCursorNodeById(this.browser, 'colour_picker_1'); await this.browser.pause(PAUSE_TIME); await this.browser.keys(Key.ArrowRight); await this.browser.pause(PAUSE_TIME); + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('simple_circle_1_connection_'); + chai.assert.equal( - await getCurrentCursorNodeId(this.browser), - 'create_canvas_1', + await getFocusedConnectionType(this.browser), + Blockly.ConnectionType.NEXT_STATEMENT, ); + }); + + // Test will fail until we update to a newer version of field-colour + test.skip("Down from inline input selects block's next connection", async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'colour_picker_1'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowDown); + await this.browser.pause(PAUSE_TIME); + + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('simple_circle_1_connection_'); + + chai.assert.equal( + await getFocusedConnectionType(this.browser), + Blockly.ConnectionType.NEXT_STATEMENT, + ); + }); + + test("Down from inline input selects block's child connection", async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'math_number_2'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowDown); + await this.browser.pause(PAUSE_TIME); + + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('controls_repeat_ext_1_connection_'); + }); + + // This test fails because the curly quote icons get selected. + test.skip('Right from text block selects input and skips curly quote icons', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeById(this.browser, 'text_print_1'); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowRight); + await this.browser.pause(PAUSE_TIME); + + chai.assert.equal(await getCurrentFocusNodeId(this.browser), 'text_1'); + + await this.browser.keys(Key.ArrowRight); + await this.browser.pause(PAUSE_TIME); + chai.assert.equal( - await getCurrentCursorNodeType(this.browser), - Blockly.ASTNode.types.FIELD, + await getCurrentFocusNodeId(this.browser), + 'text_print_1', ); chai.assert.equal( - await getCurrentCursorNodeFieldName(this.browser), + await getCurrentFocusNodeId(this.browser), + Blockly.ASTNode.types.NEXT, + ); + }); +}); + +// TODO(#499) These tests fail because focusing on a field doesn't update the cursor +suite.skip('Keyboard navigation on Fields', function () { + // Setting timeout to unlimited as these tests take a longer time to run than most mocha test + this.timeout(0); + + // Setup Selenium for all of the tests + suiteSetup(async function () { + this.browser = await testSetup(testFileLocations.NAVIGATION_TEST_BLOCKS); + }); + + test('Up from first field selects block', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeByIdAndFieldName( + this.browser, + 'p5_canvas_1', + 'WIDTH', + ); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowUp); + await this.browser.pause(PAUSE_TIME); + + chai.assert.equal(await getCurrentFocusNodeId(this.browser), 'p5_canvas_1'); + }); + + test('Left from first field selects block', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeByIdAndFieldName( + this.browser, + 'p5_canvas_1', + 'WIDTH', + ); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowLeft); + await this.browser.pause(PAUSE_TIME); + + chai.assert.equal(await getCurrentFocusNodeId(this.browser), 'p5_canvas_1'); + }); + + test('Right from first field selects second field', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeByIdAndFieldName( + this.browser, + 'p5_canvas_1', + 'WIDTH', + ); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowRight); + await this.browser.pause(PAUSE_TIME); + + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('p5_canvas_1_field_'); + + chai.assert.equal(await getFocusedFieldName(this.browser), 'HIGHT'); + }); + + test('Left from second field selects first field', async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeByIdAndFieldName( + this.browser, + 'p5_canvas_1', + 'HEIGHT', + ); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowLeft); + await this.browser.pause(PAUSE_TIME); + + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('p5_canvas_1_field_'); + + chai.assert.equal(await getFocusedFieldName(this.browser), 'WIDTH'); + }); + + test("Right from second field selects block's next connection", async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeByIdAndFieldName( + this.browser, + 'p5_canvas_1', + 'HEIGHT', + ); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowRight); + await this.browser.pause(PAUSE_TIME); + + chai.assert.containSubset( + await getCurrentFocusNodeId(this.browser), + 'p5_canvas_1_connection_', + ); + }); + + test("Down from field selects block's next connection", async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeByIdAndFieldName( + this.browser, + 'p5_canvas_1', 'WIDTH', ); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowDown); + await this.browser.pause(PAUSE_TIME); + + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('p5_canvas_1_connection_'); + + chai.assert.equal( + await getFocusedConnectionType(this.browser), + Blockly.ConnectionType.NEXT_STATEMENT, + ); + }); + + test("Down from field selects block's child connection", async function () { + await tabNavigateToWorkspace(this.browser); + await this.browser.pause(PAUSE_TIME); + await setCurrentCursorNodeByIdAndFieldName( + this.browser, + 'controls_repeat_1', + 'TIMES', + ); + await this.browser.pause(PAUSE_TIME); + await this.browser.keys(Key.ArrowDown); + await this.browser.pause(PAUSE_TIME); + + chai + .expect(await getCurrentFocusNodeId(this.browser)) + .to.include('controls_repeat_1_connection_'); + + chai.assert.equal( + await getFocusedConnectionType(this.browser), + Blockly.ConnectionType.INPUT_VALUE, + ); }); }); diff --git a/test/webdriverio/test/clipboard_test.ts b/test/webdriverio/test/clipboard_test.ts index 6797c615..2af136e4 100644 --- a/test/webdriverio/test/clipboard_test.ts +++ b/test/webdriverio/test/clipboard_test.ts @@ -14,6 +14,7 @@ import { getSelectedBlockId, ElementWithId, tabNavigateToWorkspace, + setCurrentCursorNodeById, } from './test_setup.js'; import {Key, KeyAction, PointerAction, WheelAction} from 'webdriverio'; @@ -30,10 +31,7 @@ suite('Clipboard test', function () { test('Copy and paste while block selected', async function () { // Navigate to draw_circle_1. await tabNavigateToWorkspace(this.browser); - for (let i = 0; i < 8; i++) { - await this.browser.keys(Key.ArrowDown); - await this.browser.pause(PAUSE_TIME); - } + await setCurrentCursorNodeById(this.browser, 'draw_circle_1'); // Copy and paste await this.browser.keys([Key.Ctrl, 'c']); @@ -54,10 +52,7 @@ suite('Clipboard test', function () { test('Cut and paste while block selected', async function () { // Navigate to draw_circle_1. await tabNavigateToWorkspace(this.browser); - for (let i = 0; i < 8; i++) { - await this.browser.keys(Key.ArrowDown); - await this.browser.pause(PAUSE_TIME); - } + await setCurrentCursorNodeById(this.browser, 'draw_circle_1'); const block = await getBlockElementById(this.browser, 'draw_circle_1'); // Cut and paste diff --git a/test/webdriverio/test/test_setup.ts b/test/webdriverio/test/test_setup.ts index c244d7b8..4dc16ce6 100644 --- a/test/webdriverio/test/test_setup.ts +++ b/test/webdriverio/test/test_setup.ts @@ -134,6 +134,10 @@ const createTestUrl = (options?: URLSearchParams) => { export const testFileLocations = { BASE: createTestUrl(), // eslint-disable-next-line @typescript-eslint/naming-convention + NAVIGATION_TEST_BLOCKS: createTestUrl( + new URLSearchParams({scenario: 'navigationTestBlocks'}), + ), + // eslint-disable-next-line @typescript-eslint/naming-convention BASE_RTL: createTestUrl(new URLSearchParams({rtl: 'true'})), GERAS: createTestUrl(new URLSearchParams({renderer: 'geras'})), // eslint-disable-next-line @typescript-eslint/naming-convention @@ -179,76 +183,85 @@ export async function setCurrentCursorNodeById( ) { return await browser.execute((blockId) => { const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg; - const rootBlock = workspaceSvg.getBlockById(blockId); - if (rootBlock) { - workspaceSvg.getCursor()?.setCurNode(rootBlock); + const block = workspaceSvg.getBlockById(blockId); + if (block) { + block.getFocusableElement()?.focus(); } }, blockId); } /** - * Get the ID of the block at the current cursor node. + * Select a block with the given id as the current cursor node. + * + * @param browser The active WebdriverIO Browser object. + * @param blockId The id of the block to select. + * @param fieldName The name of the field on the block to select. + */ +export async function setCurrentCursorNodeByIdAndFieldName( + browser: WebdriverIO.Browser, + blockId: string, + fieldName: string, +) { + return await browser.execute( + (blockId, fieldName) => { + const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg; + const block = workspaceSvg.getBlockById(blockId); + const field = block?.getField(fieldName); + if (field) { + field.getFocusableElement()?.focus(); + } + }, + blockId, + fieldName, + ); +} + +/** + * Get the ID of the block that is currently focused. * * @param browser The active WebdriverIO Browser object. * @returns A Promise that resolves to the ID of the current cursor node. */ -export async function getCurrentCursorNodeId( +export async function getCurrentFocusNodeId( browser: WebdriverIO.Browser, ): Promise { return await browser.execute(() => { - const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg; - return workspaceSvg.getCursor()?.getSourceBlock()?.id; + return Blockly.getFocusManager().getFocusedNode()?.getFocusableElement() + ?.id; }); } /** - * Get the type of the current cursor node. + * Get the connection type of the current focused node. Assumes the current node + * is a connection. * * @param browser The active WebdriverIO Browser object. - * @returns A Promise that resolves to the type of the current cursor node. + * @returns A Promise that resolves to the connection type of the current cursor + * node. */ -export async function getCurrentCursorNodeType( +export async function getFocusedConnectionType( browser: WebdriverIO.Browser, -): Promise { +): Promise { return await browser.execute(() => { - const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg; - const node = workspaceSvg.getCursor()?.getCurNode(); - if (node instanceof Blockly.WorkspaceSvg) { - return 'workspace'; - } else if (node instanceof Blockly.BlockSvg) { - return 'block'; - } else if (node instanceof Blockly.Field) { - return 'field'; - } else if (node instanceof Blockly.FlyoutButton) { - return 'button'; - } else if (node instanceof Blockly.RenderedConnection) { - if (node.getParentInput()) { - return 'input'; - } - - if (node.type === Blockly.ConnectionType.OUTPUT_VALUE) { - return 'output'; - } else if (node.type === Blockly.ConnectionType.NEXT_STATEMENT) { - return 'next'; - } else if (node.type === Blockly.ConnectionType.PREVIOUS_STATEMENT) { - return 'previous'; - } - } + const connection = + Blockly.getFocusManager().getFocusedNode() as Blockly.RenderedConnection; + return connection.type; }); } /** - * Get the field name of the current cursor node. + * Get the field name of the current focused node. Assumes the current node + * is a field. * * @param browser The active WebdriverIO Browser object. - * @returns A Promise that resolves to the field name of the current cursor node. + * @returns A Promise that resolves to the field name of the current focused + * node. */ -export async function getCurrentCursorNodeFieldName( +export async function getFocusedFieldName( browser: WebdriverIO.Browser, ): Promise { return await browser.execute(() => { - const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg; - const field = workspaceSvg.getCursor()?.getCurNode() as Blockly.Field; + const field = Blockly.getFocusManager().getFocusedNode() as Blockly.Field; return field.name; }); }