Skip to content

Commit e9920a5

Browse files
authored
feat!: allow blocks to receive their own delete events (#6337)
* feat!: allow blocks to receive their own delete events * fix: move block tests back into main directory * chore: add a test for disposing of callers * chore: add test for delete being received * chore: add comment about why we have to run the clock twice * chore: fix whitespace * chore: fix whitespace * chore: fix imports in tests * chore: bump mocha timeout * chore: bump timeout again? * chore: eliminate the possibility that tests are actually timing out * chore: change timeout back * chore: remove tests that might be the problematic ones * chore: attempt enabling delete event test * chore: enable lists tests * chore: try ternary test as well * chore: actually add block test files * chore: enable remaining tests
1 parent 8689ab2 commit e9920a5

File tree

7 files changed

+174
-95
lines changed

7 files changed

+174
-95
lines changed

blocks/procedures.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ const PROCEDURE_CALL_COMMON = {
980980
Xml.domToWorkspace(xml, this.workspace);
981981
Events.setGroup(false);
982982
}
983-
} else if (event.type === Events.BLOCK_DELETE) {
983+
} else if (event.type === Events.BLOCK_DELETE && event.blockId != this.id) {
984984
// Look for the case where a procedure definition has been deleted,
985985
// leaving this block (a procedure call) orphaned. In this case, delete
986986
// the orphan.

core/block.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,18 +316,18 @@ export class Block implements IASTNodeLocation, IDeletable {
316316
*/
317317
dispose(healStack: boolean) {
318318
if (this.disposed) {
319-
// Already deleted.
320319
return;
321320
}
322-
// Terminate onchange event calls.
323-
if (this.onchangeWrapper_) {
324-
this.workspace.removeChangeListener(this.onchangeWrapper_);
325-
}
326321

327322
this.unplug(healStack);
328323
if (eventUtils.isEnabled()) {
329324
eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_DELETE))!(this));
330325
}
326+
327+
if (this.onchangeWrapper_) {
328+
this.workspace.removeChangeListener(this.onchangeWrapper_);
329+
}
330+
331331
eventUtils.disable();
332332

333333
try {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
goog.declareModuleId('Blockly.test.blockDeleteEvent');
8+
9+
import * as eventUtils from '../../build/src/core/events/utils.js';
10+
import {sharedTestSetup, sharedTestTeardown} from './test_helpers/setup_teardown.js';
11+
12+
suite('Block Delete Event', function() {
13+
setup(function() {
14+
sharedTestSetup.call(this);
15+
this.workspace = new Blockly.Workspace();
16+
});
17+
18+
teardown(function() {
19+
sharedTestTeardown.call(this);
20+
});
21+
22+
suite('Receiving', function() {
23+
test('blocks receive their own delete events', function() {
24+
Blockly.Blocks['test'] = {
25+
onchange: function(e) {},
26+
};
27+
// Need to stub the definition, because the property on the definition is
28+
// what gets registered as an event listener.
29+
const spy = sinon.spy(Blockly.Blocks['test'], 'onchange');
30+
const testBlock = this.workspace.newBlock('test');
31+
32+
testBlock.dispose();
33+
34+
const deleteClass = eventUtils.get(eventUtils.BLOCK_DELETE);
35+
chai.assert.isTrue(spy.calledOnce);
36+
chai.assert.isTrue(spy.getCall(0).args[0] instanceof deleteClass);
37+
});
38+
});
39+
});

tests/mocha/blocks/lists_test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ goog.declareModuleId('Blockly.test.lists');
88

99
import {runSerializationTestSuite} from '../test_helpers/serialization.js';
1010
import {sharedTestSetup, sharedTestTeardown} from '../test_helpers/setup_teardown.js';
11-
import {ConnectionType} from '../../build/src/core/connection_type.js';
11+
import {ConnectionType} from '../../../build/src/core/connection_type.js';
1212
import {defineStatementBlock} from '../test_helpers/block_definitions.js';
1313

1414

tests/mocha/blocks/logic_ternary_test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
goog.declareModuleId('Blockly.test.logicTernary');
88

9-
import * as eventUtils from '../../build/src/core/events/utils.js';
9+
import * as eventUtils from '../../../build/src/core/events/utils.js';
1010
import {runSerializationTestSuite} from '../test_helpers/serialization.js';
1111
import {sharedTestSetup, sharedTestTeardown} from '../test_helpers/setup_teardown.js';
1212

tests/mocha/blocks/procedures_test.js

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66

77
goog.declareModuleId('Blockly.test.procedures');
88

9-
import * as Blockly from '../../build/src/core/blockly.js';
9+
import * as Blockly from '../../../build/src/core/blockly.js';
1010
import {assertCallBlockStructure, assertDefBlockStructure, createProcDefBlock, createProcCallBlock} from '../test_helpers/procedures.js';
1111
import {runSerializationTestSuite} from '../test_helpers/serialization.js';
1212
import {createGenUidStubWithReturns, sharedTestSetup, sharedTestTeardown, workspaceTeardown} from '../test_helpers/setup_teardown.js';
1313

14-
1514
suite('Procedures', function() {
1615
setup(function() {
1716
sharedTestSetup.call(this);
@@ -1210,3 +1209,43 @@ suite('Procedures', function() {
12101209
});
12111210
});
12121211
});
1212+
1213+
suite('Procedures, dont auto fire events', function() {
1214+
setup(function() {
1215+
sharedTestSetup.call(this, {fireEventsNow: false});
1216+
this.workspace = new Blockly.Workspace();
1217+
});
1218+
teardown(function() {
1219+
sharedTestTeardown.call(this);
1220+
});
1221+
1222+
const testSuites = [
1223+
{title: 'procedures_defreturn', hasReturn: true,
1224+
defType: 'procedures_defreturn', callType: 'procedures_callreturn'},
1225+
{title: 'procedures_defnoreturn', hasReturn: false,
1226+
defType: 'procedures_defnoreturn', callType: 'procedures_callnoreturn'},
1227+
];
1228+
1229+
testSuites.forEach((testSuite) => {
1230+
suite(testSuite.title, function() {
1231+
suite('Disposal', function() {
1232+
test('callers are disposed when definitions are disposed', function() {
1233+
this.defBlock = new Blockly.Block(this.workspace, testSuite.defType);
1234+
this.defBlock.setFieldValue('proc name', 'NAME');
1235+
this.callerBlock = new Blockly.Block(
1236+
this.workspace, testSuite.callType);
1237+
this.callerBlock.setFieldValue('proc name', 'NAME');
1238+
1239+
// Run the clock now so that the create events get fired. If we fire
1240+
// it after disposing, a new procedure def will get created when
1241+
// the caller create event is heard.
1242+
this.clock.runAll();
1243+
this.defBlock.dispose();
1244+
this.clock.runAll();
1245+
1246+
chai.assert.isTrue(this.callerBlock.disposed);
1247+
});
1248+
});
1249+
});
1250+
});
1251+
});

tests/mocha/index.html

Lines changed: 86 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
<div id="failureCount" style="display:none" tests_failed="unset"></div>
2020
<div id="failureMessages" style="display:none"></div>
2121
<!-- Load mocha et al. before bootstrapping so that we can safely
22-
goog.require() the test modules that make calls to (e.g.)
23-
suite() at the top level. -->
22+
goog.require() the test modules that make calls to (e.g.)
23+
suite() at the top level. -->
2424
<script src="../../node_modules/chai/chai.js"></script>
2525
<script src="../../node_modules/mocha/mocha.js"></script>
2626
<script src="../../node_modules/sinon/pkg/sinon.js"></script>
@@ -31,90 +31,91 @@
3131
});
3232

3333
var BLOCKLY_BOOTSTRAP_OPTIONS = {
34-
loadCompressed: false,
35-
depsFiles: ['build/deps.js', 'build/deps.mocha.js'],
36-
requires: [
37-
// Blockly modules needed by tests.
38-
'Blockly',
39-
'Blockly.libraryBlocks',
40-
'Blockly.Dart',
41-
'Blockly.Dart.texts',
42-
'Blockly.JavaScript',
43-
'Blockly.JavaScript.texts',
44-
'Blockly.Lua',
45-
'Blockly.Lua.texts',
46-
'Blockly.PHP',
47-
'Blockly.PHP.texts',
48-
'Blockly.Python',
49-
'Blockly.Python.texts',
34+
loadCompressed: false,
35+
depsFiles: ['build/deps.js', 'build/deps.mocha.js'],
36+
requires: [
37+
// Blockly modules needed by tests.
38+
'Blockly',
39+
'Blockly.libraryBlocks',
40+
'Blockly.Dart',
41+
'Blockly.Dart.texts',
42+
'Blockly.JavaScript',
43+
'Blockly.JavaScript.texts',
44+
'Blockly.Lua',
45+
'Blockly.Lua.texts',
46+
'Blockly.PHP',
47+
'Blockly.PHP.texts',
48+
'Blockly.Python',
49+
'Blockly.Python.texts',
5050

51-
// Test modules.
52-
'Blockly.test.astNode',
53-
'Blockly.test.blockChangeEvent',
54-
'Blockly.test.blockCreateEvent',
55-
'Blockly.test.blockJson',
56-
'Blockly.test.blocks',
57-
'Blockly.test.comments',
58-
'Blockly.test.commentDeserialization',
59-
'Blockly.test.connectionChecker',
60-
'Blockly.test.connectionDb',
61-
'Blockly.test.connection',
62-
'Blockly.test.contextMenuItem',
63-
'Blockly.test.cursor',
64-
'Blockly.test.dropdown',
65-
'Blockly.test.event',
66-
'Blockly.test.extensions',
67-
'Blockly.test.fieldAngle',
68-
'Blockly.test.fieldCheckbox',
69-
'Blockly.test.fieldColour',
70-
'Blockly.test.fieldDropdown',
71-
'Blockly.test.fieldImage',
72-
'Blockly.test.fieldLabelSerialization',
73-
'Blockly.test.fieldLabel',
74-
'Blockly.test.fieldMultiline',
75-
'Blockly.test.fieldNumber',
76-
'Blockly.test.fieldRegistry',
77-
'Blockly.test.fieldTest',
78-
'Blockly.test.fieldTextInput',
79-
'Blockly.test.fieldVariable',
80-
'Blockly.test.flyout',
81-
'Blockly.test.generator',
82-
'Blockly.test.gesture',
83-
'Blockly.test.input',
84-
'Blockly.test.insertionMarker',
85-
'Blockly.test.jsoDeserialization',
86-
'Blockly.test.jsoSerialization',
87-
'Blockly.test.json',
88-
'Blockly.test.keydown',
89-
'Blockly.test.lists',
90-
'Blockly.test.logicTernary',
91-
'Blockly.test.metrics',
92-
'Blockly.test.mutator',
93-
'Blockly.test.names',
94-
'Blockly.test.procedures',
95-
'Blockly.test.registry',
96-
'Blockly.test.serialization',
97-
'Blockly.test.shortcutRegistry',
98-
'Blockly.test.theme',
99-
'Blockly.test.toolbox',
100-
'Blockly.test.tooltip',
101-
'Blockly.test.trashcan',
102-
'Blockly.test.utils',
103-
'Blockly.test.variableMap',
104-
'Blockly.test.variableModel',
105-
'Blockly.test.variables',
106-
'Blockly.test.widgetDiv',
107-
'Blockly.test.workspaceComment',
108-
'Blockly.test.workspaceSvg',
109-
'Blockly.test.workspace',
110-
'Blockly.test.xml',
111-
'Blockly.test.zoomControls',
112-
],
113-
additionalScripts: [
114-
'msg/messages.js',
115-
'tests/playgrounds/screenshot.js',
116-
'node_modules/@blockly/dev-tools/dist/index.js',
117-
],
51+
// Test modules.
52+
'Blockly.test.astNode',
53+
'Blockly.test.blockChangeEvent',
54+
'Blockly.test.blockDeleteEvent',
55+
'Blockly.test.blockCreateEvent',
56+
'Blockly.test.blockJson',
57+
'Blockly.test.blocks',
58+
'Blockly.test.comments',
59+
'Blockly.test.commentDeserialization',
60+
'Blockly.test.connectionChecker',
61+
'Blockly.test.connectionDb',
62+
'Blockly.test.connection',
63+
'Blockly.test.contextMenuItem',
64+
'Blockly.test.cursor',
65+
'Blockly.test.dropdown',
66+
'Blockly.test.event',
67+
'Blockly.test.extensions',
68+
'Blockly.test.fieldAngle',
69+
'Blockly.test.fieldCheckbox',
70+
'Blockly.test.fieldColour',
71+
'Blockly.test.fieldDropdown',
72+
'Blockly.test.fieldImage',
73+
'Blockly.test.fieldLabelSerialization',
74+
'Blockly.test.fieldLabel',
75+
'Blockly.test.fieldMultiline',
76+
'Blockly.test.fieldNumber',
77+
'Blockly.test.fieldRegistry',
78+
'Blockly.test.fieldTest',
79+
'Blockly.test.fieldTextInput',
80+
'Blockly.test.fieldVariable',
81+
'Blockly.test.flyout',
82+
'Blockly.test.generator',
83+
'Blockly.test.gesture',
84+
'Blockly.test.input',
85+
'Blockly.test.insertionMarker',
86+
'Blockly.test.jsoDeserialization',
87+
'Blockly.test.jsoSerialization',
88+
'Blockly.test.json',
89+
'Blockly.test.keydown',
90+
'Blockly.test.lists',
91+
'Blockly.test.logicTernary',
92+
'Blockly.test.metrics',
93+
'Blockly.test.mutator',
94+
'Blockly.test.names',
95+
'Blockly.test.procedures',
96+
'Blockly.test.registry',
97+
'Blockly.test.serialization',
98+
'Blockly.test.shortcutRegistry',
99+
'Blockly.test.theme',
100+
'Blockly.test.toolbox',
101+
'Blockly.test.tooltip',
102+
'Blockly.test.trashcan',
103+
'Blockly.test.utils',
104+
'Blockly.test.variableMap',
105+
'Blockly.test.variableModel',
106+
'Blockly.test.variables',
107+
'Blockly.test.widgetDiv',
108+
'Blockly.test.workspaceComment',
109+
'Blockly.test.workspaceSvg',
110+
'Blockly.test.workspace',
111+
'Blockly.test.xml',
112+
'Blockly.test.zoomControls',
113+
],
114+
additionalScripts: [
115+
'msg/messages.js',
116+
'tests/playgrounds/screenshot.js',
117+
'node_modules/@blockly/dev-tools/dist/index.js',
118+
],
118119
}
119120
</script>
120121
<script src="../bootstrap.js"></script>

0 commit comments

Comments
 (0)