|
4 | 4 | */ |
5 | 5 | import * as Blockly from 'blockly/core' |
6 | 6 | import { afterAll, afterEach, assert, beforeAll, beforeEach, describe, expect, it } from 'vitest' |
7 | | -import { registerDeleteBlock } from '../../src/context_menu_items' |
| 7 | +import { deleteBlock, registerDeleteBlock } from '../../src/context_menu_items' |
8 | 8 |
|
9 | 9 | // Tests for the scratch-specific delete context menu override (registerDeleteBlock). |
10 | 10 | // The copy/cut/paste override (registerDuplicateBlock, issue #3470) is tested |
@@ -171,4 +171,48 @@ describe('registerDeleteBlock', () => { |
171 | 171 | delete Blockly.Blocks.test_output_block |
172 | 172 | } |
173 | 173 | }) |
| 174 | + |
| 175 | + it('callback deletes only a top stack block and preserves its next block', () => { |
| 176 | + const first = workspace.newBlock('test_stack_block') |
| 177 | + const second = workspace.newBlock('test_stack_block') |
| 178 | + const nextConn = first.nextConnection |
| 179 | + const prevConn = second.previousConnection |
| 180 | + assert(nextConn, 'Expected next connection') |
| 181 | + assert(prevConn, 'Expected previous connection') |
| 182 | + nextConn.connect(prevConn) |
| 183 | + |
| 184 | + const item = Blockly.ContextMenuRegistry.registry.getItem('blockDelete') |
| 185 | + assert(item, 'Expected blockDelete item to be registered') |
| 186 | + const callback = item.callback as (scope: Blockly.ContextMenuRegistry.Scope) => void |
| 187 | + callback({ block: asBlockSvg(first) }) |
| 188 | + |
| 189 | + expect(workspace.getAllBlocks(false)).toEqual([second]) |
| 190 | + expect(second.getParent()).toBeNull() |
| 191 | + }) |
| 192 | + |
| 193 | + it('checkAndDelete override routes through deleteBlock and preserves next block', () => { |
| 194 | + const first = workspace.newBlock('test_stack_block') |
| 195 | + const second = workspace.newBlock('test_stack_block') |
| 196 | + const nextConn = first.nextConnection |
| 197 | + const prevConn = second.previousConnection |
| 198 | + assert(nextConn, 'Expected next connection') |
| 199 | + assert(prevConn, 'Expected previous connection') |
| 200 | + nextConn.connect(prevConn) |
| 201 | + |
| 202 | + // Mirror the wiring in src/index.ts so we cover the keyboard-delete path. |
| 203 | + // Tests use plain Workspace (not WorkspaceSvg), so blocks aren't BlockSvg |
| 204 | + // instances — invoke the override via prototype to simulate the call site. |
| 205 | + const originalCheckAndDelete = Blockly.BlockSvg.prototype.checkAndDelete |
| 206 | + Blockly.BlockSvg.prototype.checkAndDelete = function () { |
| 207 | + deleteBlock(this) |
| 208 | + } |
| 209 | + try { |
| 210 | + Blockly.BlockSvg.prototype.checkAndDelete.call(first) |
| 211 | + } finally { |
| 212 | + Blockly.BlockSvg.prototype.checkAndDelete = originalCheckAndDelete |
| 213 | + } |
| 214 | + |
| 215 | + expect(workspace.getAllBlocks(false)).toEqual([second]) |
| 216 | + expect(second.getParent()).toBeNull() |
| 217 | + }) |
174 | 218 | }) |
0 commit comments