Skip to content

Commit 9fe5362

Browse files
committed
fix: Fix bug that caused input blocks to bump immovable blocks on insert.
1 parent 7eb748b commit 9fe5362

File tree

3 files changed

+78
-12
lines changed

3 files changed

+78
-12
lines changed

src/navigation.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -414,19 +414,33 @@ export class Navigation {
414414
const inputType = movingHasOutput
415415
? Blockly.inputs.inputTypes.VALUE
416416
: Blockly.inputs.inputTypes.STATEMENT;
417-
const compatibleInputs = stationaryNode.inputList.filter(
418-
(input) => input.type === inputType,
419-
);
420-
const input = compatibleInputs.length > 0 ? compatibleInputs[0] : null;
421-
let connection = input?.connection;
422-
if (connection) {
417+
const compatibleConnections = stationaryNode.inputList
418+
.filter((input) => input.type === inputType)
419+
.map((input) => input.connection);
420+
for (const connection of compatibleConnections) {
421+
let targetConnection: Blockly.Connection | null | undefined =
422+
connection;
423423
if (inputType === Blockly.inputs.inputTypes.STATEMENT) {
424-
while (connection.targetBlock()?.nextConnection) {
425-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
426-
connection = connection.targetBlock()!.nextConnection!;
424+
while (targetConnection?.targetBlock()?.nextConnection) {
425+
targetConnection = targetConnection?.targetBlock()?.nextConnection;
427426
}
428427
}
429-
return connection as Blockly.RenderedConnection;
428+
429+
if (
430+
targetConnection &&
431+
movingBlock.workspace.connectionChecker.canConnect(
432+
movingHasOutput
433+
? movingBlock.outputConnection
434+
: movingBlock.previousConnection,
435+
targetConnection,
436+
true,
437+
// Since we're connecting programmatically, we don't care how
438+
// close the blocks are when determining if they can be connected.
439+
Infinity,
440+
)
441+
) {
442+
return targetConnection as Blockly.RenderedConnection;
443+
}
430444
}
431445

432446
// 2. Connect statement blocks to next connection. Only return a next
@@ -442,6 +456,8 @@ export class Navigation {
442456
movingBlock.previousConnection,
443457
nextConnection,
444458
true,
459+
// Since we're connecting programmatically, we don't care how
460+
// close the blocks are when determining if they can be connected.
445461
Infinity,
446462
)
447463
) {

test/loadTestBlocks.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ const moreBlocks = {
343343
'DO0': {
344344
'block': {
345345
'type': 'text_print',
346-
'id': 'uSxT~QT8p%D2o)b~)Dki',
346+
'id': 'text_print_2',
347347
'inputs': {
348348
'TEXT': {
349349
'shadow': {
@@ -388,7 +388,7 @@ const moreBlocks = {
388388
'next': {
389389
'block': {
390390
'type': 'text_print',
391-
'id': '-bTQ2YVSuBS/SYn[C^LX',
391+
'id': 'text_print_3',
392392
'inputs': {
393393
'TEXT': {
394394
'shadow': {

test/webdriverio/test/insert_test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
testSetup,
1818
sendKeyAndWait,
1919
keyRight,
20+
keyDown,
2021
getCurrentFocusedBlockId,
2122
blockIsPresent,
2223
keyUp,
@@ -133,3 +134,52 @@ suite('Insert test', function () {
133134
);
134135
});
135136
});
137+
138+
suite('Insert test with more blocks', function () {
139+
// Disable timeouts when non-zero PAUSE_TIME is used to watch tests run.
140+
if (PAUSE_TIME) this.timeout(0);
141+
142+
// Clear the workspace and load start blocks.
143+
setup(async function () {
144+
this.browser = await testSetup(
145+
testFileLocations.MORE_BLOCKS,
146+
this.timeout(),
147+
);
148+
await this.browser.pause(PAUSE_TIME);
149+
});
150+
151+
test('Does not bump immovable input blocks on insert', async function () {
152+
// Focus the print block with a connected input block. Ordinarily, inserting
153+
// an input block would connect it to this block and bump its child, but
154+
// if all blocks are immovable the connected input block should not move
155+
// and the newly inserted block should be added as a top-level block on the
156+
// workspace.
157+
await focusOnBlock(this.browser, 'text_print_2');
158+
await this.browser.execute(() => {
159+
Blockly.getMainWorkspace()
160+
.getAllBlocks()
161+
.forEach((b) => b.setMovable(false));
162+
});
163+
await tabNavigateToToolbox(this.browser);
164+
165+
// Insert number block
166+
await keyDown(this.browser, 2);
167+
await keyRight(this.browser);
168+
// Choose.
169+
await sendKeyAndWait(this.browser, Key.Enter);
170+
// Confirm position.
171+
await sendKeyAndWait(this.browser, Key.Enter);
172+
173+
// Assert inserted at the top-level due to immovable block occupying the
174+
// selected block's input.
175+
chai.assert.equal('math_number', await getFocusedBlockType(this.browser));
176+
const focusedBlockIsParentless = await this.browser.execute(() => {
177+
const focusedNode = Blockly.getFocusManager().getFocusedNode();
178+
return (
179+
focusedNode instanceof Blockly.BlockSvg &&
180+
focusedNode.getParent() === null
181+
);
182+
});
183+
chai.assert.isTrue(focusedBlockIsParentless);
184+
});
185+
});

0 commit comments

Comments
 (0)