Skip to content

Commit 0afff23

Browse files
authored
fix: json serialize lists_getIndex with json extraState (#6136) (#6170)
* fix: json serialize lists_getIndex with json extraState (#6136) * address review comments * fix: move block tests to mocha/block folder
1 parent d21db8a commit 0afff23

File tree

9 files changed

+147
-8
lines changed

9 files changed

+147
-8
lines changed

blocks/lists.js

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
goog.module('Blockly.libraryBlocks.lists');
1414

1515
const xmlUtils = goog.require('Blockly.utils.xml');
16+
const Xml = goog.require('Blockly.Xml');
1617
const {Align} = goog.require('Blockly.Input');
1718
/* eslint-disable-next-line no-unused-vars */
1819
const {Block} = goog.requireType('Blockly.Block');
@@ -452,10 +453,34 @@ blocks['lists_getIndex'] = {
452453
this.updateAt_(isAt);
453454
},
454455

455-
// This block does not need JSO serialization hooks (saveExtraState and
456-
// loadExtraState) because the state of this object is already encoded in the
457-
// dropdown values.
458-
// XML hooks are kept for backwards compatibility.
456+
/**
457+
* Returns the state of this block as a JSON serializable object.
458+
* Returns null for efficiency if no state is needed (not a statement)
459+
* @return {?{isStatement: boolean}} The state of this block, ie whether it's
460+
* a statement.
461+
*/
462+
saveExtraState: function() {
463+
if (!this.outputConnection) {
464+
return {
465+
'isStatement': true,
466+
};
467+
}
468+
return null;
469+
},
470+
471+
/**
472+
* Applies the given state to this block.
473+
* @param {*} state The state to apply to this block, ie whether it's a
474+
* statement.
475+
*/
476+
loadExtraState: function(state) {
477+
if (state['isStatement']) {
478+
this.updateStatement_(true);
479+
} else if (typeof state === 'string') {
480+
// backward compatible for json serialised mutations
481+
this.domToMutation(Xml.textToDom(state));
482+
}
483+
},
459484

460485
/**
461486
* Switch between a value block and a statement block.

core/serialization/blocks.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,9 @@ const loadAttributes = function(block, state) {
441441
/**
442442
* Applies any extra state information available on the state object to the
443443
* block.
444+
* For json serialised blocks with a loadExtraState method, if the extraState
445+
* is an xml mutation (not an object), domToMutation will be called instead for
446+
* backward compatibility.
444447
* @param {!Block} block The block to set the extra state of.
445448
* @param {!State} state The state object to reference.
446449
*/

tests/deps.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/deps.mocha.js

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/mocha/blocks/lists_test.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* @license
3+
* Copyright 2022 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
goog.module('Blockly.test.lists');
8+
9+
const {runSerializationTestSuite} = goog.require('Blockly.test.helpers.serialization');
10+
const {sharedTestSetup, sharedTestTeardown} = goog.require('Blockly.test.helpers.setupTeardown');
11+
const {ConnectionType} = goog.require('Blockly.ConnectionType');
12+
const {defineStatementBlock} = goog.require('Blockly.test.helpers.blockDefinitions');
13+
14+
15+
suite('Lists', function() {
16+
setup(function() {
17+
defineStatementBlock();
18+
sharedTestSetup.call(this);
19+
this.workspace = new Blockly.Workspace();
20+
});
21+
22+
teardown(function() {
23+
sharedTestTeardown.call(this);
24+
});
25+
26+
suite('ListsGetIndex', function() {
27+
/**
28+
* Test cases for serialization tests.
29+
* @type {Array<SerializationTestCase>}
30+
*/
31+
const testCases = [
32+
{
33+
title: 'JSON not requiring mutations',
34+
json: {
35+
type: 'lists_getIndex',
36+
id: '1',
37+
fields: {MODE: 'GET', WHERE: 'FIRST'},
38+
},
39+
assertBlockStructure: (block) => {
40+
chai.assert.equal(block.type, 'lists_getIndex');
41+
chai.assert.exists(block.outputConnection);
42+
},
43+
},
44+
{
45+
title: 'JSON requiring mutations',
46+
json: {
47+
type: 'lists_getIndex',
48+
id: '1',
49+
extraState: {isStatement: true},
50+
fields: {MODE: 'REMOVE', WHERE: 'FROM_START'},
51+
},
52+
assertBlockStructure: (block) => {
53+
chai.assert.equal(block.type, 'lists_getIndex');
54+
chai.assert.isNotTrue(block.outputConnection);
55+
chai.assert.isTrue(
56+
block.getInput('AT').type === ConnectionType.INPUT_VALUE
57+
);
58+
},
59+
},
60+
{
61+
title:
62+
'JSON requiring mutations and extra state for previous connection',
63+
json: {
64+
type: 'statement_block',
65+
id: '1',
66+
next: {
67+
block: {
68+
type: 'lists_getIndex',
69+
id: '2',
70+
extraState: {isStatement: true},
71+
fields: {MODE: 'REMOVE', WHERE: 'FROM_START'},
72+
},
73+
},
74+
},
75+
assertBlockStructure: (block) => {},
76+
},
77+
{
78+
title:
79+
'JSON requiring mutations with XML extra state',
80+
json: {
81+
type: 'statement_block',
82+
id: '1',
83+
next: {
84+
block: {
85+
type: 'lists_getIndex',
86+
id: '2',
87+
extraState: '<mutation statement="true" at="true"></mutation>',
88+
fields: {MODE: 'REMOVE', WHERE: 'FROM_START'},
89+
},
90+
},
91+
},
92+
expectedJson: {
93+
type: 'statement_block',
94+
id: '1',
95+
next: {
96+
block: {
97+
type: 'lists_getIndex',
98+
id: '2',
99+
extraState: {isStatement: true},
100+
fields: {MODE: 'REMOVE', WHERE: 'FROM_START'},
101+
},
102+
},
103+
},
104+
assertBlockStructure: (block) => {},
105+
},
106+
];
107+
runSerializationTestSuite(testCases);
108+
});
109+
});
File renamed without changes.

tests/mocha/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
goog.require('Blockly.test.jsoSerialization');
9292
goog.require('Blockly.test.json');
9393
goog.require('Blockly.test.keydown');
94+
goog.require('Blockly.test.lists');
9495
goog.require('Blockly.test.logicTernary');
9596
goog.require('Blockly.test.metrics');
9697
goog.require('Blockly.test.mutator');

0 commit comments

Comments
 (0)