fix: touch up some deserialization behavior (#5181)

* Add parameter for recording undo.

This sets up the most common default behavior, but also makes it clear
to people that it is happening, because it might not be expected.

* Add grouping of events

* Add text width caching

* Add disabling workspace resizing

* Add performance optimizations

* Respect nulls from blocks.save

* Cleanup from rebase

* PR Comments

* Cleanup from rebase
This commit is contained in:
Beka Westberg
2021-08-11 15:01:24 +00:00
committed by alschmiedt
parent 9138bca93c
commit bd77b4ad3d
7 changed files with 555 additions and 125 deletions

View File

@@ -21,46 +21,51 @@ suite('JSO Deserialization', function() {
});
suite('Events', function() {
test.skip('Finished loading', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
},
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.FinishedLoading,
{},
this.workspace.id);
});
suite('Var create', function() {
suite('Finished loading', function() {
test('Just var', function() {
const state = {
'variables': [
{
'name': 'test',
'id': 'testId',
}
]
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
},
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{'varName': 'test', 'varId': 'testId', 'varType': ''},
Blockly.Events.FinishedLoading,
{},
this.workspace.id);
});
test('Only fire one event with var and var on block', function() {
test('Explicit group', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
},
]
}
};
Blockly.Events.setGroup('my group');
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.FinishedLoading,
{'group': 'my group'},
this.workspace.id);
});
test('Automatic group', function() {
const state = {
'variables': [
{
@@ -84,78 +89,378 @@ suite('JSO Deserialization', function() {
};
Blockly.serialization.workspaces.load(state, this.workspace);
const calls = this.eventsFireStub.getCalls();
const count = calls.reduce((acc, call) => {
if (call.args[0] instanceof Blockly.Events.VarCreate) {
return acc + 1;
}
return acc;
}, 0);
chai.assert.equal(count, 1);
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{'varName': 'test', 'varId': 'testId', 'varType': ''},
this.workspace.id);
const group = calls[0].args[0].group;
chai.assert.isTrue(calls.every(call => call.args[0].group == group));
});
});
suite('Var create', function() {
suite('Top-level call', function() {
test('Just var', function() {
const state = {
'variables': [
{
'name': 'test',
'id': 'testId',
}
]
};
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{
'varName': 'test',
'varId': 'testId',
'varType': '',
'recordUndo': false
},
this.workspace.id);
});
test('Record undo', function() {
const state = {
'variables': [
{
'name': 'test',
'id': 'testId',
}
]
};
Blockly.serialization.workspaces.load(state, this.workspace, {recordUndo: true});
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{
'varName': 'test',
'varId': 'testId',
'varType': '',
'recordUndo': true
},
this.workspace.id);
});
test('Grouping', function() {
const state = {
'variables': [
{
'name': 'test',
'id': 'testId',
}
]
};
Blockly.Events.setGroup('my group');
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{
'varName': 'test',
'varId': 'testId',
'varType': '',
'group': 'my group'
},
this.workspace.id);
});
test('Multiple vars grouped', function() {
const state = {
'variables': [
{
'name': 'test',
'id': 'testId',
},
{
'name': 'test2',
'id': 'testId2',
}
]
};
Blockly.serialization.workspaces.load(state, this.workspace);
const calls = this.eventsFireStub.getCalls();
const group = calls[0].args[0].group;
chai.assert.isTrue(calls.every(call => call.args[0].group == group));
});
test('Var with block', function() {
const state = {
'variables': [
{
'name': 'test',
'id': 'testId',
}
],
'blocks': {
'blocks': [
{
'type': 'variables_get',
'id': 'blockId',
'x': 42,
'y': 42,
'fields': {
'VAR': 'testId'
}
},
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace);
const calls = this.eventsFireStub.getCalls();
const count = calls.reduce((acc, call) => {
if (call.args[0] instanceof Blockly.Events.VarCreate) {
return acc + 1;
}
return acc;
}, 0);
chai.assert.equal(count, 1);
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{'varName': 'test', 'varId': 'testId', 'varType': ''},
this.workspace.id);
});
});
suite('Direct call', function() {
test('Just var', function() {
const state = {
'name': 'test',
'id': 'testId',
};
Blockly.serialization.variables.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{
'varName': 'test',
'varId': 'testId',
'varType': '',
'recordUndo': false
},
this.workspace.id);
});
test('Record undo', function() {
const state = {
'name': 'test',
'id': 'testId',
};
Blockly.serialization.variables
.load(state, this.workspace, {recordUndo: true});
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{
'varName': 'test',
'varId': 'testId',
'varType': '',
'recordUndo': true
},
this.workspace.id);
});
test('Grouping', function() {
const state = {
'name': 'test',
'id': 'testId',
};
Blockly.Events.setGroup('my group');
Blockly.serialization.variables.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.VarCreate,
{
'varName': 'test',
'varId': 'testId',
'varType': '',
'group': 'my group'
},
this.workspace.id);
});
});
});
suite('Block create', function() {
test('Simple', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
},
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{},
this.workspace.id,
'testId');
});
suite('Top-level call', function() {
test('No children', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
},
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{'recordUndo': false},
this.workspace.id,
'testId');
});
test('Only fire event for top block', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'id1',
'x': 42,
'y': 42,
'inputs': {
'DO0': {
test('Record undo', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
},
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace, {'recordUndo': true});
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{'recordUndo': true},
this.workspace.id,
'testId');
});
test('Grouping', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
},
]
}
};
Blockly.Events.setGroup('my group');
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{'group': 'my group'},
this.workspace.id,
'testId');
});
test('Multiple blocks grouped', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
},
{
'type': 'controls_if',
'id': 'testId',
'x': 84,
'y': 84
},
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace);
const calls = this.eventsFireStub.getCalls();
const group = calls[0].args[0].group;
chai.assert.isTrue(calls.every(call => call.args[0].group == group));
});
test('With children', function() {
const state = {
'blocks': {
'blocks': [
{
'type': 'controls_if',
'id': 'id1',
'x': 42,
'y': 42,
'inputs': {
'DO0': {
'block': {
'type': 'controls_if',
'id': 'id2'
}
}
},
'next': {
'block': {
'type': 'controls_if',
'id': 'id2'
'id': 'id3'
}
}
},
'next': {
'block': {
'type': 'controls_if',
'id': 'id3'
}
}
},
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{},
this.workspace.id,
'id1');
]
}
};
Blockly.serialization.workspaces.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{},
this.workspace.id,
'id1');
});
});
suite('Direct call', function() {
test('No children', function() {
const state = {
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
};
Blockly.serialization.blocks.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{'recordUndo': false},
this.workspace.id,
'testId');
});
test('Record undo', function() {
const state = {
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
};
Blockly.serialization.blocks
.load(state, this.workspace, {'recordUndo': true});
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{'recordUndo': true},
this.workspace.id,
'testId');
});
test('Grouping', function() {
const state = {
'type': 'controls_if',
'id': 'testId',
'x': 42,
'y': 42
};
Blockly.Events.setGroup('my group');
Blockly.serialization.blocks.load(state, this.workspace);
assertEventFired(
this.eventsFireStub,
Blockly.Events.BlockCreate,
{'group': 'my group'},
this.workspace.id,
'testId');
});
});
});
});