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;
});
}