diff --git a/core/xml.js b/core/xml.js
index 8f0c2738c..d8b2cd61d 100644
--- a/core/xml.js
+++ b/core/xml.js
@@ -91,6 +91,13 @@ Blockly.Xml.blockToDom = function(block, opt_noId) {
if (field.name && field.EDITABLE) {
var container = goog.dom.createDom('field', null, field.getValue());
container.setAttribute('name', field.name);
+ if (field instanceof Blockly.FieldVariable) {
+ var variable = block.workspace.getVariable(field.getValue());
+ if (variable) {
+ container.setAttribute('id', variable.getId());
+ container.setAttribute('variableType', variable.type);
+ }
+ }
element.appendChild(container);
}
}
diff --git a/tests/jsunit/xml_test.js b/tests/jsunit/xml_test.js
index d77ed9343..e0db19c28 100644
--- a/tests/jsunit/xml_test.js
+++ b/tests/jsunit/xml_test.js
@@ -19,6 +19,12 @@
*/
'use strict';
+goog.require('goog.testing');
+goog.require('goog.testing.MockControl');
+
+var mockControl_;
+var saved_msg = Blockly.Msg.DELETE_VARIABLE;
+var workspace;
var XML_TEXT = ['',
' ',
' ',
@@ -46,6 +52,52 @@ var XML_TEXT = ['',
' ',
''].join('\n');
+
+function xmlTest_setUpWithMockBlocks() {
+ workspace = new Blockly.Workspace();
+ mockControl_ = new goog.testing.MockControl();
+ // Need to define this because field_variable's dropdownCreate() calls replace
+ // on undefined value, Blockly.Msg.DELETE_VARIABLE. To fix this, define
+ // Blockly.Msg.DELETE_VARIABLE as %1 so the replace function finds the %1 it
+ // expects.
+ Blockly.Msg.DELETE_VARIABLE = '%1';
+}
+
+function xmlTest_tearDownWithMockBlocks() {
+ mockControl_.$tearDown();
+ workspace.dispose();
+ delete Blockly.Blocks.field_variable_test_block;
+ Blockly.Msg.DELETE_VARIABLE = saved_msg;
+}
+
+/**
+ * Check the values of the non variable field dom.
+ * @param {!Element} fieldDom The xml dom of the non variable field.
+ * @param {!string} name The expected name of the variable.
+ * @param {!string} text The expected text of the variable.
+ */
+function xmlTest_checkNonVariableField(fieldDom, name, text) {
+ assertEquals(text, fieldDom.textContent);
+ assertEquals(name, fieldDom.getAttribute('name'));
+ assertNull(fieldDom.getAttribute('id'));
+ assertNull(fieldDom.getAttribute('variableType'));
+}
+
+/**
+ * Check the values of the variable field DOM.
+ * @param {!Element} fieldDom The xml dom of the variable field.
+ * @param {!string} name The expected name of the variable.
+ * @param {!string} type The expected type of the variable.
+ * @param {!string} id The expected id of the variable.
+ * @param {!string} text The expected text of the variable.
+ */
+function xmlTest_checkVariableDomValues(fieldDom, name, type, id, text) {
+ assertEquals(name, fieldDom.getAttribute('name'));
+ assertEquals(type, fieldDom.getAttribute('variableType'));
+ assertEquals(id, fieldDom.getAttribute('id'));
+ assertEquals(text, fieldDom.textContent);
+}
+
function test_textToDom() {
var dom = Blockly.Xml.textToDom(XML_TEXT);
assertEquals('XML tag', 'xml', dom.nodeName);
@@ -68,7 +120,7 @@ function test_domToWorkspace() {
}
};
- var workspace = new Blockly.Workspace();
+ workspace = new Blockly.Workspace();
try {
var dom = Blockly.Xml.textToDom(
'' +
@@ -110,7 +162,7 @@ function test_appendDomToWorkspace() {
' ' +
' ' +
'');
- var workspace = new Blockly.Workspace();
+ workspace = new Blockly.Workspace();
Blockly.Xml.appendDomToWorkspace(dom, workspace);
assertEquals('Block count', 1, workspace.getAllBlocks().length);
var newBlockIds = Blockly.Xml.appendDomToWorkspace(dom, workspace);
@@ -121,3 +173,69 @@ function test_appendDomToWorkspace() {
workspace.dispose();
}
}
+
+function test_blockToDom_fieldToDom_trivial() {
+ Blockly.defineBlocksWithJsonArray([{
+ 'type': 'field_variable_test_block',
+ 'message0': '%1',
+ 'args0': [
+ {
+ 'type': 'field_variable',
+ 'name': 'VAR',
+ 'variable': 'item'
+ }
+ ],
+ }]);
+ xmlTest_setUpWithMockBlocks()
+ workspace.createVariable('name1', 'type1', 'id1');
+ var block = new Blockly.Block(workspace, 'field_variable_test_block');
+ block.inputList[0].fieldRow[0].setValue('name1');
+ var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0];
+ xmlTest_checkVariableDomValues(resultFieldDom, 'VAR', 'type1', 'id1', 'name1')
+ xmlTest_tearDownWithMockBlocks()
+}
+
+function test_blockToDom_fieldToDom_defaultCase() {
+ Blockly.defineBlocksWithJsonArray([{
+ 'type': 'field_variable_test_block',
+ 'message0': '%1',
+ 'args0': [
+ {
+ 'type': 'field_variable',
+ 'name': 'VAR',
+ 'variable': 'item'
+ }
+ ],
+ }]);
+ xmlTest_setUpWithMockBlocks()
+ var mockGenUid = mockControl_.createMethodMock(Blockly.utils, 'genUid');
+ mockGenUid().$returns('1');
+ mockGenUid().$replay();
+ workspace.createVariable('name1');
+ var block = new Blockly.Block(workspace, 'field_variable_test_block');
+ block.inputList[0].fieldRow[0].setValue('name1');
+ var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0];
+ // Expect type is '' and id is '1' since we don't specify type and id.
+ xmlTest_checkVariableDomValues(resultFieldDom, 'VAR', '', '1', 'name1')
+ xmlTest_tearDownWithMockBlocks()
+}
+
+function test_blockToDom_fieldToDom_notAFieldVariable() {
+ Blockly.defineBlocksWithJsonArray([{
+ "type": "field_angle_test_block",
+ "message0": "%1",
+ "args0": [
+ {
+ "type": "field_angle",
+ "name": "VAR",
+ "angle": 90
+ }
+ ],
+ }]);
+ xmlTest_setUpWithMockBlocks()
+ var block = new Blockly.Block(workspace, 'field_angle_test_block');
+ var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0];
+ xmlTest_checkNonVariableField(resultFieldDom, 'VAR', '90');
+ delete Blockly.Blocks.field_angle_block;
+ xmlTest_tearDownWithMockBlocks()
+}