diff --git a/core/block_svg.ts b/core/block_svg.ts index d8ac52e29e0..ec39e681445 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -365,6 +365,7 @@ export class BlockSvg this.workspace.getCanvas().appendChild(svg); } this.initialized = true; + this.recomputeAriaLabel(); } /** diff --git a/core/rendered_connection.ts b/core/rendered_connection.ts index f824cdb38f9..ffef106f579 100644 --- a/core/rendered_connection.ts +++ b/core/rendered_connection.ts @@ -688,7 +688,7 @@ export class RenderedConnection /** See IFocusableNode.canBeFocused. */ canBeFocused(): boolean { - return true; + return this.findHighlightSvg() !== null; } private findHighlightSvg(): SVGPathElement | null { diff --git a/core/utils/dom.ts b/core/utils/dom.ts index e32cad4d604..a7fc35dc3a5 100644 --- a/core/utils/dom.ts +++ b/core/utils/dom.ts @@ -64,7 +64,7 @@ export function createSvgElement( opt_parent.appendChild(e); } if (name === Svg.SVG || name === Svg.G) { - aria.setRole(e, aria.Role.PRESENTATION); + aria.setRole(e, aria.Role.GENERIC); } return e; } diff --git a/tests/mocha/cursor_test.js b/tests/mocha/cursor_test.js index 2273ec4b381..6816cf8c1e7 100644 --- a/tests/mocha/cursor_test.js +++ b/tests/mocha/cursor_test.js @@ -342,7 +342,7 @@ suite('Cursor', function () { }); suite('one empty block', function () { setup(function () { - this.blockA = this.workspace.newBlock('empty_block'); + this.blockA = createRenderedBlock(this.workspace, 'empty_block'); }); teardown(function () { this.workspace.clear(); @@ -359,7 +359,7 @@ suite('Cursor', function () { suite('one stack block', function () { setup(function () { - this.blockA = this.workspace.newBlock('stack_block'); + this.blockA = createRenderedBlock(this.workspace, 'stack_block'); }); teardown(function () { this.workspace.clear(); @@ -376,7 +376,7 @@ suite('Cursor', function () { suite('one row block', function () { setup(function () { - this.blockA = this.workspace.newBlock('row_block'); + this.blockA = createRenderedBlock(this.workspace, 'row_block'); }); teardown(function () { this.workspace.clear(); @@ -392,7 +392,7 @@ suite('Cursor', function () { }); suite('one c-hat block', function () { setup(function () { - this.blockA = this.workspace.newBlock('c_hat_block'); + this.blockA = createRenderedBlock(this.workspace, 'c_hat_block'); }); teardown(function () { this.workspace.clear(); diff --git a/tests/mocha/navigation_test.js b/tests/mocha/navigation_test.js index 3a9292b9209..37972318d50 100644 --- a/tests/mocha/navigation_test.js +++ b/tests/mocha/navigation_test.js @@ -5,10 +5,10 @@ */ import {assert} from '../../node_modules/chai/index.js'; +import {createRenderedBlock} from './test_helpers/block_definitions.js'; import { sharedTestSetup, sharedTestTeardown, - workspaceTeardown, } from './test_helpers/setup_teardown.js'; suite('Navigation', function () { @@ -89,13 +89,28 @@ suite('Navigation', function () { ]); this.workspace = Blockly.inject('blocklyDiv', {}); this.navigator = this.workspace.getNavigator(); - const statementInput1 = this.workspace.newBlock('input_statement'); - const statementInput2 = this.workspace.newBlock('input_statement'); - const statementInput3 = this.workspace.newBlock('input_statement'); - const statementInput4 = this.workspace.newBlock('input_statement'); - const fieldWithOutput = this.workspace.newBlock('field_input'); - const doubleValueInput = this.workspace.newBlock('double_value_input'); - const valueInput = this.workspace.newBlock('value_input'); + const statementInput1 = createRenderedBlock( + this.workspace, + 'input_statement', + ); + const statementInput2 = createRenderedBlock( + this.workspace, + 'input_statement', + ); + const statementInput3 = createRenderedBlock( + this.workspace, + 'input_statement', + ); + const statementInput4 = createRenderedBlock( + this.workspace, + 'input_statement', + ); + const fieldWithOutput = createRenderedBlock(this.workspace, 'field_input'); + const doubleValueInput = createRenderedBlock( + this.workspace, + 'double_value_input', + ); + const valueInput = createRenderedBlock(this.workspace, 'value_input'); statementInput1.nextConnection.connect(statementInput2.previousConnection); statementInput1.inputList[0].connection.connect( @@ -355,13 +370,25 @@ suite('Navigation', function () { 'helpUrl': '', }, ]); - const noNextConnection = this.workspace.newBlock('top_connection'); - const fieldAndInputs = this.workspace.newBlock('fields_and_input'); - const twoFields = this.workspace.newBlock('two_fields'); - const fieldAndInputs2 = this.workspace.newBlock('fields_and_input2'); - const noPrevConnection = this.workspace.newBlock('start_block'); - const hiddenField = this.workspace.newBlock('hidden_field'); - const hiddenInput = this.workspace.newBlock('hidden_input'); + const noNextConnection = createRenderedBlock( + this.workspace, + 'top_connection', + ); + const fieldAndInputs = createRenderedBlock( + this.workspace, + 'fields_and_input', + ); + const twoFields = createRenderedBlock(this.workspace, 'two_fields'); + const fieldAndInputs2 = createRenderedBlock( + this.workspace, + 'fields_and_input2', + ); + const noPrevConnection = createRenderedBlock( + this.workspace, + 'start_block', + ); + const hiddenField = createRenderedBlock(this.workspace, 'hidden_field'); + const hiddenInput = createRenderedBlock(this.workspace, 'hidden_input'); this.blocks.noNextConnection = noNextConnection; this.blocks.fieldAndInputs = fieldAndInputs; this.blocks.twoFields = twoFields; @@ -373,28 +400,47 @@ suite('Navigation', function () { hiddenField.inputList[0].fieldRow[1].setVisible(false); hiddenInput.inputList[1].setVisible(false); - const dummyInput = this.workspace.newBlock('dummy_input'); - const dummyInputValue = this.workspace.newBlock('dummy_inputValue'); - const fieldWithOutput2 = this.workspace.newBlock('field_input'); + const dummyInput = createRenderedBlock(this.workspace, 'dummy_input'); + const dummyInputValue = createRenderedBlock( + this.workspace, + 'dummy_inputValue', + ); + const fieldWithOutput2 = createRenderedBlock( + this.workspace, + 'field_input', + ); this.blocks.dummyInput = dummyInput; this.blocks.dummyInputValue = dummyInputValue; this.blocks.fieldWithOutput2 = fieldWithOutput2; - const secondBlock = this.workspace.newBlock('input_statement'); - const outputNextBlock = this.workspace.newBlock('output_next'); + const secondBlock = createRenderedBlock( + this.workspace, + 'input_statement', + ); + const outputNextBlock = createRenderedBlock( + this.workspace, + 'output_next', + ); this.blocks.secondBlock = secondBlock; this.blocks.outputNextBlock = outputNextBlock; - const buttonBlock = this.workspace.newBlock('buttons', 'button_block'); - const buttonInput1 = this.workspace.newBlock( + const buttonBlock = createRenderedBlock( + this.workspace, + 'buttons', + 'button_block', + ); + const buttonInput1 = createRenderedBlock( + this.workspace, 'field_input', 'button_input1', ); - const buttonInput2 = this.workspace.newBlock( + const buttonInput2 = createRenderedBlock( + this.workspace, 'field_input', 'button_input2', ); - const buttonNext = this.workspace.newBlock( + const buttonNext = createRenderedBlock( + this.workspace, 'input_statement', 'button_next', ); @@ -420,15 +466,6 @@ suite('Navigation', function () { this.workspace.cleanUp(); }); suite('Next', function () { - setup(function () { - this.singleBlockWorkspace = new Blockly.Workspace(); - const singleBlock = this.singleBlockWorkspace.newBlock('two_fields'); - this.blocks.singleBlock = singleBlock; - }); - teardown(function () { - workspaceTeardown.call(this, this.singleBlockWorkspace); - }); - test('fromPreviousToBlock', function () { const prevConnection = this.blocks.statementInput1.previousConnection; const nextNode = this.navigator.getNextSibling(prevConnection); @@ -471,8 +508,6 @@ suite('Navigation', function () { }); test('fromFieldToNestedBlock', function () { const field = this.blocks.statementInput1.inputList[0].fieldRow[1]; - const inputConnection = - this.blocks.statementInput1.inputList[0].connection; const nextNode = this.navigator.getNextSibling(field); assert.equal(nextNode, this.blocks.fieldWithOutput); }); @@ -576,7 +611,6 @@ suite('Navigation', function () { const prevNode = this.navigator.getPreviousSibling( this.blocks.fieldWithOutput, ); - const outputConnection = this.blocks.fieldWithOutput.outputConnection; assert.equal(prevNode, [...this.blocks.statementInput1.getFields()][1]); }); test('fromNextToBlock', function () { @@ -617,14 +651,12 @@ suite('Navigation', function () { assert.isNull(prevNode); }); test('fromFieldToInput', function () { - const outputBlock = this.workspace.newBlock('field_input'); + const outputBlock = createRenderedBlock(this.workspace, 'field_input'); this.blocks.fieldAndInputs2.inputList[0].connection.connect( outputBlock.outputConnection, ); const field = this.blocks.fieldAndInputs2.inputList[1].fieldRow[0]; - const inputConnection = - this.blocks.fieldAndInputs2.inputList[0].connection; const prevNode = this.navigator.getPreviousSibling(field); assert.equal(prevNode, outputBlock); }); @@ -701,18 +733,13 @@ suite('Navigation', function () { }); suite('In', function () { - setup(function () { - this.emptyWorkspace = Blockly.inject(document.createElement('div'), {}); - }); - teardown(function () { - workspaceTeardown.call(this, this.emptyWorkspace); - }); - test('fromInputToOutput', function () { + // The first child is the connected block since the connection itself + // cannot be navigated to directly. const input = this.blocks.statementInput1.inputList[0]; const inNode = this.navigator.getFirstChild(input.connection); - const outputConnection = this.blocks.fieldWithOutput.outputConnection; - assert.equal(inNode, outputConnection); + const connectedBlock = this.blocks.fieldWithOutput; + assert.equal(inNode, connectedBlock); }); test('fromInputToNull', function () { const input = this.blocks.statementInput2.inputList[0]; diff --git a/tests/mocha/test_helpers/block_definitions.js b/tests/mocha/test_helpers/block_definitions.js index 26507b29cb8..e5ca106d2c4 100644 --- a/tests/mocha/test_helpers/block_definitions.js +++ b/tests/mocha/test_helpers/block_definitions.js @@ -196,8 +196,8 @@ export function createTestBlock() { }; } -export function createRenderedBlock(workspaceSvg, type) { - const block = workspaceSvg.newBlock(type); +export function createRenderedBlock(workspaceSvg, type, opt_id) { + const block = workspaceSvg.newBlock(type, opt_id); block.initSvg(); block.render(); return block;