Skip to content
Open
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
26 changes: 14 additions & 12 deletions packages/blockly/core/block_aria_composer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,7 @@ export function getInputLabels(
): string[] {
return block.inputList
.filter((input) => input.isVisible())
.map((input) =>
input.getAriaLabelText() !== null
? input.getAriaLabelText()!
: input.getLabel(verbosity),
);
.map((input) => input.getAriaLabelText() ?? input.getLabel(verbosity));
Copy link
Copy Markdown
Contributor Author

@mikeharv mikeharv May 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't change anything functionally, but using nullish is safe because it expresses the intended “use this unless it's null” logic directly, while avoiding both a duplicate method call and an unnecessary non-null assertion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, I was under the impression that nullish coalescing was unsafe here because empty string evaluates to falsy but looks like the MDN documentation says that's not the case. Thanks, I wanted to do that to begin with. :D

}

/**
Expand Down Expand Up @@ -378,14 +374,20 @@ function computeMoveConnectionLabel(
const input = conn.getParentInput();
if (!input) return baseLabel;

const labels = getInputLabelsSubset(
conn.getSourceBlock(),
input,
Verbosity.TERSE,
);
if (!labels.length) return baseLabel;
let inputLabel = input.getAriaLabelText();

const inputLabel = labels.join(', ');
// If the input doesn't have a custom ARIA label, compute one using the labels from
// nearby fields.
if (!inputLabel) {
const labels = getInputLabelsSubset(
conn.getSourceBlock(),
input,
Verbosity.TERSE,
);
if (!labels.length) return baseLabel;

inputLabel = labels.join(', ');
}

return baseLabel
? Msg['ANNOUNCE_MOVE_OF'].replace('%1', inputLabel).replace('%2', baseLabel)
Expand Down
86 changes: 44 additions & 42 deletions packages/blockly/tests/mocha/keyboard_movement_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import {getInputLabelsSubset} from '../../build/src/core/block_aria_composer.js';
import * as Blockly from '../../build/src/core/blockly.js';
import {Verbosity} from '../../build/src/core/utils/aria.js';
import {assert} from '../../node_modules/chai/index.js';
import {
moveStatementTestBlocks,
Expand Down Expand Up @@ -1143,12 +1141,6 @@ suite('Keyboard-driven movement', function () {
};
this.getBlockLabel = (block) =>
block.getAriaLabel(Blockly.utils.aria.Verbosity.TERSE);
this.getInputLabel = (block, input) =>
getInputLabelsSubset(
block,
block.getInput(input),
Verbosity.TERSE,
).join(', ');
this.block1 = this.workspace.newBlock('draw_emoji');
this.block1.initSvg();
this.block1.render();
Expand All @@ -1158,7 +1150,7 @@ suite('Keyboard-driven movement', function () {
Blockly.getFocusManager().focusNode(this.block1);
this.moveAndAssert(
startMove,
['Moving', this.getBlockLabel(this.block1), 'on workspace.'],
['Moving', 'draw', '❤️', 'on workspace.'],
[],
);
cancelMove(this.workspace);
Expand Down Expand Up @@ -1190,7 +1182,7 @@ suite('Keyboard-driven movement', function () {
startMove(this.workspace);
this.moveAndAssert(
moveRight,
['Moving', 'before', this.getBlockLabel(block2)],
['Moving', 'before', 'draw', '✨'],
[this.getBlockLabel(this.block1)],
);

Expand All @@ -1208,9 +1200,11 @@ suite('Keyboard-driven movement', function () {

this.moveAndAssert(startMove, [
'Moving',
this.getBlockLabel(block2),
'draw',
'✨',
'after',
this.getBlockLabel(this.block1),
'draw',
'❤️',
]);

cancelMove(this.workspace);
Expand All @@ -1229,7 +1223,7 @@ suite('Keyboard-driven movement', function () {
this.clock.tick(10);
this.moveAndAssert(
moveRight,
['Moving', 'to', this.getBlockLabel(parent)],
['Moving', 'to', 'print'],
[this.getBlockLabel(valueBlock)],
);

Expand All @@ -1247,8 +1241,8 @@ suite('Keyboard-driven movement', function () {

this.moveAndAssert(
moveRight,
['Moving', 'around', this.getBlockLabel(this.block1)],
[this.getBlockLabel(loop), this.getInputLabel(loop, 'DO')],
['Moving', 'around', 'draw', '❤️'],
[this.getBlockLabel(loop)],
);

cancelMove(this.workspace);
Expand All @@ -1268,27 +1262,46 @@ suite('Keyboard-driven movement', function () {
this.clock.tick(10);
this.moveAndAssert(
moveRight,
[
'Moving',
this.getInputLabel(ifBlock, 'DO1'),
'around',
this.getBlockLabel(this.block1),
],
['Moving', 'else if, do', 'around', 'draw', '❤️'],
[this.getBlockLabel(ifBlock)],
);
this.moveAndAssert(
moveRight,
[
'Moving',
this.getInputLabel(ifBlock, 'DO0'),
'around',
this.getBlockLabel(this.block1),
],
['Moving', 'if, do', 'around', 'draw', '❤️'],
[this.getBlockLabel(ifBlock)],
);

cancelMove(this.workspace);
});
test('disambiguates with custom input labels', function () {
const ifBlock = this.workspace.newBlock('controls_if');
ifBlock.initSvg();
ifBlock.elseifCount_ = 1;
ifBlock.elseCount_ = 1;
ifBlock.updateShape_();
ifBlock.render();
ifBlock.getInput('DO1').setAriaLabelProvider('custom else if branch');
this.workspace.cleanUp();

Blockly.getFocusManager().focusNode(ifBlock);
startMove(this.workspace); // on workspace
moveRight(this.workspace); // before block1
this.clock.tick(10);
this.moveAndAssert(
moveRight,
['Moving', 'custom else if branch', 'around', 'draw', '❤️'],
['else if, do'],
);
cancelMove(this.workspace);
Blockly.getFocusManager().focusNode(this.block1);
this.clock.tick(10);
this.moveAndAssert(
startMove,
['Moving', 'inside', 'custom else if branch'],
['else if, do'],
);
cancelMove(this.workspace);
});
test('disambiguates between multiple value inputs', function () {
const compare = this.workspace.newBlock('logic_compare');
compare.initSvg();
Expand All @@ -1300,25 +1313,14 @@ suite('Keyboard-driven movement', function () {
Blockly.getFocusManager().focusNode(boolean);
startMove(this.workspace);
this.clock.tick(10);
console.log([this.getBlockLabel(compare), this.getBlockLabel(boolean)]);
this.moveAndAssert(
moveRight,
[
'Moving',
'to',
this.getBlockLabel(compare),
this.getInputLabel(compare, 'A'),
],
['Moving', 'to', '=', 'input 1'],
[this.getBlockLabel(boolean)],
);
this.moveAndAssert(
moveRight,
[
'Moving',
'to',
this.getBlockLabel(compare),
this.getInputLabel(compare, 'B'),
],
['Moving', 'to', '=', '='],
[this.getBlockLabel(boolean)],
);

Expand All @@ -1340,12 +1342,12 @@ suite('Keyboard-driven movement', function () {
this.clock.tick(10);
this.moveAndAssert(
moveRight,
['Moving', 'to', this.getBlockLabel(textJoin), 'input 2'],
['Moving', 'to', 'create text with', 'input 2'],
[this.getBlockLabel(text)],
);
this.moveAndAssert(
moveRight,
['Moving', 'to', this.getBlockLabel(textJoin), 'input 3'],
['Moving', 'to', 'create text with', 'input 3'],
[this.getBlockLabel(text)],
);

Expand Down
Loading