From 231230e6da15b47a0a97694c5fcbb54faed280b3 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 11 Apr 2025 15:50:26 -0700 Subject: [PATCH 1/6] chore: tests for cursor getNextNode --- tests/mocha/cursor_test.js | 218 ++++++++++++++++++++++++++++++++++++- 1 file changed, 217 insertions(+), 1 deletion(-) diff --git a/tests/mocha/cursor_test.js b/tests/mocha/cursor_test.js index b2a38268866..5fe7834714f 100644 --- a/tests/mocha/cursor_test.js +++ b/tests/mocha/cursor_test.js @@ -385,4 +385,220 @@ suite('Cursor', function () { }); }); }); -}); + suite.only('Get next node', function () { + setup(function () { + sharedTestSetup.call(this); + Blockly.defineBlocksWithJsonArray([ + { + 'type': 'empty_block', + 'message0': '', + }, + { + 'type': 'stack_block', + 'message0': '%1', + 'args0': [ + { + 'type': 'field_input', + 'name': 'FIELD', + 'text': 'default', + }, + ], + 'previousStatement': null, + 'nextStatement': null, + }, + { + 'type': 'row_block', + 'message0': '%1 %2', + 'args0': [ + { + 'type': 'field_input', + 'name': 'FIELD', + 'text': 'default', + }, + { + 'type': 'input_value', + 'name': 'INPUT', + }, + ], + 'output': null, + }, + ]); + this.workspace = Blockly.inject('blocklyDiv', {}); + this.cursor = this.workspace.getCursor(); + this.neverValid = () => false; + this.alwaysValid = () => true; + this.isConnection = (node) => { + return node && node.isConnection(); + }; + }); + teardown(function () { + sharedTestTeardown.call(this); + }); + suite('stack', function () { + setup(function () { + const state = { + 'blocks': { + 'languageVersion': 0, + 'blocks': [ + { + 'type': 'stack_block', + 'id': 'A', + 'x': 0, + 'y': 0, + 'next': { + 'block': { + 'type': 'stack_block', + 'id': 'B', + 'next': { + 'block': { + 'type': 'stack_block', + 'id': 'C', + }, + }, + }, + }, + }, + ], + }, + }; + Blockly.serialization.workspaces.load(state, this.workspace); + this.blockA = this.workspace.getBlockById('A'); + this.blockB = this.workspace.getBlockById('B'); + this.blockC = this.workspace.getBlockById('C'); + }); + teardown(function () { + this.workspace.clear(); + }); + test('Never valid - start at top', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.neverValid, + false, + ); + assert.isNull(nextNode); + }); + test('Never valid - start in middle', function () { + const startNode = ASTNode.createBlockNode(this.blockB); + const nextNode = this.cursor.getNextNode( + startNode, + this.neverValid, + false, + ); + assert.isNull(nextNode); + }); + test('Never valid - start at end', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.neverValid, + false, + ); + assert.isNull(nextNode); + }); + + test('Always valid - start at top', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.alwaysValid, + false, + ); + assert.equal(nextNode.getLocation(), this.blockA); + }); + test('Always valid - start in middle', function () { + const startNode = ASTNode.createBlockNode(this.blockB); + const nextNode = this.cursor.getNextNode( + startNode, + this.alwaysValid, + false, + ); + assert.equal(nextNode.getLocation(), this.blockB.getField('FIELD')); + }); + test('Always valid - start at end', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.alwaysValid, + false, + ); + assert.isNull(nextNode); + }); + + test('Valid if connection - start at top', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.isConnection, + false, + ); + assert.equal(nextNode.getLocation(), this.blockA.nextConnection); + }); + test('Valid if connection - start in middle', function () { + const startNode = ASTNode.createBlockNode(this.blockB); + const nextNode = this.cursor.getNextNode( + startNode, + this.isConnection, + false, + ); + assert.equal(nextNode.getLocation(), this.blockB.nextConnection); + }); + test('Valid if connection - start at end', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.isConnection, + false, + ); + assert.isNull(nextNode); + }); + test('Never valid - start at end - with loopback', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.neverValid, + true, + ); + assert.isNull(nextNode); + }); + test('Always valid - start at end - with loopback', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.alwaysValid, + true, + ); + assert.equal(nextNode.getLocation(), this.blockA.previousConnection); + }); + + test('Valid if connection - start at end - with loopback', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const nextNode = this.cursor.getNextNode( + startNode, + this.isConnection, + true, + ); + // todo + assert.equal(nextNode.getLocation(), this.blockA.previousConnection); + }); + }); + }); +}); \ No newline at end of file From 8c1bdac99d7901c2087363e6a1c2fb96b5485a78 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 11 Apr 2025 16:26:46 -0700 Subject: [PATCH 2/6] chore: add tests for getPreviousNode --- tests/mocha/cursor_test.js | 226 ++++++++++++++++++++++++++++++++++++- 1 file changed, 223 insertions(+), 3 deletions(-) diff --git a/tests/mocha/cursor_test.js b/tests/mocha/cursor_test.js index 5fe7834714f..ddb4c7d147f 100644 --- a/tests/mocha/cursor_test.js +++ b/tests/mocha/cursor_test.js @@ -586,7 +586,7 @@ suite('Cursor', function () { ); assert.equal(nextNode.getLocation(), this.blockA.previousConnection); }); - + test('Valid if connection - start at end - with loopback', function () { const startNode = ASTNode.createConnectionNode( this.blockC.nextConnection, @@ -596,9 +596,229 @@ suite('Cursor', function () { this.isConnection, true, ); - // todo assert.equal(nextNode.getLocation(), this.blockA.previousConnection); }); }); }); -}); \ No newline at end of file + + suite.only('Get previous node', function () { + setup(function () { + sharedTestSetup.call(this); + Blockly.defineBlocksWithJsonArray([ + { + 'type': 'empty_block', + 'message0': '', + }, + { + 'type': 'stack_block', + 'message0': '%1', + 'args0': [ + { + 'type': 'field_input', + 'name': 'FIELD', + 'text': 'default', + }, + ], + 'previousStatement': null, + 'nextStatement': null, + }, + { + 'type': 'row_block', + 'message0': '%1 %2', + 'args0': [ + { + 'type': 'field_input', + 'name': 'FIELD', + 'text': 'default', + }, + { + 'type': 'input_value', + 'name': 'INPUT', + }, + ], + 'output': null, + }, + ]); + this.workspace = Blockly.inject('blocklyDiv', {}); + this.cursor = this.workspace.getCursor(); + this.neverValid = () => false; + this.alwaysValid = () => true; + this.isConnection = (node) => { + return node && node.isConnection(); + }; + }); + teardown(function () { + sharedTestTeardown.call(this); + }); + suite('stack', function () { + setup(function () { + const state = { + 'blocks': { + 'languageVersion': 0, + 'blocks': [ + { + 'type': 'stack_block', + 'id': 'A', + 'x': 0, + 'y': 0, + 'next': { + 'block': { + 'type': 'stack_block', + 'id': 'B', + 'next': { + 'block': { + 'type': 'stack_block', + 'id': 'C', + }, + }, + }, + }, + }, + ], + }, + }; + Blockly.serialization.workspaces.load(state, this.workspace); + this.blockA = this.workspace.getBlockById('A'); + this.blockB = this.workspace.getBlockById('B'); + this.blockC = this.workspace.getBlockById('C'); + }); + teardown(function () { + this.workspace.clear(); + }); + test('Never valid - start at top', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.neverValid, + false, + ); + assert.isNull(previousNode); + }); + test('Never valid - start in middle', function () { + const startNode = ASTNode.createBlockNode(this.blockB); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.neverValid, + false, + ); + assert.isNull(previousNode); + }); + test('Never valid - start at end', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.neverValid, + false, + ); + assert.isNull(previousNode); + }); + + test('Always valid - start at top', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.alwaysValid, + false, + ); + //assert.equal(previousNode.getLocation(), this.blockA); + assert.isNotNull(previousNode); + }); + test('Always valid - start in middle', function () { + const startNode = ASTNode.createBlockNode(this.blockB); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.alwaysValid, + false, + ); + assert.equal(previousNode.getLocation(), this.blockB.previousConnection); + //assert.isNotNull(previousNode); + }); + test('Always valid - start at end', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.alwaysValid, + false, + ); + assert.equal(previousNode.getLocation(), this.blockC.getField('FIELD')); + }); + + test('Valid if connection - start at top', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.isConnection, + false, + ); + assert.isNull(previousNode); + }); + test('Valid if connection - start in middle', function () { + const startNode = ASTNode.createBlockNode(this.blockB); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.isConnection, + false, + ); + assert.equal(previousNode.getLocation(), this.blockB.previousConnection); + //assert.equal(previousNode.getLocation(), this.blockB.nextConnection); + //assert.isNotNull(previousNode); + }); + test('Valid if connection - start at end', function () { + const startNode = ASTNode.createConnectionNode( + this.blockC.nextConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.isConnection, + false, + ); + assert.equal(previousNode.getLocation(), this.blockC.previousConnection); + //assert.isNull(previousNode); + }); + test('Never valid - start at top - with loopback', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.neverValid, + true, + ); + assert.isNull(previousNode); + }); + test('Always valid - start at top - with loopback', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.alwaysValid, + true, + ); + assert.equal(previousNode.getLocation(), this.blockC.nextConnection); + }); + + test('Valid if connection - start at top - with loopback', function () { + const startNode = ASTNode.createConnectionNode( + this.blockA.previousConnection, + ); + const previousNode = this.cursor.getPreviousNode( + startNode, + this.isConnection, + true, + ); + assert.equal(previousNode.getLocation(), this.blockC.nextConnection); + }); + }); + }); +}); From 2056aea6307edddaededaefed8883f420f811dee Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 11 Apr 2025 16:39:11 -0700 Subject: [PATCH 3/6] feat: add looping to getPreviousNode and getNextNode --- core/keyboard_nav/line_cursor.ts | 91 +++++++++++++++++++++++++++----- tests/mocha/cursor_test.js | 26 +++++---- 2 files changed, 93 insertions(+), 24 deletions(-) diff --git a/core/keyboard_nav/line_cursor.ts b/core/keyboard_nav/line_cursor.ts index d8e0a472bad..8d6e425323d 100644 --- a/core/keyboard_nav/line_cursor.ts +++ b/core/keyboard_nav/line_cursor.ts @@ -99,7 +99,11 @@ export class LineCursor extends Marker { if (!curNode) { return null; } - const newNode = this.getNextNode(curNode, this.validLineNode.bind(this)); + const newNode = this.getNextNode( + curNode, + this.validLineNode.bind(this), + true, + ); if (newNode) { this.setCurNode(newNode); @@ -119,7 +123,11 @@ export class LineCursor extends Marker { if (!curNode) { return null; } - const newNode = this.getNextNode(curNode, this.validInLineNode.bind(this)); + const newNode = this.getNextNode( + curNode, + this.validInLineNode.bind(this), + true, + ); if (newNode) { this.setCurNode(newNode); @@ -138,11 +146,10 @@ export class LineCursor extends Marker { if (!curNode) { return null; } - const newNode = this.getPreviousNode( + const newNode = this.getPreviousNodeImpl( curNode, this.validLineNode.bind(this), ); - if (newNode) { this.setCurNode(newNode); } @@ -161,7 +168,7 @@ export class LineCursor extends Marker { if (!curNode) { return null; } - const newNode = this.getPreviousNode( + const newNode = this.getPreviousNodeImpl( curNode, this.validInLineNode.bind(this), ); @@ -184,6 +191,7 @@ export class LineCursor extends Marker { const rightNode = this.getNextNode( curNode, this.validInLineNode.bind(this), + false, ); return this.validLineNode(rightNode); } @@ -299,7 +307,7 @@ export class LineCursor extends Marker { * should be traversed. * @returns The next node in the traversal. */ - getNextNode( + private getNextNodeImpl( node: ASTNode | null, isValid: (p1: ASTNode | null) => boolean, ): ASTNode | null { @@ -310,17 +318,44 @@ export class LineCursor extends Marker { if (isValid(newNode)) { return newNode; } else if (newNode) { - return this.getNextNode(newNode, isValid); + return this.getNextNodeImpl(newNode, isValid); } const siblingOrParentSibling = this.findSiblingOrParentSibling(node.out()); if (isValid(siblingOrParentSibling)) { return siblingOrParentSibling; } else if (siblingOrParentSibling) { - return this.getNextNode(siblingOrParentSibling, isValid); + return this.getNextNodeImpl(siblingOrParentSibling, isValid); } return null; } + /** + * Get the next node in the AST, optionally allowing for loopback. + * + * @param node The current position in the AST. + * @param isValid A function true/false depending on whether the given node + * should be traversed. + * @param boolean Whether to loop around to the beginning of the workspace if + * novalid node was found. + * @returns The next node in the traversal. + */ + getNextNode( + node: ASTNode | null, + isValid: (p1: ASTNode | null) => boolean, + loop: boolean, + ): ASTNode | null { + if (!node) { + return null; + } + + const potential = this.getNextNodeImpl(node, isValid); + if (potential || !loop) return potential; + // Loop back. + const firstNode = this.getFirstNode(); + if (isValid(firstNode)) return firstNode; + return this.getNextNodeImpl(firstNode, isValid); + } + /** * Reverses the pre order traversal in order to find the previous node. This * will allow a user to easily navigate the entire Blockly AST without having @@ -332,7 +367,7 @@ export class LineCursor extends Marker { * @returns The previous node in the traversal or null if no previous node * exists. */ - getPreviousNode( + private getPreviousNodeImpl( node: ASTNode | null, isValid: (p1: ASTNode | null) => boolean, ): ASTNode | null { @@ -349,11 +384,37 @@ export class LineCursor extends Marker { if (isValid(newNode)) { return newNode; } else if (newNode) { - return this.getPreviousNode(newNode, isValid); + return this.getPreviousNodeImpl(newNode, isValid); } return null; } + /** + * Get the previous node in the AST, optionally allowing for loopback. + * + * @param node The current position in the AST. + * @param isValid A function true/false depending on whether the given node + * should be traversed. + * @param boolean Whether to loop around to the end of the workspace if no + * valid node was found. + * @returns The previous node in the traversal or null if no previous node + * exists. + */ + getPreviousNode( + node: ASTNode | null, + isValid: (p1: ASTNode | null) => boolean, + loop: boolean, + ): ASTNode | null { + if (!node) { + return null; + } + const potential = this.getPreviousNodeImpl(node, isValid); + if (potential || !loop) return potential; + // Loop back. + const lastNode = this.getLastNode(); + if (isValid(lastNode)) return lastNode; + return this.getPreviousNodeImpl(lastNode, isValid); + } /** * From the given node find either the next valid sibling or the parent's * next sibling. @@ -787,9 +848,13 @@ export class LineCursor extends Marker { // Iterate until you fall off the end of the stack. while (nextNode) { prevNode = nextNode; - nextNode = this.getNextNode(prevNode, (node) => { - return !!node; - }); + nextNode = this.getNextNode( + prevNode, + (node) => { + return !!node; + }, + false, + ); } return prevNode; } diff --git a/tests/mocha/cursor_test.js b/tests/mocha/cursor_test.js index ddb4c7d147f..830185c1a04 100644 --- a/tests/mocha/cursor_test.js +++ b/tests/mocha/cursor_test.js @@ -385,7 +385,7 @@ suite('Cursor', function () { }); }); }); - suite.only('Get next node', function () { + suite('Get next node', function () { setup(function () { sharedTestSetup.call(this); Blockly.defineBlocksWithJsonArray([ @@ -601,7 +601,7 @@ suite('Cursor', function () { }); }); - suite.only('Get previous node', function () { + suite('Get previous node', function () { setup(function () { sharedTestSetup.call(this); Blockly.defineBlocksWithJsonArray([ @@ -726,7 +726,6 @@ suite('Cursor', function () { this.alwaysValid, false, ); - //assert.equal(previousNode.getLocation(), this.blockA); assert.isNotNull(previousNode); }); test('Always valid - start in middle', function () { @@ -736,8 +735,10 @@ suite('Cursor', function () { this.alwaysValid, false, ); - assert.equal(previousNode.getLocation(), this.blockB.previousConnection); - //assert.isNotNull(previousNode); + assert.equal( + previousNode.getLocation(), + this.blockB.previousConnection, + ); }); test('Always valid - start at end', function () { const startNode = ASTNode.createConnectionNode( @@ -769,9 +770,10 @@ suite('Cursor', function () { this.isConnection, false, ); - assert.equal(previousNode.getLocation(), this.blockB.previousConnection); - //assert.equal(previousNode.getLocation(), this.blockB.nextConnection); - //assert.isNotNull(previousNode); + assert.equal( + previousNode.getLocation(), + this.blockB.previousConnection, + ); }); test('Valid if connection - start at end', function () { const startNode = ASTNode.createConnectionNode( @@ -782,8 +784,10 @@ suite('Cursor', function () { this.isConnection, false, ); - assert.equal(previousNode.getLocation(), this.blockC.previousConnection); - //assert.isNull(previousNode); + assert.equal( + previousNode.getLocation(), + this.blockC.previousConnection, + ); }); test('Never valid - start at top - with loopback', function () { const startNode = ASTNode.createConnectionNode( @@ -796,7 +800,7 @@ suite('Cursor', function () { ); assert.isNull(previousNode); }); - test('Always valid - start at top - with loopback', function () { + test.skip('Always valid - start at top - with loopback', function () { const startNode = ASTNode.createConnectionNode( this.blockA.previousConnection, ); From f6ee669decd46e901f895d38c1043253ed5062cb Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 11 Apr 2025 16:52:15 -0700 Subject: [PATCH 4/6] chore: inline returns --- core/keyboard_nav/line_cursor.ts | 57 +++++++++++--------------------- 1 file changed, 19 insertions(+), 38 deletions(-) diff --git a/core/keyboard_nav/line_cursor.ts b/core/keyboard_nav/line_cursor.ts index 8d6e425323d..44c9a5c30b9 100644 --- a/core/keyboard_nav/line_cursor.ts +++ b/core/keyboard_nav/line_cursor.ts @@ -311,21 +311,14 @@ export class LineCursor extends Marker { node: ASTNode | null, isValid: (p1: ASTNode | null) => boolean, ): ASTNode | null { - if (!node) { - return null; - } - const newNode = node.in() || node.next(); - if (isValid(newNode)) { - return newNode; - } else if (newNode) { - return this.getNextNodeImpl(newNode, isValid); - } - const siblingOrParentSibling = this.findSiblingOrParentSibling(node.out()); - if (isValid(siblingOrParentSibling)) { - return siblingOrParentSibling; - } else if (siblingOrParentSibling) { - return this.getNextNodeImpl(siblingOrParentSibling, isValid); - } + if (!node) return null; + let newNode = node.in() || node.next(); + if (isValid(newNode)) return newNode; + if (newNode) return this.getNextNodeImpl(newNode, isValid); + + newNode = this.findSiblingOrParentSibling(node.out()); + if (isValid(newNode)) return newNode; + if (newNode) return this.getNextNodeImpl(newNode, isValid); return null; } @@ -344,9 +337,7 @@ export class LineCursor extends Marker { isValid: (p1: ASTNode | null) => boolean, loop: boolean, ): ASTNode | null { - if (!node) { - return null; - } + if (!node) return null; const potential = this.getNextNodeImpl(node, isValid); if (potential || !loop) return potential; @@ -371,9 +362,7 @@ export class LineCursor extends Marker { node: ASTNode | null, isValid: (p1: ASTNode | null) => boolean, ): ASTNode | null { - if (!node) { - return null; - } + if (!node) return null; let newNode: ASTNode | null = node.prev(); if (newNode) { @@ -381,13 +370,12 @@ export class LineCursor extends Marker { } else { newNode = node.out(); } - if (isValid(newNode)) { - return newNode; - } else if (newNode) { - return this.getPreviousNodeImpl(newNode, isValid); - } + + if (isValid(newNode)) return newNode; + if (newNode) return this.getPreviousNodeImpl(newNode, isValid); return null; } + /** * Get the previous node in the AST, optionally allowing for loopback. * @@ -404,9 +392,7 @@ export class LineCursor extends Marker { isValid: (p1: ASTNode | null) => boolean, loop: boolean, ): ASTNode | null { - if (!node) { - return null; - } + if (!node) return null; const potential = this.getPreviousNodeImpl(node, isValid); if (potential || !loop) return potential; @@ -415,6 +401,7 @@ export class LineCursor extends Marker { if (isValid(lastNode)) return lastNode; return this.getPreviousNodeImpl(lastNode, isValid); } + /** * From the given node find either the next valid sibling or the parent's * next sibling. @@ -423,13 +410,9 @@ export class LineCursor extends Marker { * @returns The next sibling node, the parent's next sibling, or null. */ private findSiblingOrParentSibling(node: ASTNode | null): ASTNode | null { - if (!node) { - return null; - } + if (!node) return null; const nextNode = node.next(); - if (nextNode) { - return nextNode; - } + if (nextNode) return nextNode; return this.findSiblingOrParentSibling(node.out()); } @@ -442,9 +425,7 @@ export class LineCursor extends Marker { */ private getRightMostChild(node: ASTNode): ASTNode | null { let newNode = node.in(); - if (!newNode) { - return node; - } + if (!newNode) return node; for ( let nextNode: ASTNode | null = newNode; nextNode; From 99963f1ebd4ffc88aec60bdeade72bb4ac920fc7 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 11 Apr 2025 17:07:44 -0700 Subject: [PATCH 5/6] chore: fix test that results in a stack node --- tests/mocha/cursor_test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/mocha/cursor_test.js b/tests/mocha/cursor_test.js index 830185c1a04..905f48c09ad 100644 --- a/tests/mocha/cursor_test.js +++ b/tests/mocha/cursor_test.js @@ -800,7 +800,7 @@ suite('Cursor', function () { ); assert.isNull(previousNode); }); - test.skip('Always valid - start at top - with loopback', function () { + test('Always valid - start at top - with loopback', function () { const startNode = ASTNode.createConnectionNode( this.blockA.previousConnection, ); @@ -809,9 +809,9 @@ suite('Cursor', function () { this.alwaysValid, true, ); - assert.equal(previousNode.getLocation(), this.blockC.nextConnection); + // Previous node will be a stack node in this case. + assert.equal(previousNode.getLocation(), this.blockA); }); - test('Valid if connection - start at top - with loopback', function () { const startNode = ASTNode.createConnectionNode( this.blockA.previousConnection, From 527f5bc28100002eab1ca0e39251c45a6ad4df34 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 11 Apr 2025 17:19:06 -0700 Subject: [PATCH 6/6] chore: fix annotations --- core/keyboard_nav/line_cursor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/keyboard_nav/line_cursor.ts b/core/keyboard_nav/line_cursor.ts index 44c9a5c30b9..b2bda39c739 100644 --- a/core/keyboard_nav/line_cursor.ts +++ b/core/keyboard_nav/line_cursor.ts @@ -328,7 +328,7 @@ export class LineCursor extends Marker { * @param node The current position in the AST. * @param isValid A function true/false depending on whether the given node * should be traversed. - * @param boolean Whether to loop around to the beginning of the workspace if + * @param loop Whether to loop around to the beginning of the workspace if * novalid node was found. * @returns The next node in the traversal. */ @@ -382,7 +382,7 @@ export class LineCursor extends Marker { * @param node The current position in the AST. * @param isValid A function true/false depending on whether the given node * should be traversed. - * @param boolean Whether to loop around to the end of the workspace if no + * @param loop Whether to loop around to the end of the workspace if no * valid node was found. * @returns The previous node in the traversal or null if no previous node * exists.