fix: create and delete events, and the trashcan (#5425)

* fix: create and delete events with JSON serialization

* fix: trashcan with JSON serialization

* fix: build

* fix: tests

* fix: PR comments

* fix: types

* fix: tests
This commit is contained in:
Beka Westberg
2021-09-09 20:48:38 +00:00
committed by alschmiedt
parent 17f9f4f689
commit 84514efb09
9 changed files with 274 additions and 201 deletions

View File

@@ -18,9 +18,9 @@ const Block = goog.requireType('Blockly.Block');
const BlockBase = goog.require('Blockly.Events.BlockBase'); const BlockBase = goog.require('Blockly.Events.BlockBase');
const Events = goog.require('Blockly.Events'); const Events = goog.require('Blockly.Events');
const Xml = goog.require('Blockly.Xml'); const Xml = goog.require('Blockly.Xml');
const blocks = goog.require('Blockly.serialization.blocks');
const object = goog.require('Blockly.utils.object'); const object = goog.require('Blockly.utils.object');
const registry = goog.require('Blockly.registry'); const registry = goog.require('Blockly.registry');
const xml = goog.require('Blockly.utils.xml');
/** /**
@@ -40,12 +40,15 @@ const BlockCreate = function(opt_block) {
this.recordUndo = false; this.recordUndo = false;
} }
if (opt_block.workspace.rendered) { this.xml = Xml.blockToDomWithXY(opt_block);
this.xml = Xml.blockToDomWithXY(opt_block);
} else {
this.xml = Xml.blockToDom(opt_block);
}
this.ids = Events.getDescendantIds(opt_block); this.ids = Events.getDescendantIds(opt_block);
/**
* JSON representation of the block that was just created.
* @type {!blocks.State}
*/
this.json = /** @type {!blocks.State} */ (blocks.save(
opt_block, {addCoordinates: true}));
}; };
object.inherits(BlockCreate, BlockBase); object.inherits(BlockCreate, BlockBase);
@@ -63,6 +66,7 @@ BlockCreate.prototype.toJson = function() {
const json = BlockCreate.superClass_.toJson.call(this); const json = BlockCreate.superClass_.toJson.call(this);
json['xml'] = Xml.domToText(this.xml); json['xml'] = Xml.domToText(this.xml);
json['ids'] = this.ids; json['ids'] = this.ids;
json['json'] = this.json;
if (!this.recordUndo) { if (!this.recordUndo) {
json['recordUndo'] = this.recordUndo; json['recordUndo'] = this.recordUndo;
} }
@@ -77,6 +81,7 @@ BlockCreate.prototype.fromJson = function(json) {
BlockCreate.superClass_.fromJson.call(this, json); BlockCreate.superClass_.fromJson.call(this, json);
this.xml = Xml.textToDom(json['xml']); this.xml = Xml.textToDom(json['xml']);
this.ids = json['ids']; this.ids = json['ids'];
this.json = /** @type {!blocks.State} */ (json['json']);
if (json['recordUndo'] !== undefined) { if (json['recordUndo'] !== undefined) {
this.recordUndo = json['recordUndo']; this.recordUndo = json['recordUndo'];
} }
@@ -89,9 +94,7 @@ BlockCreate.prototype.fromJson = function(json) {
BlockCreate.prototype.run = function(forward) { BlockCreate.prototype.run = function(forward) {
const workspace = this.getEventWorkspace_(); const workspace = this.getEventWorkspace_();
if (forward) { if (forward) {
const xmlEl = xml.createElement('xml'); blocks.load(this.json, workspace);
xmlEl.appendChild(this.xml);
Xml.domToWorkspace(xmlEl, workspace);
} else { } else {
for (let i = 0; i < this.ids.length; i++) { for (let i = 0; i < this.ids.length; i++) {
const id = this.ids[i]; const id = this.ids[i];

View File

@@ -18,9 +18,9 @@ const Block = goog.requireType('Blockly.Block');
const BlockBase = goog.require('Blockly.Events.BlockBase'); const BlockBase = goog.require('Blockly.Events.BlockBase');
const Events = goog.require('Blockly.Events'); const Events = goog.require('Blockly.Events');
const Xml = goog.require('Blockly.Xml'); const Xml = goog.require('Blockly.Xml');
const blocks = goog.require('Blockly.serialization.blocks');
const object = goog.require('Blockly.utils.object'); const object = goog.require('Blockly.utils.object');
const registry = goog.require('Blockly.registry'); const registry = goog.require('Blockly.registry');
const xml = goog.require('Blockly.utils.xml');
/** /**
@@ -43,12 +43,21 @@ const BlockDelete = function(opt_block) {
this.recordUndo = false; this.recordUndo = false;
} }
if (opt_block.workspace.rendered) { this.oldXml = Xml.blockToDomWithXY(opt_block);
this.oldXml = Xml.blockToDomWithXY(opt_block);
} else {
this.oldXml = Xml.blockToDom(opt_block);
}
this.ids = Events.getDescendantIds(opt_block); this.ids = Events.getDescendantIds(opt_block);
/**
* Was the block that was just deleted a shadow?
* @type {boolean}
*/
this.wasShadow = opt_block.isShadow();
/**
* JSON representation of the block that was just deleted.
* @type {!blocks.State}
*/
this.oldJson = /** @type {!blocks.State} */ (blocks.save(
opt_block, {addCoordinates: true}));
}; };
object.inherits(BlockDelete, BlockBase); object.inherits(BlockDelete, BlockBase);
@@ -66,6 +75,8 @@ BlockDelete.prototype.toJson = function() {
const json = BlockDelete.superClass_.toJson.call(this); const json = BlockDelete.superClass_.toJson.call(this);
json['oldXml'] = Xml.domToText(this.oldXml); json['oldXml'] = Xml.domToText(this.oldXml);
json['ids'] = this.ids; json['ids'] = this.ids;
json['wasShadow'] = this.wasShadow;
json['oldJson'] = this.oldJson;
if (!this.recordUndo) { if (!this.recordUndo) {
json['recordUndo'] = this.recordUndo; json['recordUndo'] = this.recordUndo;
} }
@@ -80,6 +91,9 @@ BlockDelete.prototype.fromJson = function(json) {
BlockDelete.superClass_.fromJson.call(this, json); BlockDelete.superClass_.fromJson.call(this, json);
this.oldXml = Xml.textToDom(json['oldXml']); this.oldXml = Xml.textToDom(json['oldXml']);
this.ids = json['ids']; this.ids = json['ids'];
this.wasShadow =
json['wasShadow'] || this.oldXml.tagName.toLowerCase() == 'shadow';
this.oldJson = /** @type {!blocks.State} */ (json['oldJson']);
if (json['recordUndo'] !== undefined) { if (json['recordUndo'] !== undefined) {
this.recordUndo = json['recordUndo']; this.recordUndo = json['recordUndo'];
} }
@@ -103,9 +117,7 @@ BlockDelete.prototype.run = function(forward) {
} }
} }
} else { } else {
const xmlEl = xml.createElement('xml'); blocks.load(this.oldJson, workspace);
xmlEl.appendChild(this.oldXml);
Xml.domToWorkspace(xmlEl, workspace);
} }
}; };

View File

@@ -36,7 +36,8 @@ const Size = goog.require('Blockly.utils.Size');
const Svg = goog.require('Blockly.utils.Svg'); const Svg = goog.require('Blockly.utils.Svg');
/* eslint-disable-next-line no-unused-vars */ /* eslint-disable-next-line no-unused-vars */
const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg');
const Xml = goog.require('Blockly.Xml'); /* eslint-disable-next-line no-unused-vars */
const blocks = goog.requireType('Blockly.serialization.blocks');
const browserEvents = goog.require('Blockly.browserEvents'); const browserEvents = goog.require('Blockly.browserEvents');
const dom = goog.require('Blockly.utils.dom'); const dom = goog.require('Blockly.utils.dom');
const internalConstants = goog.require('Blockly.internalConstants'); const internalConstants = goog.require('Blockly.internalConstants');
@@ -73,7 +74,7 @@ const Trashcan = function(workspace) {
this.id = 'trashcan'; this.id = 'trashcan';
/** /**
* A list of XML (stored as strings) representing blocks in the trashcan. * A list of JSON (stored as strings) representing blocks in the trashcan.
* @type {!Array<string>} * @type {!Array<string>}
* @private * @private
*/ */
@@ -393,8 +394,10 @@ Trashcan.prototype.openFlyout = function() {
if (this.contentsIsOpen()) { if (this.contentsIsOpen()) {
return; return;
} }
const xml = this.contents_.map(Xml.textToDom); const contents = this.contents_.map(function(string) {
this.flyout.show(xml); return JSON.parse(string);
});
this.flyout.show(contents);
this.fireUiEvent_(true); this.fireUiEvent_(true);
}; };
@@ -669,14 +672,12 @@ Trashcan.prototype.onDelete_ = function(event) {
if (this.workspace_.options.maxTrashcanContents <= 0) { if (this.workspace_.options.maxTrashcanContents <= 0) {
return; return;
} }
// Must check that the tagName exists since oldXml can be a DocumentFragment. if (event.type == Events.BLOCK_DELETE && !event.wasShadow) {
if (event.type == Events.BLOCK_DELETE && event.oldXml.tagName && const cleanedJson = this.cleanBlockJson_(event.oldJson);
event.oldXml.tagName.toLowerCase() != 'shadow') { if (this.contents_.indexOf(cleanedJson) != -1) {
const cleanedXML = this.cleanBlockXML_(event.oldXml);
if (this.contents_.indexOf(cleanedXML) != -1) {
return; return;
} }
this.contents_.unshift(cleanedXML); this.contents_.unshift(cleanedJson);
while (this.contents_.length > while (this.contents_.length >
this.workspace_.options.maxTrashcanContents) { this.workspace_.options.maxTrashcanContents) {
this.contents_.pop(); this.contents_.pop();
@@ -687,52 +688,51 @@ Trashcan.prototype.onDelete_ = function(event) {
}; };
/** /**
* Converts XML representing a block into text that can be stored in the * Converts JSON representing a block into text that can be stored in the
* content array. * content array.
* @param {!Element} xml An XML tree defining the block and any * @param {!blocks.State} json A JSON representation of
* connected child blocks. * a block's state.
* @return {string} Text representing the XML tree, cleaned of all unnecessary * @return {string} Text representing the JSON, cleaned of all unnecessary
* attributes. * attributes.
* @private * @private
*/ */
Trashcan.prototype.cleanBlockXML_ = function(xml) { Trashcan.prototype.cleanBlockJson_ = function(json) {
const xmlBlock = xml.cloneNode(true); // Create a deep copy.
let node = xmlBlock; json = /** @type {!blocks.State} */(JSON.parse(JSON.stringify(json)));
while (node) {
// Things like text inside tags are still treated as nodes, but they function cleanRec(json) {
// don't have attributes (or the removeAttribute function) so we can if (!json) {
// skip removing attributes from them. return;
if (node.removeAttribute) {
node.removeAttribute('x');
node.removeAttribute('y');
node.removeAttribute('id');
node.removeAttribute('disabled');
if (node.nodeName == 'comment') { // Future proof just in case.
node.removeAttribute('h');
node.removeAttribute('w');
node.removeAttribute('pinned');
}
} }
// Try to go down the tree delete json['id'];
let nextNode = node.firstChild || node.nextSibling; delete json['x'];
// If we can't go down, try to go back up the tree. delete json['y'];
if (!nextNode) { delete json['enabled'];
nextNode = node.parentNode;
while (nextNode) { if (json['icons'] && json['icons']['comment']) {
// We are valid again! const comment = json['icons']['comment'];
if (nextNode.nextSibling) { delete comment['height'];
nextNode = nextNode.nextSibling; delete comment['width'];
break; delete comment['pinned'];
} }
// Try going up again. If parentNode is null that means we have
// reached the top, and we will break out of both loops. const inputs = json['inputs'];
nextNode = nextNode.parentNode; for (var name in inputs) {
} const input = inputs[name];
cleanRec(input['block']);
cleanRec(input['shadow']);
}
if (json['next']) {
const next = json['next'];
cleanRec(next['block']);
cleanRec(next['shadow']);
} }
node = nextNode;
} }
return Xml.domToText(xmlBlock);
cleanRec(json);
json['kind'] = 'BLOCK';
return JSON.stringify(json);
}; };
exports = Trashcan; exports = Trashcan;

View File

@@ -40,8 +40,8 @@ goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.
goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_base.js', ['Blockly.Events.BlockBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_base.js', ['Blockly.Events.BlockBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_change.js', ['Blockly.Events.BlockChange'], ['Blockly.Events', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_change.js', ['Blockly.Events.BlockChange'], ['Blockly.Events', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_create.js', ['Blockly.Events.BlockCreate'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_create.js', ['Blockly.Events.BlockCreate'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.Xml', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_delete.js', ['Blockly.Events.BlockDelete'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_delete.js', ['Blockly.Events.BlockDelete'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.Xml', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_move.js', ['Blockly.Events.BlockMove'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_move.js', ['Blockly.Events.BlockMove'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
@@ -217,7 +217,7 @@ goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem']
goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.common', 'Blockly.utils.deprecation', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.common', 'Blockly.utils.deprecation', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.Options', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.internalConstants', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.global', 'Blockly.utils.idGenerator', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.svgPaths', 'Blockly.utils.toolbox', 'Blockly.utils.userAgent', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.internalConstants', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.global', 'Blockly.utils.idGenerator', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.svgPaths', 'Blockly.utils.toolbox', 'Blockly.utils.userAgent', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], ['Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], ['Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'});

View File

@@ -40,8 +40,8 @@ goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.
goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_base.js', ['Blockly.Events.BlockBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_base.js', ['Blockly.Events.BlockBase'], ['Blockly.Events.Abstract', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_change.js', ['Blockly.Events.BlockChange'], ['Blockly.Events', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_change.js', ['Blockly.Events.BlockChange'], ['Blockly.Events', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_create.js', ['Blockly.Events.BlockCreate'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_create.js', ['Blockly.Events.BlockCreate'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.Xml', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_delete.js', ['Blockly.Events.BlockDelete'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.object', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_delete.js', ['Blockly.Events.BlockDelete'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.Xml', 'Blockly.registry', 'Blockly.serialization.blocks', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_block_move.js', ['Blockly.Events.BlockMove'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_block_move.js', ['Blockly.Events.BlockMove'], ['Blockly.Events', 'Blockly.Events.BlockBase', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
@@ -217,7 +217,7 @@ goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem']
goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.common', 'Blockly.utils.deprecation', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.common', 'Blockly.utils.deprecation', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.string'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.Options', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.internalConstants', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.global', 'Blockly.utils.idGenerator', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.svgPaths', 'Blockly.utils.toolbox', 'Blockly.utils.userAgent', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.internalConstants', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.global', 'Blockly.utils.idGenerator', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.svgPaths', 'Blockly.utils.toolbox', 'Blockly.utils.userAgent', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], ['Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], ['Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'});

View File

@@ -437,48 +437,118 @@ suite('Events', function() {
viewLeft: 0, scale: 1.2, oldScale: 1})}, viewLeft: 0, scale: 1.2, oldScale: 1})},
]; ];
var blockEventTestCases = [ var blockEventTestCases = [
{title: 'Block change', class: Blockly.Events.BlockChange, {
title: 'Block change',
class: Blockly.Events.BlockChange,
getArgs: (thisObj) => [thisObj.block, 'collapsed', null, false, true], getArgs: (thisObj) => [thisObj.block, 'collapsed', null, false, true],
getExpectedJson: (thisObj) => ({type: 'change', getExpectedJson: (thisObj) => ({
blockId: thisObj.block.id, element: 'collapsed', oldValue: false, type: 'change',
newValue: true})}, blockId: thisObj.block.id,
{title: 'Block create', class: Blockly.Events.BlockCreate, element: 'collapsed',
oldValue: false,
newValue: true
})
},
{
title: 'Block create',
class: Blockly.Events.BlockCreate,
getArgs: (thisObj) => [thisObj.block], getArgs: (thisObj) => [thisObj.block],
getExpectedJson: (thisObj) => ({type: 'create', getExpectedJson: (thisObj) => ({
type: 'create',
blockId: thisObj.block.id, blockId: thisObj.block.id,
xml: '<block xmlns="https://developers.google.com/blockly/xml"' + xml: '<block xmlns="https://developers.google.com/blockly/xml"' +
' type="simple_test_block" id="testBlockId1"></block>', ' type="simple_test_block" id="testBlockId1" x="0" y="0">' +
ids: [thisObj.block.id]})}, '</block>',
{title: 'Block create (shadow)', class: Blockly.Events.BlockCreate, ids: [thisObj.block.id],
json: {
'type': 'simple_test_block',
'id': 'testBlockId1',
'x': 0,
'y': 0,
},
})
},
{
title: 'Block create (shadow)',
class: Blockly.Events.BlockCreate,
getArgs: (thisObj) => [thisObj.shadowBlock], getArgs: (thisObj) => [thisObj.shadowBlock],
getExpectedJson: (thisObj) => ({type: 'create', getExpectedJson: (thisObj) => ({
type: 'create',
blockId: thisObj.shadowBlock.id, blockId: thisObj.shadowBlock.id,
xml: '<shadow xmlns="https://developers.google.com/blockly/xml"' + xml: '<shadow xmlns="https://developers.google.com/blockly/xml"' +
' type="simple_test_block" id="testBlockId2"></shadow>', ' type="simple_test_block" id="testBlockId2" x="0" y="0">' +
ids: [thisObj.shadowBlock.id], recordUndo: false})}, '</shadow>',
{title: 'Block delete', class: Blockly.Events.BlockDelete, ids: [thisObj.shadowBlock.id],
json: {
'type': 'simple_test_block',
'id': 'testBlockId2',
'x': 0,
'y': 0,
},
recordUndo: false
})
},
{
title: 'Block delete',
class: Blockly.Events.BlockDelete,
getArgs: (thisObj) => [thisObj.block], getArgs: (thisObj) => [thisObj.block],
getExpectedJson: (thisObj) => ({type: 'delete', getExpectedJson: (thisObj) => ({
type: 'delete',
blockId: thisObj.block.id, blockId: thisObj.block.id,
oldXml: '<block xmlns="https://developers.google.com/blockly/xml"' + oldXml: '<block xmlns="https://developers.google.com/blockly/xml"' +
' type="simple_test_block" id="testBlockId1"></block>', ' type="simple_test_block" id="testBlockId1" x="0" y="0">' +
ids: [thisObj.block.id]})}, '</block>',
{title: 'Block delete (shadow)', class: Blockly.Events.BlockDelete, ids: [thisObj.block.id],
wasShadow: false,
oldJson: {
'type': 'simple_test_block',
'id': 'testBlockId1',
'x': 0,
'y': 0,
},
})
},
{
title: 'Block delete (shadow)',
class: Blockly.Events.BlockDelete,
getArgs: (thisObj) => [thisObj.shadowBlock], getArgs: (thisObj) => [thisObj.shadowBlock],
getExpectedJson: (thisObj) => ({type: 'delete', getExpectedJson: (thisObj) => ({
type: 'delete',
blockId: thisObj.shadowBlock.id, blockId: thisObj.shadowBlock.id,
oldXml: '<shadow xmlns="https://developers.google.com/blockly/xml"' + oldXml: '<shadow xmlns="https://developers.google.com/blockly/xml"' +
' type="simple_test_block" id="testBlockId2"></shadow>', ' type="simple_test_block" id="testBlockId2" x="0" y="0">' +
ids: [thisObj.shadowBlock.id], recordUndo: false})}, '</shadow>',
ids: [thisObj.shadowBlock.id],
wasShadow: true,
oldJson: {
'type': 'simple_test_block',
'id': 'testBlockId2',
'x': 0,
'y': 0,
},
recordUndo: false
})
},
// TODO(#4577) Test serialization of move event coordinate properties. // TODO(#4577) Test serialization of move event coordinate properties.
{title: 'Block move', class: Blockly.Events.BlockMove, {
title: 'Block move',
class: Blockly.Events.BlockMove,
getArgs: (thisObj) => [thisObj.block], getArgs: (thisObj) => [thisObj.block],
getExpectedJson: (thisObj) => ({type: 'move', getExpectedJson: (thisObj) => ({
blockId: thisObj.block.id})}, type: 'move',
{title: 'Block move (shadow)', class: Blockly.Events.BlockMove, blockId: thisObj.block.id
})
},
{
title: 'Block move (shadow)',
class: Blockly.Events.BlockMove,
getArgs: (thisObj) => [thisObj.shadowBlock], getArgs: (thisObj) => [thisObj.shadowBlock],
getExpectedJson: (thisObj) => ({type: 'move', getExpectedJson: (thisObj) => ({
blockId: thisObj.shadowBlock.id, recordUndo: false})}, type: 'move',
blockId: thisObj.shadowBlock.id,
recordUndo: false
})
},
]; ];
var workspaceEventTestCases = [ var workspaceEventTestCases = [
{title: 'Finished Loading', class: Blockly.Events.FinishedLoading, {title: 'Finished Loading', class: Blockly.Events.FinishedLoading,

View File

@@ -689,7 +689,11 @@ suite('JSO Deserialization', function() {
Blockly.Blocks['test_block'] = { Blockly.Blocks['test_block'] = {
init: function() { }, init: function() { },
mutationToDom: function() { }, mutationToDom: function() {
var container = Blockly.utils.xml.createElement('mutation');
container.setAttribute('value', 'some value');
return container;
},
domToMutation: function(element) { domToMutation: function(element) {
this.someProperty = element.getAttribute('value'); this.someProperty = element.getAttribute('value');

View File

@@ -481,9 +481,9 @@ function assertNthCallEventArgEquals(spy, n, instanceType, expectedProperties,
} }
exports.assertNthCallEventArgEquals = assertNthCallEventArgEquals; exports.assertNthCallEventArgEquals = assertNthCallEventArgEquals;
function defineStackBlock() { function defineStackBlock(name = 'stack_block') {
Blockly.defineBlocksWithJsonArray([{ Blockly.defineBlocksWithJsonArray([{
"type": "stack_block", "type": name,
"message0": "", "message0": "",
"previousStatement": null, "previousStatement": null,
"nextStatement": null "nextStatement": null
@@ -491,9 +491,9 @@ function defineStackBlock() {
} }
exports.defineStackBlock = defineStackBlock; exports.defineStackBlock = defineStackBlock;
function defineRowBlock() { function defineRowBlock(name = 'row_block') {
Blockly.defineBlocksWithJsonArray([{ Blockly.defineBlocksWithJsonArray([{
"type": "row_block", "type": name,
"message0": "%1", "message0": "%1",
"args0": [ "args0": [
{ {
@@ -506,9 +506,9 @@ function defineRowBlock() {
} }
exports.defineRowBlock = defineRowBlock; exports.defineRowBlock = defineRowBlock;
function defineStatementBlock() { function defineStatementBlock(name = 'statement_block') {
Blockly.defineBlocksWithJsonArray([{ Blockly.defineBlocksWithJsonArray([{
"type": "statement_block", "type": name,
"message0": "%1", "message0": "%1",
"args0": [ "args0": [
{ {
@@ -525,9 +525,9 @@ function defineStatementBlock() {
} }
exports.defineStatementBlock = defineStatementBlock; exports.defineStatementBlock = defineStatementBlock;
function defineBasicBlockWithField() { function defineBasicBlockWithField(name = 'test_field_block') {
Blockly.defineBlocksWithJsonArray([{ Blockly.defineBlocksWithJsonArray([{
"type": "test_field_block", "type": name,
"message0": "%1", "message0": "%1",
"args0": [ "args0": [
{ {

View File

@@ -6,7 +6,7 @@
goog.module('Blockly.test.trashcan'); goog.module('Blockly.test.trashcan');
const {assertEventFired, assertEventNotFired, sharedTestSetup, sharedTestTeardown, simulateClick} = goog.require('Blockly.test.helpers'); const {assertEventFired, assertEventNotFired, defineBasicBlockWithField, defineRowBlock, defineStatementBlock, defineStackBlock, defineMutatorBlocks, sharedTestSetup, sharedTestTeardown, simulateClick} = goog.require('Blockly.test.helpers');
suite("Trashcan", function() { suite("Trashcan", function() {
@@ -15,14 +15,13 @@ suite("Trashcan", function() {
'<xml xmlns="https://developers.google.com/blockly/xml">' + '<xml xmlns="https://developers.google.com/blockly/xml">' +
xmlString + '</xml>'); xmlString + '</xml>');
xml = xml.children[0]; xml = xml.children[0];
var event = new Blockly.Events.BlockDelete(); var block = Blockly.Xml.domToBlock(xml, workspace);
event.oldXml = xml; var event = new Blockly.Events.BlockDelete(block);
event.workspaceId = workspace.id;
Blockly.Events.fire(event); Blockly.Events.fire(event);
} }
function fireNonDeleteEvent(workspace, oldXml) { function fireNonDeleteEvent(workspace, oldXml) {
var event = new Blockly.Events.Abstract(); var event = new Blockly.Events.Abstract();
event.type = 'dummy_type'; event.type = 'test_field_block';
event.workspaceId = workspace.id; event.workspaceId = workspace.id;
if (oldXml) { if (oldXml) {
event.oldXml = oldXml; event.oldXml = oldXml;
@@ -32,17 +31,27 @@ suite("Trashcan", function() {
setup(function() { setup(function() {
sharedTestSetup.call(this); sharedTestSetup.call(this);
defineBasicBlockWithField();
defineRowBlock();
defineRowBlock('row_block2');
defineStatementBlock();
defineStatementBlock('statement_block2');
defineStackBlock();
defineStackBlock('stack_block2');
defineMutatorBlocks();
this.workspace = Blockly.inject('blocklyDiv', this.workspace = Blockly.inject('blocklyDiv',
{'trashcan': true, 'maxTrashcanContents': Infinity}); {'trashcan': true, 'maxTrashcanContents': Infinity});
this.trashcan = this.workspace.trashcan; this.trashcan = this.workspace.trashcan;
}); });
teardown(function() { teardown(function() {
sharedTestTeardown.call(this); sharedTestTeardown.call(this);
Blockly.Extensions.unregister('xml_mutator');
Blockly.Extensions.unregister('jso_mutator');
}); });
suite("Events", function() { suite("Events", function() {
test("Delete", function() { test("Delete", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<block type="test_field_block"/>');
chai.assert.equal(this.trashcan.contents_.length, 1); chai.assert.equal(this.trashcan.contents_.length, 1);
}); });
test("Non-Delete", function() { test("Non-Delete", function() {
@@ -52,7 +61,7 @@ suite("Trashcan", function() {
test("Non-Delete w/ oldXml", function() { test("Non-Delete w/ oldXml", function() {
var xml = Blockly.Xml.textToDom( var xml = Blockly.Xml.textToDom(
'<xml xmlns="https://developers.google.com/blockly/xml">' + '<xml xmlns="https://developers.google.com/blockly/xml">' +
' <block type="dummy_type"/>' + ' <block type="test_field_block"/>' +
'</xml>' '</xml>'
); );
xml = xml.children[0]; xml = xml.children[0];
@@ -60,7 +69,7 @@ suite("Trashcan", function() {
chai.assert.equal(this.trashcan.contents_.length, 0); chai.assert.equal(this.trashcan.contents_.length, 0);
}); });
test("Shadow Delete", function() { test("Shadow Delete", function() {
fireDeleteEvent(this.workspace, '<shadow type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<shadow type="test_field_block"/>');
chai.assert.equal(this.trashcan.contents_.length, 0); chai.assert.equal(this.trashcan.contents_.length, 0);
}); });
test("Click without contents - fires workspace click", function() { test("Click without contents - fires workspace click", function() {
@@ -73,7 +82,7 @@ suite("Trashcan", function() {
this.workspace.id, null); this.workspace.id, null);
}); });
test("Click with contents - fires trashcanOpen", function() { test("Click with contents - fires trashcanOpen", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<block type="test_field_block"/>');
chai.assert.equal(this.trashcan.contents_.length, 1); chai.assert.equal(this.trashcan.contents_.length, 1);
// Stub flyout interaction. // Stub flyout interaction.
var showFlyoutStub = sinon.stub(this.trashcan.flyout, "show"); var showFlyoutStub = sinon.stub(this.trashcan.flyout, "show");
@@ -107,56 +116,52 @@ suite("Trashcan", function() {
}); });
suite("Unique Contents", function() { suite("Unique Contents", function() {
test("Simple", function() { test("Simple", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<block type="test_field_block"/>');
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<block type="test_field_block"/>');
chai.assert.equal(this.trashcan.contents_.length, 1); chai.assert.equal(this.trashcan.contents_.length, 1);
}); });
test("Different Coords", function() { test("Different Coords", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type" x="10" y="10"/>'); fireDeleteEvent(
fireDeleteEvent(this.workspace, '<block type="dummy_type" x="20" y="20"/>'); this.workspace, '<block type="test_field_block" x="10" y="10"/>');
fireDeleteEvent(
this.workspace, '<block type="test_field_block" x="20" y="20"/>');
chai.assert.equal(this.trashcan.contents_.length, 1); chai.assert.equal(this.trashcan.contents_.length, 1);
}); });
test("Different IDs", function() { test("Different IDs", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type" id="id1"/>'); fireDeleteEvent(
fireDeleteEvent(this.workspace, '<block type="dummy_type" id="id2"/>'); this.workspace, '<block type="test_field_block" id="id1"/>');
fireDeleteEvent(
this.workspace, '<block type="test_field_block" id="id2"/>');
chai.assert.equal(this.trashcan.contents_.length, 1); chai.assert.equal(this.trashcan.contents_.length, 1);
}); });
test("No Disabled - Disabled True", function() { test("No Disabled - Disabled True", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(
fireDeleteEvent(this.workspace, '<block type="dummy_type" disabled="true"/>'); this.workspace, '<block type="test_field_block"/>');
fireDeleteEvent(
this.workspace, '<block type="test_field_block" disabled="true"/>');
// Disabled tags get removed because disabled blocks aren't allowed to // Disabled tags get removed because disabled blocks aren't allowed to
// be dragged from flyouts. See #2239 and #3243. // be dragged from flyouts. See #2239 and #3243.
chai.assert.equal(this.trashcan.contents_.length, 1); chai.assert.equal(this.trashcan.contents_.length, 1);
}); });
test("No Editable - Editable False", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>');
fireDeleteEvent(this.workspace, '<block type="dummy_type" editable="false"/>');
chai.assert.equal(this.trashcan.contents_.length, 2);
});
test("No Movable - Movable False", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>');
fireDeleteEvent(this.workspace, '<block type="dummy_type" movable="false"/>');
chai.assert.equal(this.trashcan.contents_.length, 2);
});
test("Different Field Values", function() { test("Different Field Values", function() {
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <field name="dummy_name">dummy_value1</field>' + ' <field name="NAME">dummy_value1</field>' +
'</block>' '</block>'
); );
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <field name="dummy_name">dummy_value2</field>' + ' <field name="NAME">dummy_value2</field>' +
'</block>' '</block>'
); );
chai.assert.equal(this.trashcan.contents_.length, 2); chai.assert.equal(this.trashcan.contents_.length, 2);
}); });
test("No Values - Values", function() { test("No Values - Values", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<block type="row_block"/>');
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="row_block">' +
' <value name="dummy_input">' + ' <value name="INPUT">' +
' <block type="dummy_type"/>' + ' <block type="row_block"/>' +
' </value>' + ' </value>' +
'</block>' '</block>'
); );
@@ -164,27 +169,27 @@ suite("Trashcan", function() {
}); });
test("Different Value Blocks", function() { test("Different Value Blocks", function() {
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="row_block">' +
' <value name="dummy_input">' + ' <value name="INPUT">' +
' <block type="dummy_type1"/>' + ' <block type="row_block"/>' +
' </value>' + ' </value>' +
'</block>' '</block>'
); );
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="row_block">' +
' <value name="dummy_input">' + ' <value name="INPUT">' +
' <block type="dummy_type2"/>' + ' <block type="row_block2"/>' +
' </value>' + ' </value>' +
'</block>' '</block>'
); );
chai.assert.equal(this.trashcan.contents_.length, 2); chai.assert.equal(this.trashcan.contents_.length, 2);
}); });
test("No Statements - Statements", function() { test("No Statements - Statements", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<block type="statement_block"/>');
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="statement_block">' +
' <statement name="dummy_input">' + ' <statement name="NAME">' +
' <block type="dummy_type"/>' + ' <block type="statement_block"/>' +
' </statement>' + ' </statement>' +
'</block>' '</block>'
); );
@@ -192,27 +197,27 @@ suite("Trashcan", function() {
}); });
test("Different Statement Blocks", function() { test("Different Statement Blocks", function() {
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="statement_block">' +
' <statement name="dummy_input">' + ' <statement name="NAME">' +
' <block type="dummy_type1"/>' + ' <block type="statement_block"/>' +
' </statement>' + ' </statement>' +
'</block>' '</block>'
); );
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <statement name="dummy_input">' + ' <statement name="NAME">' +
' <block type="dummy_type2"/>' + ' <block type="statement_block2"/>' +
' </statement>' + ' </statement>' +
'</block>' '</block>'
); );
chai.assert.equal(this.trashcan.contents_.length, 2); chai.assert.equal(this.trashcan.contents_.length, 2);
}); });
test("No Next - Next", function() { test("No Next - Next", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<block type="stack_block"/>');
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="stack_block">' +
' <next>' + ' <next>' +
' <block type="dummy_type"/>' + ' <block type="stack_block"/>' +
' </next>' + ' </next>' +
'</block>' '</block>'
); );
@@ -220,25 +225,25 @@ suite("Trashcan", function() {
}); });
test("Different Next Blocks", function() { test("Different Next Blocks", function() {
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="stack_block">' +
' <next>' + ' <next>' +
' <block type="dummy_type1"/>' + ' <block type="stack_block"/>' +
' </next>' + ' </next>' +
'</block>' '</block>'
); );
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="stack_block">' +
' <next>' + ' <next>' +
' <block type="dummy_type2"/>' + ' <block type="stack_block2"/>' +
' </next>' + ' </next>' +
'</block>' '</block>'
); );
chai.assert.equal(this.trashcan.contents_.length, 2); chai.assert.equal(this.trashcan.contents_.length, 2);
}); });
test("No Comment - Comment", function() { test("No Comment - Comment", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>'); fireDeleteEvent(this.workspace, '<block type="test_field_block"/>');
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <comment>comment_text</comment>' + ' <comment>comment_text</comment>' +
'</block>' '</block>'
); );
@@ -246,12 +251,12 @@ suite("Trashcan", function() {
}); });
test("Different Comment Text", function() { test("Different Comment Text", function() {
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <comment>comment_text1</comment>' + ' <comment>comment_text1</comment>' +
'</block>' '</block>'
); );
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <comment>comment_text2</comment>' + ' <comment>comment_text2</comment>' +
'</block>' '</block>'
); );
@@ -259,12 +264,12 @@ suite("Trashcan", function() {
}); });
test("Different Comment Size", function() { test("Different Comment Size", function() {
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <comment h="10" w="10">comment_text</comment>' + ' <comment h="10" w="10">comment_text</comment>' +
'</block>' '</block>'
); );
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <comment h="20" w="20">comment_text</comment>' + ' <comment h="20" w="20">comment_text</comment>' +
'</block>' '</block>'
); );
@@ -273,36 +278,27 @@ suite("Trashcan", function() {
}); });
test("Different Comment Pinned", function() { test("Different Comment Pinned", function() {
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <comment pinned="false">comment_text</comment>' + ' <comment pinned="false">comment_text</comment>' +
'</block>' '</block>'
); );
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="test_field_block">' +
' <comment pinned="true">comment_text</comment>' + ' <comment pinned="true">comment_text</comment>' +
'</block>' '</block>'
); );
// pinned tags are removed b/c the blocks appear the same. // pinned tags are removed b/c the blocks appear the same.
chai.assert.equal(this.trashcan.contents_.length, 1); chai.assert.equal(this.trashcan.contents_.length, 1);
}); });
test("No Mutator - Mutator", function() {
fireDeleteEvent(this.workspace, '<block type="dummy_type"/>');
fireDeleteEvent(this.workspace,
'<block type="dummy_type">' +
' <mutation dummy_attribute="dummy_value"></mutation>' +
'</block>'
);
chai.assert.equal(this.trashcan.contents_.length, 2);
});
test("Different Mutator", function() { test("Different Mutator", function() {
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="xml_block">' +
' <mutation dummy_attribute="dummy_value1"></mutation>' + ' <mutation hasInput="true"></mutation>' +
'</block>' '</block>'
); );
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type">' + '<block type="xml_block">' +
' <mutation dummy_attribute="dummy_value2"></mutation>' + ' <mutation hasInputt="false"></mutation>' +
'</block>' '</block>'
); );
chai.assert.equal(this.trashcan.contents_.length, 2); chai.assert.equal(this.trashcan.contents_.length, 2);
@@ -312,22 +308,10 @@ suite("Trashcan", function() {
test("Max 0", function() { test("Max 0", function() {
this.workspace.options.maxTrashcanContents = 0; this.workspace.options.maxTrashcanContents = 0;
fireDeleteEvent(this.workspace, fireDeleteEvent(this.workspace,
'<block type="dummy_type"/>' '<block type="test_field_block"/>'
); );
chai.assert.equal(this.trashcan.contents_.length, 0); chai.assert.equal(this.trashcan.contents_.length, 0);
this.workspace.options.maxTrashcanContents = Infinity; this.workspace.options.maxTrashcanContents = Infinity;
}); });
test("Last In First Out", function() {
this.workspace.options.maxTrashcanContents = 1;
fireDeleteEvent(this.workspace, '<block type="dummy_type1"/>');
fireDeleteEvent(this.workspace, '<block type="dummy_type2"/>');
chai.assert.equal(this.trashcan.contents_.length, 1);
chai.assert.equal(
Blockly.Xml.textToDom(this.trashcan.contents_[0])
.getAttribute('type'),
'dummy_type2'
);
this.workspace.options.maxTrashcanContents = Infinity;
});
}); });
}); });