From 7e03924d4ca3ef57a0d0401fd244fad0e023cc14 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Tue, 31 Mar 2020 12:25:53 -0700 Subject: [PATCH 001/139] Remove mutator bump timeout. Anything that changes the shape of a block should be calling bumpNeighbors from inside BlockSvg. So this call is unnecessary. If this call is making something bump that normally wouldn't, that should be treated as a bug, and the root should be made to call bumpNieghbours. --- core/mutator.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/core/mutator.js b/core/mutator.js index 313e3f101..540178d05 100644 --- a/core/mutator.js +++ b/core/mutator.js @@ -386,13 +386,6 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) { if (oldMutation != newMutation) { Blockly.Events.fire(new Blockly.Events.BlockChange( block, 'mutation', null, oldMutation, newMutation)); - // Ensure that any bump is part of this mutation's event group. - var group = Blockly.Events.getGroup(); - setTimeout(function() { - Blockly.Events.setGroup(group); - block.bumpNeighbours(); - Blockly.Events.setGroup(false); - }, Blockly.BUMP_DELAY); } // Don't update the bubble until the drag has ended, to avoid moving blocks From 7a006b0307644405d137984a38bc014c818c0076 Mon Sep 17 00:00:00 2001 From: Abby Date: Thu, 2 Apr 2020 17:55:03 -0700 Subject: [PATCH 002/139] Update version number and build --- blockly_compressed.js | 2 +- msg/json/en.json | 2 +- package-lock.json | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/blockly_compressed.js b/blockly_compressed.js index 08b305a36..3a13f799b 100644 --- a/blockly_compressed.js +++ b/blockly_compressed.js @@ -767,7 +767,7 @@ Blockly.WidgetDiv.show=function(a,b,c){Blockly.WidgetDiv.hide();Blockly.WidgetDi Blockly.WidgetDiv.hide=function(){if(Blockly.WidgetDiv.isVisible()){Blockly.WidgetDiv.owner_=null;var a=Blockly.WidgetDiv.DIV;a.style.display="none";a.style.left="";a.style.top="";Blockly.WidgetDiv.dispose_&&Blockly.WidgetDiv.dispose_();Blockly.WidgetDiv.dispose_=null;a.textContent="";Blockly.WidgetDiv.rendererClassName_&&(Blockly.utils.dom.removeClass(a,Blockly.WidgetDiv.rendererClassName_),Blockly.WidgetDiv.rendererClassName_="");Blockly.WidgetDiv.themeClassName_&&(Blockly.utils.dom.removeClass(a, Blockly.WidgetDiv.themeClassName_),Blockly.WidgetDiv.themeClassName_="");Blockly.getMainWorkspace().markFocused()}};Blockly.WidgetDiv.isVisible=function(){return!!Blockly.WidgetDiv.owner_};Blockly.WidgetDiv.hideIfOwner=function(a){Blockly.WidgetDiv.owner_==a&&Blockly.WidgetDiv.hide()};Blockly.WidgetDiv.positionInternal_=function(a,b,c){Blockly.WidgetDiv.DIV.style.left=a+"px";Blockly.WidgetDiv.DIV.style.top=b+"px";Blockly.WidgetDiv.DIV.style.height=c+"px"}; Blockly.WidgetDiv.positionWithAnchor=function(a,b,c,d){var e=Blockly.WidgetDiv.calculateY_(a,b,c);a=Blockly.WidgetDiv.calculateX_(a,b,c,d);0>e?Blockly.WidgetDiv.positionInternal_(a,0,c.height+e):Blockly.WidgetDiv.positionInternal_(a,e,c.height)};Blockly.WidgetDiv.calculateX_=function(a,b,c,d){if(d)return b=Math.max(b.right-c.width,a.left),Math.min(b,a.right-c.width);b=Math.min(b.left,a.right-c.width);return Math.max(b,a.left)}; -Blockly.WidgetDiv.calculateY_=function(a,b,c){return b.bottom+c.height>=a.bottom?b.top-c.height:b.bottom};Blockly.VERSION="3.20200402.0";Blockly.mainWorkspace=null;Blockly.selected=null;Blockly.draggingConnections=[];Blockly.clipboardXml_=null;Blockly.clipboardSource_=null;Blockly.clipboardTypeCounts_=null;Blockly.cache3dSupported_=null;Blockly.parentContainer=null;Blockly.svgSize=function(a){return{width:a.cachedWidth_,height:a.cachedHeight_}};Blockly.resizeSvgContents=function(a){a.resizeContents()}; +Blockly.WidgetDiv.calculateY_=function(a,b,c){return b.bottom+c.height>=a.bottom?b.top-c.height:b.bottom};Blockly.VERSION="3.20200402.0-develop";Blockly.mainWorkspace=null;Blockly.selected=null;Blockly.draggingConnections=[];Blockly.clipboardXml_=null;Blockly.clipboardSource_=null;Blockly.clipboardTypeCounts_=null;Blockly.cache3dSupported_=null;Blockly.parentContainer=null;Blockly.svgSize=function(a){return{width:a.cachedWidth_,height:a.cachedHeight_}};Blockly.resizeSvgContents=function(a){a.resizeContents()}; Blockly.svgResize=function(a){for(;a.options.parentWorkspace;)a=a.options.parentWorkspace;var b=a.getParentSvg(),c=b.parentNode;if(c){var d=c.offsetWidth;c=c.offsetHeight;b.cachedWidth_!=d&&(b.setAttribute("width",d+"px"),b.cachedWidth_=d);b.cachedHeight_!=c&&(b.setAttribute("height",c+"px"),b.cachedHeight_=c);a.resize()}}; Blockly.onKeyDown=function(a){var b=Blockly.mainWorkspace;if(b&&!(Blockly.utils.isTargetInput(a)||b.rendered&&!b.isVisible()))if(b.options.readOnly)Blockly.navigation.onKeyPress(a);else{var c=!1;if(a.keyCode==Blockly.utils.KeyCodes.ESC)Blockly.hideChaff(),Blockly.navigation.onBlocklyAction(Blockly.navigation.ACTION_EXIT);else{if(Blockly.navigation.onKeyPress(a))return;if(a.keyCode==Blockly.utils.KeyCodes.BACKSPACE||a.keyCode==Blockly.utils.KeyCodes.DELETE){a.preventDefault();if(Blockly.Gesture.inProgress())return; Blockly.selected&&Blockly.selected.isDeletable()&&(c=!0)}else if(a.altKey||a.ctrlKey||a.metaKey){if(Blockly.Gesture.inProgress())return;Blockly.selected&&Blockly.selected.isDeletable()&&Blockly.selected.isMovable()&&(a.keyCode==Blockly.utils.KeyCodes.C?(Blockly.hideChaff(),Blockly.copy_(Blockly.selected)):a.keyCode!=Blockly.utils.KeyCodes.X||Blockly.selected.workspace.isFlyout||(Blockly.copy_(Blockly.selected),c=!0));a.keyCode==Blockly.utils.KeyCodes.V?Blockly.clipboardXml_&&(a=Blockly.clipboardSource_, diff --git a/msg/json/en.json b/msg/json/en.json index 7570be7d2..2a1dd30a3 100644 --- a/msg/json/en.json +++ b/msg/json/en.json @@ -1,7 +1,7 @@ { "@metadata": { "author": "Ellen Spertus ", - "lastupdated": "2020-04-02 16:01:48.114405", + "lastupdated": "2020-04-02 17:54:16.459011", "locale": "en", "messagedocumentation" : "qqq" }, diff --git a/package-lock.json b/package-lock.json index 0e0db42f4..c1af1d21d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "blockly", - "version": "3.20200402.0", + "version": "3.20200402.0-develop", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 58146d7c9..463f17d06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blockly", - "version": "3.20200402.0", + "version": "3.20200402.0-develop", "description": "Blockly is a library for building visual programming editors.", "keywords": [ "blockly" From 06f6c22a27dffa6eb6eba0f7e9ec115cc45edf6a Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Fri, 3 Apr 2020 14:36:19 -0700 Subject: [PATCH 003/139] Fix field colour in headless (#3795) --- core/field_colour.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/field_colour.js b/core/field_colour.js index 6cf82d089..562bdaeec 100644 --- a/core/field_colour.js +++ b/core/field_colour.js @@ -220,7 +220,7 @@ Blockly.FieldColour.prototype.doValueUpdate_ = function(newValue) { this.value_ = newValue; if (this.borderRect_) { this.borderRect_.style.fill = newValue; - } else if (this.sourceBlock_) { + } else if (this.sourceBlock_ && this.sourceBlock_.rendered) { this.sourceBlock_.pathObject.svgPath.setAttribute('fill', newValue); this.sourceBlock_.pathObject.svgPath.setAttribute('stroke', '#fff'); } From 4f9b4a707a00631be4ba3d4e36f9696aeb1b578c Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Fri, 3 Apr 2020 14:50:33 -0700 Subject: [PATCH 004/139] Add field set source block tests (#3796) * Set the source block on fields in mocha tests. --- tests/mocha/.eslintrc.json | 4 ++-- tests/mocha/field_angle_test.js | 5 +++++ tests/mocha/field_checkbox_test.js | 5 +++++ tests/mocha/field_colour_test.js | 5 +++++ tests/mocha/field_dropdown_test.js | 5 +++++ tests/mocha/field_label_serializable_test.js | 5 +++++ tests/mocha/field_label_test.js | 5 +++++ tests/mocha/field_number_test.js | 5 +++++ tests/mocha/field_textinput_test.js | 5 +++++ tests/mocha/test_helpers.js | 12 +++++++++++- 10 files changed, 53 insertions(+), 3 deletions(-) diff --git a/tests/mocha/.eslintrc.json b/tests/mocha/.eslintrc.json index b4bb40fec..8e3fd2a25 100644 --- a/tests/mocha/.eslintrc.json +++ b/tests/mocha/.eslintrc.json @@ -16,8 +16,8 @@ "assertNotUndefined": true, "defineStackBlock": true, "defineRowBlock": true, - "defineStatementBlock": true - + "defineStatementBlock": true, + "createTestBlock": true }, "extends": "../../.eslintrc.json" } diff --git a/tests/mocha/field_angle_test.js b/tests/mocha/field_angle_test.js index 6bbc838a4..3c59bf627 100644 --- a/tests/mocha/field_angle_test.js +++ b/tests/mocha/field_angle_test.js @@ -133,6 +133,11 @@ suite('Angle Fields', function() { this.angleField.setValue('-Infinity'); assertValueDefault(this.angleField); }); + test('With source block', function() { + this.angleField.setSourceBlock(createTestBlock()); + this.angleField.setValue(2.5); + assertValue(this.angleField, 2.5); + }); }); suite('Value -> New Value', function() { setup(function() { diff --git a/tests/mocha/field_checkbox_test.js b/tests/mocha/field_checkbox_test.js index edfdebee2..9348bbb4f 100644 --- a/tests/mocha/field_checkbox_test.js +++ b/tests/mocha/field_checkbox_test.js @@ -87,6 +87,11 @@ suite('Checkbox Fields', function() { this.checkboxField.setValue('FALSE'); assertValue(this.checkboxField, 'FALSE', 'false'); }); + test('With source block', function() { + this.checkboxField.setSourceBlock(createTestBlock()); + this.checkboxField.setValue('FALSE'); + assertValue(this.checkboxField, 'FALSE', 'false'); + }); }); suite('False -> New Value', function() { setup(function() { diff --git a/tests/mocha/field_colour_test.js b/tests/mocha/field_colour_test.js index 16878c47e..d2987a691 100644 --- a/tests/mocha/field_colour_test.js +++ b/tests/mocha/field_colour_test.js @@ -168,6 +168,11 @@ suite('Colour Fields', function() { this.colourField.setValue('red'); assertValue(this.colourField, '#ff0000', '#f00'); }); + test('With source block', function() { + this.colourField.setSourceBlock(createTestBlock()); + this.colourField.setValue('#bcbcbc'); + assertValue(this.colourField, '#bcbcbc', '#bcbcbc'); + }); }); suite('Value -> New Value', function() { setup(function() { diff --git a/tests/mocha/field_dropdown_test.js b/tests/mocha/field_dropdown_test.js index 0bbc36724..0d6e26c30 100644 --- a/tests/mocha/field_dropdown_test.js +++ b/tests/mocha/field_dropdown_test.js @@ -148,6 +148,11 @@ suite('Dropdown Fields', function() { this.dropdownField.setValue('B'); assertValue(this.dropdownField, 'B', 'b'); }); + test('With source block', function() { + this.dropdownField.setSourceBlock(createTestBlock()); + this.dropdownField.setValue('B'); + assertValue(this.dropdownField, 'B', 'b'); + }); }); suite('Validators', function() { setup(function() { diff --git a/tests/mocha/field_label_serializable_test.js b/tests/mocha/field_label_serializable_test.js index fb490a6ee..676e14fe3 100644 --- a/tests/mocha/field_label_serializable_test.js +++ b/tests/mocha/field_label_serializable_test.js @@ -136,6 +136,11 @@ suite('Label Serializable Fields', function() { this.labelField.setValue(false); assertValue(this.labelField, 'false'); }); + test('With source block', function() { + this.labelField.setSourceBlock(createTestBlock()); + this.labelField.setValue('newValue'); + assertValue(this.labelField, 'newValue'); + }); }); suite('Value -> New Value', function() { setup(function() { diff --git a/tests/mocha/field_label_test.js b/tests/mocha/field_label_test.js index b2cf8be95..fba48723c 100644 --- a/tests/mocha/field_label_test.js +++ b/tests/mocha/field_label_test.js @@ -125,6 +125,11 @@ suite('Label Fields', function() { this.labelField.setValue(false); assertValue(this.labelField, 'false'); }); + test('With source block', function() { + this.labelField.setSourceBlock(createTestBlock()); + this.labelField.setValue('newValue'); + assertValue(this.labelField, 'newValue'); + }); }); suite('Value -> New Value', function() { setup(function() { diff --git a/tests/mocha/field_number_test.js b/tests/mocha/field_number_test.js index 91edca652..c6564fad7 100644 --- a/tests/mocha/field_number_test.js +++ b/tests/mocha/field_number_test.js @@ -158,6 +158,11 @@ suite('Number Fields', function() { this.numberField.setValue('-Infinity'); assertValue(this.numberField, -Infinity); }); + test('With source block', function() { + this.numberField.setSourceBlock(createTestBlock()); + this.numberField.setValue(2.5); + assertValue(this.numberField, 2.5); + }); }); suite('Value -> New Value', function() { setup(function() { diff --git a/tests/mocha/field_textinput_test.js b/tests/mocha/field_textinput_test.js index a3acdec61..9fcbc16c4 100644 --- a/tests/mocha/field_textinput_test.js +++ b/tests/mocha/field_textinput_test.js @@ -109,6 +109,11 @@ suite('Text Input Fields', function() { this.textInputField.setValue(false); assertValue(this.textInputField, 'false'); }); + test('With source block', function() { + this.textInputField.setSourceBlock(createTestBlock()); + this.textInputField.setValue('newValue'); + assertValue(this.textInputField, 'newValue'); + }); }); suite('Value -> New Value', function() { setup(function() { diff --git a/tests/mocha/test_helpers.js b/tests/mocha/test_helpers.js index 6ff98c327..15ddc3f88 100644 --- a/tests/mocha/test_helpers.js +++ b/tests/mocha/test_helpers.js @@ -7,7 +7,7 @@ /* exported assertEquals, assertNotEquals, assertArrayEquals, assertTrue, assertFalse, assertNull, assertNotNull, assertNotNullNorUndefined, assert, isEqualArrays, assertUndefined, assertNotUndefined, - defineRowBlock, defineStackBlock, defineStatementBlock */ + defineRowBlock, defineStackBlock, defineStatementBlock, createTestBlock */ function _argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) { return args.length == expectedNumberOfNonCommentArgs + 1; } @@ -181,3 +181,13 @@ function defineStatementBlock() { "helpUrl": "" }]); } + +function createTestBlock() { + return { + id: 'test', + rendered: false, + workspace: { + rendered: false + } + }; +} From b64028521f78483aa0f9620b0ac350b55dec0dfe Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Fri, 3 Apr 2020 17:09:08 -0700 Subject: [PATCH 005/139] Fix jsdoc typing in theme. (#3798) --- core/theme.js | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/core/theme.js b/core/theme.js index 311782f55..ea88f5a64 100644 --- a/core/theme.js +++ b/core/theme.js @@ -97,22 +97,22 @@ Blockly.Theme.CategoryStyle; /** * A component style. * @typedef {{ - * workspaceBackgroundColour:string?, - * toolboxBackgroundColour:string?, - * toolboxForegroundColour:string?, - * flyoutBackgroundColour:string?, - * flyoutForegroundColour:string?, - * flyoutOpacity:number?, - * scrollbarColour:string?, - * scrollbarOpacity:number?, - * insertionMarkerColour:string?, - * insertionMarkerOpacity:number?, - * markerColour:string?, - * cursorColour:string?, - * selectedGlowColour:string?, - * selectedGlowOpacity:number?, - * replacementGlowColour:string?, - * replacementGlowOpacity:number? + * workspaceBackgroundColour:?string, + * toolboxBackgroundColour:?string, + * toolboxForegroundColour:?string, + * flyoutBackgroundColour:?string, + * flyoutForegroundColour:?string, + * flyoutOpacity:?number, + * scrollbarColour:?string, + * scrollbarOpacity:?number, + * insertionMarkerColour:?string, + * insertionMarkerOpacity:?number, + * markerColour:?string, + * cursorColour:?string, + * selectedGlowColour:?string, + * selectedGlowOpacity:?number, + * replacementGlowColour:?string, + * replacementGlowOpacity:?number * }} */ Blockly.Theme.ComponentStyle; @@ -120,9 +120,9 @@ Blockly.Theme.ComponentStyle; /** * A font style. * @typedef {{ - * family:string?, - * weight:string?, - * size:number? + * family:?string, + * weight:?string, + * size:?number * }} */ Blockly.Theme.FontStyle; From bcfde92afb7b11d2a37b148ef9af0c3f7b6cf0d1 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Mon, 6 Apr 2020 09:59:30 -0700 Subject: [PATCH 006/139] Fix setValue not handling block disposal (#3766) --- core/field.js | 10 +++++++--- tests/blocks/test_blocks.js | 16 ++++++++++++++++ tests/playground.html | 3 +++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/core/field.js b/core/field.js index 2c6328fc8..274bebf86 100644 --- a/core/field.js +++ b/core/field.js @@ -858,16 +858,20 @@ Blockly.Field.prototype.setValue = function(newValue) { return; } } + var source = this.sourceBlock_; + if (source && source.disposed) { + doLogging && console.log('source disposed, return'); + return; + } var oldValue = this.getValue(); if (oldValue === newValue) { doLogging && console.log('same, return'); - // No change. return; } - if (this.sourceBlock_ && Blockly.Events.isEnabled()) { + if (source && Blockly.Events.isEnabled()) { Blockly.Events.fire(new Blockly.Events.BlockChange( - this.sourceBlock_, 'field', this.name || null, oldValue, newValue)); + source, 'field', this.name || null, oldValue, newValue)); } this.doValueUpdate_(newValue); if (this.isDirty_) { diff --git a/tests/blocks/test_blocks.js b/tests/blocks/test_blocks.js index 47b44317d..0bb9036b6 100644 --- a/tests/blocks/test_blocks.js +++ b/tests/blocks/test_blocks.js @@ -1343,6 +1343,22 @@ Blockly.Blocks['test_images_clickhandler'] = { } }; +Blockly.Blocks['test_validators_dispose_block'] = { + init: function() { + this.appendDummyInput() + .appendField("dispose block") + .appendField(new Blockly.FieldTextInput("default", this.validate), "INPUT"); + this.setColour(230); + this.setCommentText('Any changes to the text cause the block to be disposed'); + }, + + validate: function(newValue) { + if (newValue != "default") { + this.getSourceBlock().dispose(true); + } + } +}; + Blockly.Blocks['test_validators_text_null'] = { init: function() { this.appendDummyInput() diff --git a/tests/playground.html b/tests/playground.html index 9f3d5cfd9..bba66449a 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -1677,6 +1677,9 @@ var spaghettiXml = [ + + + From ea4b30bfa6cfc80037db0d82d18c15c3594cf704 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 9 Apr 2020 15:58:33 +0200 Subject: [PATCH 007/139] Localisation updates from https://translatewiki.net. --- msg/json/ar.json | 16 +++++++-------- msg/json/az.json | 6 +++--- msg/json/ba.json | 4 ++-- msg/json/be-tarask.json | 4 ++-- msg/json/bg.json | 12 ++++++------ msg/json/bn.json | 8 ++++---- msg/json/br.json | 10 ++++++---- msg/json/ca.json | 6 +++--- msg/json/cs.json | 16 +++++++-------- msg/json/da.json | 8 ++++---- msg/json/de.json | 16 +++++++-------- msg/json/diq.json | 6 +++--- msg/json/el.json | 20 +++++++++---------- msg/json/en-gb.json | 4 ++-- msg/json/eo.json | 4 ++-- msg/json/es.json | 24 +++++++++++------------ msg/json/et.json | 4 ++-- msg/json/eu.json | 10 +++++----- msg/json/fa.json | 12 ++++++------ msg/json/fi.json | 22 ++++++++++----------- msg/json/fr.json | 28 +++++++++++++-------------- msg/json/gl.json | 5 ++--- msg/json/he.json | 43 +++++++++++++++++++++++++++++++---------- msg/json/hi.json | 8 ++++---- msg/json/hu.json | 24 +++++++++++------------ msg/json/hy.json | 1 + msg/json/ia.json | 4 ++-- msg/json/id.json | 10 +++++----- msg/json/is.json | 6 +++--- msg/json/it.json | 14 +++++++------- msg/json/ja.json | 22 ++++++++++----------- msg/json/kab.json | 6 +++--- msg/json/kn.json | 4 ++-- msg/json/ko.json | 20 +++++++++---------- msg/json/lb.json | 4 ++-- msg/json/lrc.json | 4 ++-- msg/json/lt.json | 4 ++-- msg/json/lv.json | 4 ++-- msg/json/nb.json | 4 ++-- msg/json/nl.json | 26 ++++++++++++------------- msg/json/pl.json | 32 +++++++++++++++--------------- msg/json/pt-br.json | 34 ++++++++++++++++---------------- msg/json/pt.json | 26 ++++++++++++------------- msg/json/qqq.json | 9 +++++++++ msg/json/ro.json | 8 ++++---- msg/json/ru.json | 14 +++++++------- msg/json/sc.json | 4 ++-- msg/json/sd.json | 2 +- msg/json/shn.json | 4 ++-- msg/json/sk.json | 12 ++++++------ msg/json/sl.json | 4 ++-- msg/json/sq.json | 4 ++-- msg/json/sr.json | 12 ++++++------ msg/json/sv.json | 10 +++++----- msg/json/ta.json | 4 ++-- msg/json/tcy.json | 6 +++--- msg/json/te.json | 4 ++-- msg/json/th.json | 12 ++++++------ msg/json/tr.json | 30 ++++++++++++++-------------- msg/json/uk.json | 8 ++++---- msg/json/ur.json | 6 +++--- msg/json/vi.json | 10 +++++----- msg/json/zh-hans.json | 22 ++++++++++----------- msg/json/zh-hant.json | 14 +++++++------- 64 files changed, 389 insertions(+), 355 deletions(-) diff --git a/msg/json/ar.json b/msg/json/ar.json index bd3386e41..d450e05e3 100644 --- a/msg/json/ar.json +++ b/msg/json/ar.json @@ -1,16 +1,16 @@ { "@metadata": { "authors": [ - "Meno25", - "Test Create account", - "아라", "Diyariq", - "محمد أحمد عبد الفتاح", - "Moud hosny", - "ديفيد", - "Samir", + "DonAdnan", + "Meno25", "Mido", - "DonAdnan" + "Moud hosny", + "Samir", + "Test Create account", + "ديفيد", + "محمد أحمد عبد الفتاح", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "البند", diff --git a/msg/json/az.json b/msg/json/az.json index 6bfec5722..1f73a773b 100644 --- a/msg/json/az.json +++ b/msg/json/az.json @@ -1,10 +1,10 @@ { "@metadata": { "authors": [ - "Cekli829", "AZISS", - "Masalli qasimli", - "Adil" + "Adil", + "Cekli829", + "Masalli qasimli" ] }, "VARIABLES_DEFAULT_NAME": "element", diff --git a/msg/json/ba.json b/msg/json/ba.json index 7a995588c..0aa986eb7 100644 --- a/msg/json/ba.json +++ b/msg/json/ba.json @@ -2,10 +2,10 @@ "@metadata": { "authors": [ "Alfiya55", - "Ләйсән", + "Азат Хәлилов", "Айсар", "Кутлубаева Кунсулу Закиевна", - "Азат Хәлилов", + "Ләйсән", "Танзиля Кутлугильдина" ] }, diff --git a/msg/json/be-tarask.json b/msg/json/be-tarask.json index b90be5b73..589e5a66a 100644 --- a/msg/json/be-tarask.json +++ b/msg/json/be-tarask.json @@ -1,10 +1,10 @@ { "@metadata": { "authors": [ - "Renessaince", "Jim-by", + "Nerogaf", "Red Winged Duck", - "Nerogaf" + "Renessaince" ] }, "VARIABLES_DEFAULT_NAME": "аб’ект", diff --git a/msg/json/bg.json b/msg/json/bg.json index c0da91de2..e9399f724 100644 --- a/msg/json/bg.json +++ b/msg/json/bg.json @@ -1,14 +1,14 @@ { "@metadata": { "authors": [ - "Gkostov", - "Vodnokon4e", "Alpinistbg", - "Miroslav35232", - "StanProg", - "ShockD", + "Gkostov", "InsomniHat", - "Vlad5250" + "Miroslav35232", + "ShockD", + "StanProg", + "Vlad5250", + "Vodnokon4e" ] }, "VARIABLES_DEFAULT_NAME": "елемент", diff --git a/msg/json/bn.json b/msg/json/bn.json index 38618aa59..eaf9aded0 100644 --- a/msg/json/bn.json +++ b/msg/json/bn.json @@ -2,12 +2,12 @@ "@metadata": { "authors": [ "Aftabuzzaman", - "Rakibul", - "Tauhid16", "MasterMinhaz", - "এম আবু সাঈদ", + "Rakibul", "Rasal Lia", - "আফতাবুজ্জামান" + "Tauhid16", + "আফতাবুজ্জামান", + "এম আবু সাঈদ" ] }, "VARIABLES_DEFAULT_NAME": "পদ", diff --git a/msg/json/br.json b/msg/json/br.json index 2d8c07388..e596f2b14 100644 --- a/msg/json/br.json +++ b/msg/json/br.json @@ -2,13 +2,14 @@ "@metadata": { "authors": [ "Fohanno", - "Y-M D", - "Gwenn-Ael", "Fulup", - "Vicng" + "Gwenn-Ael", + "Vicng", + "Y-M D" ] }, "VARIABLES_DEFAULT_NAME": "elfenn", + "UNNAMED_KEY": "dizanv", "TODAY": "Hiziv", "DUPLICATE_BLOCK": "Eiladuriñ", "ADD_COMMENT": "Ouzhpennañ un evezhiadenn", @@ -234,7 +235,7 @@ "TEXT_TRIM_OPERATOR_RIGHT": "Lemel an esaouennoù eus an tu dehou", "TEXT_PRINT_TITLE": "moullañ %1", "TEXT_PRINT_TOOLTIP": "Moullañ an destenn, an niverenn pe un dalvoudenn spisaet all", - "TEXT_PROMPT_TYPE_TEXT": "pedadenn evit un destenn gant ur c'hemennad", + "TEXT_PROMPT_TYPE_TEXT": "goulenn un destenn gant ur gemennadenn", "TEXT_PROMPT_TYPE_NUMBER": "pedadenn evit un niver gant ur c'hemennad", "TEXT_PROMPT_TOOLTIP_NUMBER": "Goulenn un niver gant an implijer.", "TEXT_PROMPT_TOOLTIP_TEXT": "Goulenn un destenn gant an implijer.", @@ -349,5 +350,6 @@ "PROCEDURES_IFRETURN_TOOLTIP": "Ma'z eo gwir un dalvoudenn, distreiñ un eil talvoudenn neuze.", "PROCEDURES_IFRETURN_WARNING": "Diwallit : Gallout a rafe ar bloc'h bezañ implijet e termenadur un arc'hwel hepken.", "WORKSPACE_COMMENT_DEFAULT_TEXT": "Lavaret un dra bennak...", + "WORKSPACE_ARIA_LABEL": "Takad labour Blockly", "COLLAPSED_WARNINGS_WARNING": "Kemennoù-diwall zo er bloc'hadoù pleget." } diff --git a/msg/json/ca.json b/msg/json/ca.json index 2034d5e2f..e5834e6a4 100644 --- a/msg/json/ca.json +++ b/msg/json/ca.json @@ -3,12 +3,12 @@ "authors": [ "Alvaro Vidal-Abarca", "Espertus", + "Fitoschido", "Hiperpobla", "Jaumeortola", - "Fitoschido", - "Quel.soler", + "Lluís Batlle", "Micobu", - "Lluís Batlle" + "Quel.soler" ] }, "VARIABLES_DEFAULT_NAME": "element", diff --git a/msg/json/cs.json b/msg/json/cs.json index a106a537a..f6343561b 100644 --- a/msg/json/cs.json +++ b/msg/json/cs.json @@ -2,17 +2,17 @@ "@metadata": { "authors": [ "Chmee2", - "Rosnicka.kacka", - "Matěj Grabovský", - "Espertus", - "Utar", "Clon", - "Koo6", - "Vtmarvin", - "Dvorapa", "Dita", + "Dvorapa", + "Espertus", "Ilimanaq29", - "Patriccck" + "Koo6", + "Matěj Grabovský", + "Patriccck", + "Rosnicka.kacka", + "Utar", + "Vtmarvin" ] }, "VARIABLES_DEFAULT_NAME": "položka", diff --git a/msg/json/da.json b/msg/json/da.json index 2de937ddc..e4ed7e9c0 100644 --- a/msg/json/da.json +++ b/msg/json/da.json @@ -2,13 +2,13 @@ "@metadata": { "authors": [ "Christian List", - "RickiRunge", + "Joedalton", + "JonNPoulsen", "MGA73", "Mads Haupt", - "Tjernobyl", - "Joedalton", + "RickiRunge", "Saederup92", - "JonNPoulsen" + "Tjernobyl" ] }, "VARIABLES_DEFAULT_NAME": "element", diff --git a/msg/json/de.json b/msg/json/de.json index cfe5f95a6..968fa40eb 100644 --- a/msg/json/de.json +++ b/msg/json/de.json @@ -1,16 +1,16 @@ { "@metadata": { "authors": [ - "Metalhead64", - "M165437", - "Dan-yell", - "아라", - "Octycs", "Cvanca", - "THINK", - "Zgtm", + "Dan-yell", + "M165437", + "Metalhead64", + "Octycs", "Sushi", - "Tiin" + "THINK", + "Tiin", + "Zgtm", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "Element", diff --git a/msg/json/diq.json b/msg/json/diq.json index 6835ae357..480c845b7 100644 --- a/msg/json/diq.json +++ b/msg/json/diq.json @@ -1,12 +1,12 @@ { "@metadata": { "authors": [ + "1917 Ekim Devrimi", + "Gırd", "Kumkumuk", "Marmase", "Mirzali", - "Gırd", - "Orbot707", - "1917 Ekim Devrimi" + "Orbot707" ] }, "VARIABLES_DEFAULT_NAME": "unsur", diff --git a/msg/json/el.json b/msg/json/el.json index bc3ac1fcc..c657727fa 100644 --- a/msg/json/el.json +++ b/msg/json/el.json @@ -4,20 +4,20 @@ "Azountas", "Espertus", "Evropi", - "Namatreasure", - "Sfyrakis", - "Glavkos", - "Gchr", - "아라", - "Geraki", - "Ανώνυμος Βικιπαιδιστής", "GR", + "Gchr", + "Geraki", + "Glavkos", + "KATRINE1992", + "Namatreasure", + "Nikosgranturismogt", + "Sarri.greek", + "Sfyrakis", "Stam.nikos", "Themelis", - "KATRINE1992", "Vicng", - "Nikosgranturismogt", - "Sarri.greek" + "Ανώνυμος Βικιπαιδιστής", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "αντικείμενο", diff --git a/msg/json/en-gb.json b/msg/json/en-gb.json index 42ca12b1e..1264bf71a 100644 --- a/msg/json/en-gb.json +++ b/msg/json/en-gb.json @@ -1,10 +1,10 @@ { "@metadata": { "authors": [ + "Aefgh39622", "Andibing", "Codynguyen1116", - "Shirayuki", - "Aefgh39622" + "Shirayuki" ] }, "VARIABLES_DEFAULT_NAME": "item", diff --git a/msg/json/eo.json b/msg/json/eo.json index 88565b02d..dab0ddcfe 100644 --- a/msg/json/eo.json +++ b/msg/json/eo.json @@ -1,12 +1,12 @@ { "@metadata": { "authors": [ + "Cérilew", "Etrapani", + "Mirin", "Ochilov", "Orikrin1998", "Robin van der Vliet", - "Cérilew", - "Mirin", "Surfo" ] }, diff --git a/msg/json/es.json b/msg/json/es.json index 4e0840d17..ca3e1d680 100644 --- a/msg/json/es.json +++ b/msg/json/es.json @@ -1,20 +1,20 @@ { "@metadata": { "authors": [ - "Fitoschido", - "VegaDark", - "WeSiToS", - "Macofe", "Codynguyen1116", - "Indiralena", - "Rubentl134", - "Martineduardo", - "Julián L", - "Luisangelrg", - "MarcoAurelio", - "Ryo567", + "Fitoschido", "Harvest", - "Ktranz" + "Indiralena", + "Julián L", + "Ktranz", + "Luisangelrg", + "Macofe", + "MarcoAurelio", + "Martineduardo", + "Rubentl134", + "Ryo567", + "VegaDark", + "WeSiToS" ] }, "VARIABLES_DEFAULT_NAME": "elemento", diff --git a/msg/json/et.json b/msg/json/et.json index a2f11bce8..ee759fbe1 100644 --- a/msg/json/et.json +++ b/msg/json/et.json @@ -3,9 +3,9 @@ "authors": [ "Aivarannamaa", "Hasso", - "Puik", "Ilmarine", - "Masavi" + "Masavi", + "Puik" ] }, "VARIABLES_DEFAULT_NAME": "objekt", diff --git a/msg/json/eu.json b/msg/json/eu.json index 6b679be54..03170a3aa 100644 --- a/msg/json/eu.json +++ b/msg/json/eu.json @@ -1,14 +1,14 @@ { "@metadata": { "authors": [ + "Abacus", + "Amaia", "An13sa", "Asieriko", - "Mikel Ibaiba", - "Subi", - "RFenichel", - "Amaia", "EukeneFL", - "Abacus" + "Mikel Ibaiba", + "RFenichel", + "Subi" ] }, "VARIABLES_DEFAULT_NAME": "elementua", diff --git a/msg/json/fa.json b/msg/json/fa.json index 56c6cc1a2..c42334450 100644 --- a/msg/json/fa.json +++ b/msg/json/fa.json @@ -1,16 +1,16 @@ { "@metadata": { "authors": [ - "Ebraminio", - "Reza1615", "Alirezaaa", + "Arash.pt", + "Dalba", + "Ebraminio", + "Hamisun", + "Hossein.safavi", "Mehran", "MohandesWiki", - "Dalba", - "Hamisun", "Nhzandi", - "Arash.pt", - "Hossein.safavi" + "Reza1615" ] }, "VARIABLES_DEFAULT_NAME": "مورد", diff --git a/msg/json/fi.json b/msg/json/fi.json index a05b7141c..1064ddba2 100644 --- a/msg/json/fi.json +++ b/msg/json/fi.json @@ -1,19 +1,19 @@ { "@metadata": { "authors": [ - "Nike", - "Silvonen", - "Espertus", - "Pettevi", - "McSalama", "Espeox", - "SNuutti", - "PStudios", - "Mikahama", - "Pyscowicz", - "Pahkiqaz", + "Espertus", "Hopea", - "KK" + "KK", + "McSalama", + "Mikahama", + "Nike", + "PStudios", + "Pahkiqaz", + "Pettevi", + "Pyscowicz", + "SNuutti", + "Silvonen" ] }, "VARIABLES_DEFAULT_NAME": "kohde", diff --git a/msg/json/fr.json b/msg/json/fr.json index 79f176388..6d9e85aed 100644 --- a/msg/json/fr.json +++ b/msg/json/fr.json @@ -1,23 +1,23 @@ { "@metadata": { "authors": [ - "Espertus", - "Gomoko", - "ProfGra", - "Wladek92", - "Fredlefred", - "Grimault", - "Rixed", - "Frigory", - "Appr", - "Vexthedorito", - "Urhixidur", - "RoboErikG", - "Zarisi", "Alacabe", + "Appr", + "Espertus", + "Fredlefred", + "Frigory", + "Gomoko", + "Grimault", "Pititnatole", + "ProfGra", + "Rixed", + "RoboErikG", + "Thibaut120094", + "Urhixidur", "Verdy p", - "Thibaut120094" + "Vexthedorito", + "Wladek92", + "Zarisi" ] }, "VARIABLES_DEFAULT_NAME": "élément", diff --git a/msg/json/gl.json b/msg/json/gl.json index 7fc26ddfe..173ca265c 100644 --- a/msg/json/gl.json +++ b/msg/json/gl.json @@ -3,10 +3,9 @@ "authors": [ "Chairego apc", "Elisardojm", + "Iváns", "Macofe", - "Navhy", - "Toliño", - "Iváns" + "Toliño" ] }, "VARIABLES_DEFAULT_NAME": "elemento", diff --git a/msg/json/he.json b/msg/json/he.json index a6d9cad1d..5be2f3a00 100644 --- a/msg/json/he.json +++ b/msg/json/he.json @@ -1,25 +1,26 @@ { "@metadata": { "authors": [ - "Dorongol", - "YaronSh", "Amire80", - "Inkbug", - "Yona b", - "Noamrotem", + "Deborahjay", + "Dorongol", "Dvb", - "LaG roiL", - "아라", "Elyashiv", "Guycn2", - "Deborahjay", - "נדב ס", + "Inkbug", + "LaG roiL", "Motife", + "Noamrotem", "Steeve815", - "דגש חזק" + "YaronSh", + "Yona b", + "דגש חזק", + "נדב ס", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "פריט", + "UNNAMED_KEY": "ללא שם", "TODAY": "היום", "DUPLICATE_BLOCK": "שכפל", "ADD_COMMENT": "הוסף תגובה", @@ -97,7 +98,9 @@ "IOS_OK": "אישור", "IOS_CANCEL": "ביטול", "IOS_ERROR": "שגיאה", + "IOS_PROCEDURES_INPUTS": "קלטים", "IOS_PROCEDURES_ADD_INPUT": "+ הוספת קלט", + "IOS_PROCEDURES_DUPLICATE_INPUTS_ERROR": "לפונקציה יש קלטים כפולים.", "IOS_VARIABLES_ADD_VARIABLE": "+ הוספת משתנה", "IOS_VARIABLES_ADD_BUTTON": "הוספה", "IOS_VARIABLES_RENAME_BUTTON": "שינוי שם", @@ -158,6 +161,9 @@ "MATH_TRIG_TOOLTIP_SIN": "החזרת הסינוס של מעלה (לא רדיאן).", "MATH_TRIG_TOOLTIP_COS": "החזרת הקוסינוס של מעלה (לא רדיאן).", "MATH_TRIG_TOOLTIP_TAN": "החזרת הטנגס של מעלה (לא רדיאן).", + "MATH_TRIG_TOOLTIP_ASIN": "החזרת הארק-סינוס של מספר.", + "MATH_TRIG_TOOLTIP_ACOS": "החזרת הארק-קוסינוס של מספר.", + "MATH_TRIG_TOOLTIP_ATAN": "החזרת הארק-טנגנס של מספר.", "MATH_CONSTANT_HELPURL": "https://he.wikipedia.org/wiki/קבוע_מתמטי", "MATH_CONSTANT_TOOLTIP": "החזרת אחד מהקבועים המקובלים: π (3.141…),‏ e (2.718…),‏ φ (1.618…),‏ sqrt(2) (1.414…),‏ sqrt(½) (0.707…)‏ או ∞ (אינסוף).", "MATH_IS_EVEN": "זוגי", @@ -167,6 +173,7 @@ "MATH_IS_POSITIVE": "חיובי", "MATH_IS_NEGATIVE": "שלילי", "MATH_IS_DIVISIBLE_BY": "מתחלק ב", + "MATH_IS_TOOLTIP": "בדיקה האם מספר הוא זוגי, אי־זוגי, ראשוני, שלם, חיובי, שלילי או אם ניתן לחלק אותו במספר כלשהו. מחזירה אמת או שקר.", "MATH_CHANGE_TITLE": "שינוי %1 על־ידי %2", "MATH_CHANGE_TOOLTIP": "הוסף מספר למשתנה '%1'.", "MATH_ROUND_HELPURL": "https://he.wikipedia.org/wiki/עיגול_(אריתמטיקה)", @@ -185,6 +192,7 @@ "MATH_ONLIST_TOOLTIP_MEDIAN": "תחזיר את המספר החיצוני ביותר ברשימה.", "MATH_ONLIST_OPERATOR_MODE": "שכיחי הרשימה", "MATH_ONLIST_TOOLTIP_MODE": "החזרת רשימה של הפריטים הנפוצים ביותר ברשימה", + "MATH_ONLIST_OPERATOR_STD_DEV": "סטיית תקן של רשימה", "MATH_ONLIST_TOOLTIP_STD_DEV": "מחזיר את סטיית התקן של הרשימה.", "MATH_ONLIST_OPERATOR_RANDOM": "פריט אקראי מרשימה", "MATH_ONLIST_TOOLTIP_RANDOM": "תחזיר רכיב אקראי מרשימה.", @@ -197,18 +205,33 @@ "TEXT_TEXT_TOOLTIP": "אות, מילה, או שורת טקסט.", "TEXT_JOIN_TITLE_CREATEWITH": "יצירת טקסט עם", "TEXT_CREATE_JOIN_TITLE_JOIN": "צירוף", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "הוספת פריט לטקסט.", "TEXT_APPEND_TITLE": "אל %1 הוספת טקסט %2", + "TEXT_APPEND_TOOLTIP": "הוספת טקסט למשתנה ‚%1’.", "TEXT_LENGTH_TITLE": "אורכו של %1", "TEXT_LENGTH_TOOLTIP": "מחזיר את מספר התווים (אותיות, רווחים וכו') בטקסט שהוזן.", "TEXT_ISEMPTY_TITLE": "%1 הוא ריק", + "TEXT_ISEMPTY_TOOLTIP": "מחזירה אמת אם הטקסט שצוין ריק.", "TEXT_INDEXOF_TOOLTIP": "מחזירה את האינדקס של המופע הראשון/האחרון בטקסט הראשון לתוך הטקסט השני. מחזירה %1 אם הטקסט אינו נמצא.", + "TEXT_INDEXOF_TITLE": "בטקסט %1 %2 %3", + "TEXT_INDEXOF_OPERATOR_FIRST": "איתור המופע הראשון של טקסט", + "TEXT_INDEXOF_OPERATOR_LAST": "איתור המופע האחרון של טקסט", + "TEXT_CHARAT_TITLE": "בטקסט %1 %2", + "TEXT_CHARAT_FROM_START": "קבלת אות מס׳", + "TEXT_CHARAT_FROM_END": "קבלת אות מס׳ מהסוף", "TEXT_CHARAT_FIRST": "לקבל את האות הראשונה", "TEXT_CHARAT_LAST": "לקבל את האות האחרונה", "TEXT_CHARAT_RANDOM": "לקבל אות אקראית", "TEXT_CHARAT_TOOLTIP": "מחזיר את האות במיקום שהוגדר.", + "TEXT_GET_SUBSTRING_TOOLTIP": "החזרת קטע מסוים מהטקסט.", "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "בתוך הטקסט", + "TEXT_GET_SUBSTRING_START_FROM_START": "קבלת תת־מחרוזת מאות מס׳", + "TEXT_GET_SUBSTRING_START_FROM_END": "קבלת מחרוזת מאות מס׳ מהסוף", + "TEXT_GET_SUBSTRING_START_FIRST": "קבלת תת־מחרוזת מהאות הראשונה", "TEXT_GET_SUBSTRING_END_FROM_START": "לאות #", "TEXT_GET_SUBSTRING_END_FROM_END": "לאות # מהסוף", + "TEXT_GET_SUBSTRING_END_LAST": "עד האות האחרונה", + "TEXT_CHANGECASE_TOOLTIP": "החזרת עותק של הטקסט בשינוי רישיות.", "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "לאותיות גדולות (עבור טקסט באנגלית)", "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "לאותיות קטנות (עבור טקסט באנגלית)", "TEXT_CHANGECASE_OPERATOR_TITLECASE": "לאותיות גדולות בתחילת כל מילה (עבור טקסט באנגלית)", diff --git a/msg/json/hi.json b/msg/json/hi.json index ddd1fecd8..0262f5215 100644 --- a/msg/json/hi.json +++ b/msg/json/hi.json @@ -2,12 +2,12 @@ "@metadata": { "authors": [ "Bl707", - "संजीव कुमार", - "Phoenix303", - "Sfic", "Earlyengineers", + "Nilesh shukla", + "Phoenix303", "Sachinkatiyar", - "Nilesh shukla" + "Sfic", + "संजीव कुमार" ] }, "VARIABLES_DEFAULT_NAME": "वस्तु", diff --git a/msg/json/hu.json b/msg/json/hu.json index 0338772bb..51985cd9d 100644 --- a/msg/json/hu.json +++ b/msg/json/hu.json @@ -1,21 +1,21 @@ { "@metadata": { "authors": [ - "Espertus", - "Takács Viktor László", - "Dj", - "Grin", - "ViDam", - "Csega", - "Fitoschido", - "Lajthabalazs", - "Tacsipacsi", - "Rodrigo", - "Máté", "BanKris", + "Csega", + "Dj", + "Espertus", + "Fitoschido", + "Grin", + "Lajthabalazs", + "MeskoBalazs", + "Máté", "Notramo", + "Rodrigo", + "Tacsipacsi", + "Takács Viktor László", "Urbalazs", - "MeskoBalazs" + "ViDam" ] }, "VARIABLES_DEFAULT_NAME": "változó", diff --git a/msg/json/hy.json b/msg/json/hy.json index e0781239b..781034971 100644 --- a/msg/json/hy.json +++ b/msg/json/hy.json @@ -9,6 +9,7 @@ ] }, "VARIABLES_DEFAULT_NAME": "տարր", + "UNNAMED_KEY": "անանուն", "TODAY": "Այսօր", "DUPLICATE_BLOCK": "Պատճենել", "ADD_COMMENT": "Ավելացնել մեկնաբանություն", diff --git a/msg/json/ia.json b/msg/json/ia.json index 6fec39b21..7ce4b8c43 100644 --- a/msg/json/ia.json +++ b/msg/json/ia.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ - "McDutchie", + "Fanjiayi", "Karmwiki", - "Fanjiayi" + "McDutchie" ] }, "VARIABLES_DEFAULT_NAME": "cosa", diff --git a/msg/json/id.json b/msg/json/id.json index 87e28d8f2..66fbb1d75 100644 --- a/msg/json/id.json +++ b/msg/json/id.json @@ -1,12 +1,12 @@ { "@metadata": { "authors": [ - "Kenrick95", - "아라", - "Mirws", - "Marwan Mohamad", + "Arifin.wijaya", "Kasimtan", - "Arifin.wijaya" + "Kenrick95", + "Marwan Mohamad", + "Mirws", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "item", diff --git a/msg/json/is.json b/msg/json/is.json index cbcd2adf1..57eab208d 100644 --- a/msg/json/is.json +++ b/msg/json/is.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ - "Jonbg", - "아라", "Gaddi00", + "Jonbg", "Sveinki", - "Sveinn í Felli" + "Sveinn í Felli", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "atriði", diff --git a/msg/json/it.json b/msg/json/it.json index 842b23708..eb1ae3af4 100644 --- a/msg/json/it.json +++ b/msg/json/it.json @@ -1,19 +1,19 @@ { "@metadata": { "authors": [ + "Albe Albe 460", + "Albe Albe460", "Beta16", "Espertus", - "Nerimic", + "Federico Mugnaini", "Gbonanome", "Gianfranco", - "Federico Mugnaini", - "JackLantern", - "Selven", - "Samuele2002", "Greis", + "JackLantern", + "Nerimic", + "Samuele2002", "Sarah Bernabei", - "Albe Albe 460", - "Albe Albe460" + "Selven" ] }, "VARIABLES_DEFAULT_NAME": "elemento", diff --git a/msg/json/ja.json b/msg/json/ja.json index 0e3b809a6..f5d8f1128 100644 --- a/msg/json/ja.json +++ b/msg/json/ja.json @@ -1,19 +1,19 @@ { "@metadata": { "authors": [ - "Shirayuki", - "Oda", - "아라", - "Otokoume", - "Sujiniku", - "Sgk", - "TAKAHASHI Shuuji", - "Suiato", - "ネイ", "Aefgh39622", - "Omotecho", "Gimite", - "Gulpin" + "Gulpin", + "Oda", + "Omotecho", + "Otokoume", + "Sgk", + "Shirayuki", + "Suiato", + "Sujiniku", + "TAKAHASHI Shuuji", + "ネイ", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "項目", diff --git a/msg/json/kab.json b/msg/json/kab.json index ce5ccf9b4..fe6bc150c 100644 --- a/msg/json/kab.json +++ b/msg/json/kab.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ + "Alem", "Amaziɣ maziɣ", "Belkacem77", - "Alem", - "YubaWissin", - "SlimaneAmiri" + "SlimaneAmiri", + "YubaWissin" ] }, "VARIABLES_DEFAULT_NAME": "aferdis", diff --git a/msg/json/kn.json b/msg/json/kn.json index f1b46a905..3cc820c95 100644 --- a/msg/json/kn.json +++ b/msg/json/kn.json @@ -2,10 +2,10 @@ "@metadata": { "authors": [ "Ananth subray", + "Anoop rao", "Nayvik", "Niekiran", - "VASANTH S.N.", - "Anoop rao" + "VASANTH S.N." ] }, "VARIABLES_DEFAULT_NAME": "ವಸ್ತು", diff --git a/msg/json/ko.json b/msg/json/ko.json index b71be48d4..584ce3493 100644 --- a/msg/json/ko.json +++ b/msg/json/ko.json @@ -1,21 +1,21 @@ { "@metadata": { "authors": [ + "Alex00728", + "Gongsoonyee", "Hym411", - "아라", + "JeonHK", + "Jerrykim306", + "Kurousagi", + "Lemondoge", + "Liuxinyu970226", + "Onebone", + "Peurocs4", "Priviet", "Revi", "SeoJeongHo", - "Alex00728", - "Kurousagi", - "Lemondoge", "Ykhwong", - "Jerrykim306", - "Onebone", - "JeonHK", - "Liuxinyu970226", - "Peurocs4", - "Gongsoonyee" + "아라" ] }, "VARIABLES_DEFAULT_NAME": "항목", diff --git a/msg/json/lb.json b/msg/json/lb.json index ff12392f7..745d5dafe 100644 --- a/msg/json/lb.json +++ b/msg/json/lb.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ + "Les Meloures", "Robby", - "Soued031", - "Les Meloures" + "Soued031" ] }, "VARIABLES_DEFAULT_NAME": "Element", diff --git a/msg/json/lrc.json b/msg/json/lrc.json index a3b07e259..ff4f0be75 100644 --- a/msg/json/lrc.json +++ b/msg/json/lrc.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "Mogoeilor", - "Lorestani" + "Lorestani", + "Mogoeilor" ] }, "VARIABLES_DEFAULT_NAME": "قلٱم", diff --git a/msg/json/lt.json b/msg/json/lt.json index 649f51618..c47752777 100644 --- a/msg/json/lt.json +++ b/msg/json/lt.json @@ -3,8 +3,8 @@ "authors": [ "Eitvys200", "Jurgis", - "Zygimantus", - "Nuodas" + "Nuodas", + "Zygimantus" ] }, "VARIABLES_DEFAULT_NAME": "elementas", diff --git a/msg/json/lv.json b/msg/json/lv.json index e3ed010a9..c206623aa 100644 --- a/msg/json/lv.json +++ b/msg/json/lv.json @@ -4,8 +4,8 @@ "Elomage", "Janis", "Papuass", - "Silraks", - "RFenichel" + "RFenichel", + "Silraks" ] }, "VARIABLES_DEFAULT_NAME": "vienums", diff --git a/msg/json/nb.json b/msg/json/nb.json index ca5f3052a..d62ec0dd6 100644 --- a/msg/json/nb.json +++ b/msg/json/nb.json @@ -2,10 +2,10 @@ "@metadata": { "authors": [ "Cocu", + "Jon Harald Søby", "Kingu", - "아라", "SuperPotato", - "Jon Harald Søby" + "아라" ] }, "VARIABLES_DEFAULT_NAME": "element", diff --git a/msg/json/nl.json b/msg/json/nl.json index f60798e0f..d5ca300de 100644 --- a/msg/json/nl.json +++ b/msg/json/nl.json @@ -1,22 +1,22 @@ { "@metadata": { "authors": [ - "Siebrand", - "McDutchie", - "Ribert", - "MedShot", - "아라", - "JaapDeKleine", - "Sjoerddebruin", - "Lemondoge", - "Jeleniccz", + "Elroy", "Festina90", + "JaapDeKleine", + "Jeleniccz", + "Klaas van Buiten", + "KlaasZ4usV", + "Lemondoge", + "Marcelhospers", + "McDutchie", + "MedShot", "Optilete", "Patio", - "KlaasZ4usV", - "Marcelhospers", - "Elroy", - "Klaas van Buiten" + "Ribert", + "Siebrand", + "Sjoerddebruin", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "item", diff --git a/msg/json/pl.json b/msg/json/pl.json index 34d93bb82..4e7e65a30 100644 --- a/msg/json/pl.json +++ b/msg/json/pl.json @@ -1,27 +1,27 @@ { "@metadata": { "authors": [ + "Chrumps", + "Cirasean", "Cotidianis", + "Expert3222", "Faren", - "Vengir", + "Fringoo", + "InternerowyGołąb", + "Krottyianock", + "Krzyz23", + "Liuxinyu970226", + "Mateon1", + "Mazab IZW", "Pbz", "Pio387", - "아라", - "Mateon1", - "Expert3222", - "Cirasean", - "Fringoo", - "Chrumps", - "Woytecr", - "Liuxinyu970226", - "Krottyianock", - "Mazab IZW", - "Teeed", - "InternerowyGołąb", - "Wojtas", - "Stojex", "Rail", - "Krzyz23" + "Stojex", + "Teeed", + "Vengir", + "Wojtas", + "Woytecr", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "element", diff --git a/msg/json/pt-br.json b/msg/json/pt-br.json index 4dc2615be..3da9fa721 100644 --- a/msg/json/pt-br.json +++ b/msg/json/pt-br.json @@ -1,29 +1,29 @@ { "@metadata": { "authors": [ - "Espertus", - "Prilopes", - "Mordecaista", - "Amgauna", - "TheGabrielZaum", - "Cainamarques", - "Tuliouel", - "Rodrigo codignoli", - "Webysther", - "Fasouzafreitas", "Almondega", - "Rogerio Melfi", + "Amgauna", + "BarbaraAckles", + "Cainamarques", "Caçador de Palavras", - "Luk3", "Cristofer Alves", "EVinente", - "Lowvy", - "Trigonometria87", - "BarbaraAckles", - "Mauricio", - "Felipe L. Ewald", "Eduardo Addad de Oliveira", + "Espertus", + "Fasouzafreitas", + "Felipe L. Ewald", + "Lowvy", + "Luk3", + "Mauricio", "McDutchie", + "Mordecaista", + "Prilopes", + "Rodrigo codignoli", + "Rogerio Melfi", + "TheGabrielZaum", + "Trigonometria87", + "Tuliouel", + "Webysther", "WikiUser22222" ] }, diff --git a/msg/json/pt.json b/msg/json/pt.json index 8fc659fc5..91db92891 100644 --- a/msg/json/pt.json +++ b/msg/json/pt.json @@ -1,23 +1,23 @@ { "@metadata": { "authors": [ - "Imperadeiro98", - "Waldir", - "Vitorvicentevalente", - "아라", - "Nicola Nascimento", - "Önni", + "Athena in Wonderland", "Diniscoelho", "Fúlvio", - "Mansil", - "Mauricio", - "Vicng", - "MokaAkashiyaPT", - "Athena in Wonderland", - "McDutchie", "Hamilton Abreu", + "Imperadeiro98", + "Mansil", + "Mansil alfalb", + "Mauricio", + "McDutchie", + "MokaAkashiyaPT", + "Nicola Nascimento", + "Vicng", + "Vitorvicentevalente", + "Waldir", "Waldyrious", - "Mansil alfalb" + "Önni", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "item", diff --git a/msg/json/qqq.json b/msg/json/qqq.json index f2b7d1723..596ea55ad 100644 --- a/msg/json/qqq.json +++ b/msg/json/qqq.json @@ -1,4 +1,13 @@ { + "@metadata": { + "authors": [ + "Espertus", + "Liuxinyu970226", + "Metalhead64", + "Robby", + "Shirayuki" + ] + }, "VARIABLES_DEFAULT_NAME": "default name - A simple, general default name for a variable, preferably short. For more context, see [[Translating:Blockly#infrequent_message_types]].\n{{Identical|Item}}", "UNNAMED_KEY": "default name - A simple, default name for an unnamed function or variable. Preferably indicates that the item is unnamed.", "TODAY": "button text - Button that sets a calendar to today's date.\n{{Identical|Today}}", diff --git a/msg/json/ro.json b/msg/json/ro.json index df3ead9ad..4c73585ab 100644 --- a/msg/json/ro.json +++ b/msg/json/ro.json @@ -1,13 +1,13 @@ { "@metadata": { "authors": [ - "Minisarm", "Ely en", "Hugbear", - "아라", - "Ykhwong", + "MSClaudiu", + "Minisarm", "Wintereu", - "MSClaudiu" + "Ykhwong", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "element", diff --git a/msg/json/ru.json b/msg/json/ru.json index ef98c709a..05863ae80 100644 --- a/msg/json/ru.json +++ b/msg/json/ru.json @@ -2,17 +2,17 @@ "@metadata": { "authors": [ "Espertus", - "MS", - "Okras", - "RedFox", - "Mailman", - "Silovan", - "Redredsonia", "Facenapalm", "Helpau", - "SimondR", + "MS", + "Mailman", "Mouse21", "Movses", + "Okras", + "RedFox", + "Redredsonia", + "Silovan", + "SimondR", "Vlad5250" ] }, diff --git a/msg/json/sc.json b/msg/json/sc.json index 282d52980..903516a2e 100644 --- a/msg/json/sc.json +++ b/msg/json/sc.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ - "Via maxima", "Taxandru", - "Uharteko" + "Uharteko", + "Via maxima" ] }, "VARIABLES_DEFAULT_NAME": "item", diff --git a/msg/json/sd.json b/msg/json/sd.json index 1ea423588..666d47032 100644 --- a/msg/json/sd.json +++ b/msg/json/sd.json @@ -2,8 +2,8 @@ "@metadata": { "authors": [ "Aursani", - "Mehtab ahmed", "Indus Asia", + "Mehtab ahmed", "Tweety" ] }, diff --git a/msg/json/shn.json b/msg/json/shn.json index 6c211e4a4..fcea65b88 100644 --- a/msg/json/shn.json +++ b/msg/json/shn.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "Saosukham", - "Saimawnkham" + "Saimawnkham", + "Saosukham" ] }, "VARIABLES_DEFAULT_NAME": "ဢၼ်", diff --git a/msg/json/sk.json b/msg/json/sk.json index 3d1f8b46e..9fedf5150 100644 --- a/msg/json/sk.json +++ b/msg/json/sk.json @@ -1,16 +1,16 @@ { "@metadata": { "authors": [ + "Adams", + "Genhis", "Jaroslav.micek", + "Kusavica", + "Lexected", "Marian.stano", "Mark", - "Kusavica", - "Genhis", - "Lexected", - "Adams", - "TomášPolonec", + "Nykta 1917", "Pmikolas44", - "Nykta 1917" + "TomášPolonec" ] }, "VARIABLES_DEFAULT_NAME": "prvok", diff --git a/msg/json/sl.json b/msg/json/sl.json index 07c990a65..ace2432d2 100644 --- a/msg/json/sl.json +++ b/msg/json/sl.json @@ -2,12 +2,12 @@ "@metadata": { "authors": [ "Anzeljg", - "Miloš Košir", "Dbc334", "HairyFotr", "Igor.pesek", + "LoveMortuus", "MaxiMouse", - "LoveMortuus" + "Miloš Košir" ] }, "VARIABLES_DEFAULT_NAME": "element", diff --git a/msg/json/sq.json b/msg/json/sq.json index 187f8e4d2..bdd033496 100644 --- a/msg/json/sq.json +++ b/msg/json/sq.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ - "아라", + "Arianit", "Liridon", - "Arianit" + "아라" ] }, "VARIABLES_DEFAULT_NAME": "send", diff --git a/msg/json/sr.json b/msg/json/sr.json index a9df4644a..f4ba7fe0b 100644 --- a/msg/json/sr.json +++ b/msg/json/sr.json @@ -1,15 +1,15 @@ { "@metadata": { "authors": [ - "Rancher", - "아라", - "Perevod16", - "Nikola Smolenski", - "Obsuser", "Acamicamacaraca", "BadDog", + "Nikola Smolenski", + "Obsuser", + "Perevod16", + "Rancher", + "Zoranzoki21", "Милан Јелисавчић", - "Zoranzoki21" + "아라" ] }, "VARIABLES_DEFAULT_NAME": "ставка", diff --git a/msg/json/sv.json b/msg/json/sv.json index 65aa0a9b0..427afc297 100644 --- a/msg/json/sv.json +++ b/msg/json/sv.json @@ -1,13 +1,13 @@ { "@metadata": { "authors": [ - "Jopparn", - "WikiPhoenix", - "Abbedabb", "Aaoo", - "아라", + "Abbedabb", "Eldaria", - "Smuda" + "Jopparn", + "Smuda", + "WikiPhoenix", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "föremål", diff --git a/msg/json/ta.json b/msg/json/ta.json index 73d636d11..0efbfaad3 100644 --- a/msg/json/ta.json +++ b/msg/json/ta.json @@ -4,8 +4,8 @@ "ElangoRamanujam", "Ezhillang", "Karuthan", - "Thangamani-arun", - "Mahir78" + "Mahir78", + "Thangamani-arun" ] }, "VARIABLES_DEFAULT_NAME": "உருப்படி", diff --git a/msg/json/tcy.json b/msg/json/tcy.json index fa1883ed1..17b2442ac 100644 --- a/msg/json/tcy.json +++ b/msg/json/tcy.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ - "Vishwanatha Badikana", + "BHARATHESHA ALASANDEMAJALU", "Bharathesha Alasandemajalu", "Kiranpoojary", - "BHARATHESHA ALASANDEMAJALU", - "Ravi Mundkur" + "Ravi Mundkur", + "Vishwanatha Badikana" ] }, "VARIABLES_DEFAULT_NAME": "ವಸ್ತು", diff --git a/msg/json/te.json b/msg/json/te.json index cfd50cc3c..9ee0c1876 100644 --- a/msg/json/te.json +++ b/msg/json/te.json @@ -2,8 +2,8 @@ "@metadata": { "authors": [ "Naidugari Jayanna", - "WP MANIKHANTA", - "Veeven" + "Veeven", + "WP MANIKHANTA" ] }, "VARIABLES_DEFAULT_NAME": "అంశం", diff --git a/msg/json/th.json b/msg/json/th.json index 51cdbdfdc..50b3dd8b5 100644 --- a/msg/json/th.json +++ b/msg/json/th.json @@ -1,14 +1,14 @@ { "@metadata": { "authors": [ - "Azpirin", - "Octahedron80", - "Horus", - "Roysheng", "Aefgh39622", + "Azpirin", + "Horus", + "Karit", "Nantapat", - "Trisorn Triboon", - "Karit" + "Octahedron80", + "Roysheng", + "Trisorn Triboon" ] }, "VARIABLES_DEFAULT_NAME": "รายการ", diff --git a/msg/json/tr.json b/msg/json/tr.json index a8a4441cd..c21f14eb8 100644 --- a/msg/json/tr.json +++ b/msg/json/tr.json @@ -1,25 +1,25 @@ { "@metadata": { "authors": [ - "Meelo", - "Joseph", - "WikiBronze", - "Mavrikant", - "아라", - "Watermelon juice", - "Uğurkent", - "McAang", - "Gurkanht", - "HakanIST", - "Imabadplayer", - "Kumkumuk", "Alpkant", + "Azerhan Özen", + "BaRaN6161 TURK", "Bulgu", "By erdo can", - "Azerhan Özen", + "Grkn gll", + "Gurkanht", + "HakanIST", "Hedda", - "BaRaN6161 TURK", - "Grkn gll" + "Imabadplayer", + "Joseph", + "Kumkumuk", + "Mavrikant", + "McAang", + "Meelo", + "Uğurkent", + "Watermelon juice", + "WikiBronze", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "öge", diff --git a/msg/json/uk.json b/msg/json/uk.json index 9b2e02d0f..9e81b2c27 100644 --- a/msg/json/uk.json +++ b/msg/json/uk.json @@ -3,14 +3,14 @@ "authors": [ "Andriykopanytsia", "Base", + "Gzhegozh", "Igor Zavadsky", "Lxlalexlxl", - "아라", - "Visem", + "Movses", "Piramidion", "SimondR", - "Movses", - "Gzhegozh" + "Visem", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "елемент", diff --git a/msg/json/ur.json b/msg/json/ur.json index e39e9a4d5..1d918f2ff 100644 --- a/msg/json/ur.json +++ b/msg/json/ur.json @@ -2,11 +2,11 @@ "@metadata": { "authors": [ "Abdulq", + "NajeebKhan", "Obaid Raza", - "عثمان خان شاہ", - "محمد افضل", "Sayam Asjad", - "NajeebKhan" + "عثمان خان شاہ", + "محمد افضل" ] }, "VARIABLES_DEFAULT_NAME": "آئٹم", diff --git a/msg/json/vi.json b/msg/json/vi.json index e6d00c3ed..9d6996a25 100644 --- a/msg/json/vi.json +++ b/msg/json/vi.json @@ -2,13 +2,13 @@ "@metadata": { "authors": [ "Baonguyen21022003", - "Espertus", - "Qneutron", - "Withoutaname", "Dstream", - "Nguyenvanduocit", + "Espertus", "Leducthn", - "SierraNguyen" + "Nguyenvanduocit", + "Qneutron", + "SierraNguyen", + "Withoutaname" ] }, "VARIABLES_DEFAULT_NAME": "vật", diff --git a/msg/json/zh-hans.json b/msg/json/zh-hans.json index c3b11cce7..e807a21b6 100644 --- a/msg/json/zh-hans.json +++ b/msg/json/zh-hans.json @@ -1,25 +1,25 @@ { "@metadata": { "authors": [ + "A Chinese Wikipedian", + "Ambeta", + "Deathkon", + "Duzc2", "Espertus", + "Htq110219891", + "Hudafu", "Liuxinyu970226", "Luotiancheng", + "Muhaoying", "Qiyue2001", - "Xiaomingyan", - "Yfdyh000", - "아라", - "Hudafu", "Shatteredwind", - "Duzc2", "Tonylianlong", "WindWood", - "Deathkon", - "Muhaoying", + "Xiaomingyan", + "Yfdyh000", "佛壁灯", - "Htq110219891", - "Ambeta", - "A Chinese Wikipedian", - "沈澄心" + "沈澄心", + "아라" ] }, "VARIABLES_DEFAULT_NAME": "项目", diff --git a/msg/json/zh-hant.json b/msg/json/zh-hant.json index 2a010d60d..b0e8bc2f0 100644 --- a/msg/json/zh-hant.json +++ b/msg/json/zh-hant.json @@ -1,17 +1,17 @@ { "@metadata": { "authors": [ - "Gasolin", - "Wehwei", - "Liuxinyu970226", - "LNDDYL", "Cwlin0416", + "Dnow", + "Dnowba", + "Gasolin", + "Jessica1213", "Kasimtan", "Kly", - "Dnowba", - "Dnow", + "LNDDYL", + "Liuxinyu970226", + "Wehwei", "和平至上", - "Jessica1213", "沈澄心" ] }, From 1a0d966b703ddf5aee41b6cdc8f3e3ac87e025b7 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Fri, 10 Apr 2020 10:19:43 -0700 Subject: [PATCH 008/139] Updating chrome version in selenium config. (#3805) --- tests/scripts/selenium-config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/scripts/selenium-config.js b/tests/scripts/selenium-config.js index 3e4880888..84a4168c3 100644 --- a/tests/scripts/selenium-config.js +++ b/tests/scripts/selenium-config.js @@ -9,7 +9,7 @@ module.exports = { chrome: { // check for more recent versions of chrome driver here: // https://chromedriver.storage.googleapis.com/index.html - version: '79.0.3945.36', + version: '81.0.4044.20', arch: process.arch, baseURL: 'https://chromedriver.storage.googleapis.com' }, From 79ce850cf861b88f7fbc875023e8723d1799b133 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Sat, 11 Apr 2020 16:16:25 -0700 Subject: [PATCH 009/139] Fix procedure callers accessing private vars --- blocks/procedures.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blocks/procedures.js b/blocks/procedures.js index c309a2516..4a89582b4 100644 --- a/blocks/procedures.js +++ b/blocks/procedures.js @@ -836,7 +836,7 @@ Blockly.Blocks['procedures_callnoreturn'] = { var name = this.getProcedureCall(); var def = Blockly.Procedures.getDefinition(name, this.workspace); if (def && (def.type != this.defType_ || - JSON.stringify(def.arguments_) != JSON.stringify(this.arguments_))) { + JSON.stringify(def.getVars()) != JSON.stringify(this.arguments_))) { // The signatures don't match. def = null; } From d35b3659c878d43e2dead3c06b0cb60f60ea36a1 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Mon, 13 Apr 2020 15:52:44 -0700 Subject: [PATCH 010/139] Removed duplicate block tests and renamed tests. (#3812) * Removed duplicate block tests and renamed tests. * Refactor shared code and add comment about parent/middle/child. --- tests/jsunit/block_test.js | 243 ------------------------------------- tests/jsunit/index.html | 1 - tests/mocha/block_test.js | 103 ++++++---------- 3 files changed, 37 insertions(+), 310 deletions(-) delete mode 100644 tests/jsunit/block_test.js diff --git a/tests/jsunit/block_test.js b/tests/jsunit/block_test.js deleted file mode 100644 index 3dff5d20e..000000000 --- a/tests/jsunit/block_test.js +++ /dev/null @@ -1,243 +0,0 @@ -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - - /** - * @fileoverview Tests for Blockly.Block - * @author fenichel@google.com (Rachel Fenichel) - */ - -'use strict'; - -var workspace; -var mockControl_; - -function defineTestBlocks() { - Blockly.defineBlocksWithJsonArray([{ - "type": "stack_block", - "message0": "", - "previousStatement": null, - "nextStatement": null - }, - { - "type": "row_block", - "message0": "%1", - "args0": [ - { - "type": "input_value", - "name": "INPUT" - } - ], - "output": null - }]); -} - -function undefineTestBlocks() { - delete Blockly.Blocks['stack_block']; - delete Blockly.Blocks['row_block']; -} - -function blockTest_setUp() { - defineTestBlocks(); - workspace = new Blockly.Workspace(); -} - -function blockTest_tearDown() { - undefineTestBlocks(); - workspace.dispose(); - if (mockControl_) { - mockControl_.restore(); - } -} - -function assertUnpluggedNoheal(blocks) { - // A has nothing connected to it. - assertEquals(0, blocks.A.getChildren().length); - // B and C are still connected. - assertEquals(blocks.B, blocks.C.getParent()); - // B is the top of its stack. - assertNull(blocks.B.getParent()); -} - -function assertUnpluggedHealed(blocks) { - // A and C are connected. - assertEquals(1, blocks.A.getChildren().length); - assertEquals(blocks.A, blocks.C.getParent()); - // B has nothing connected to it. - assertEquals(0, blocks.B.getChildren().length); - // B is the top of its stack. - assertNull(blocks.B.getParent()); -} - -function assertUnpluggedHealFailed(blocks) { - // A has nothing connected to it. - assertEquals(0, blocks.A.getChildren().length); - // B has nothing connected to it. - assertEquals(0, blocks.B.getChildren().length); - // B is the top of its stack. - assertNull(blocks.B.getParent()); - // C is the top of its stack. - assertNull(blocks.C.getParent()); -} - -function setUpRowBlocks() { - var blockA = workspace.newBlock('row_block'); - var blockB = workspace.newBlock('row_block'); - var blockC = workspace.newBlock('row_block'); - - blockA.inputList[0].connection.connect(blockB.outputConnection); - blockB.inputList[0].connection.connect(blockC.outputConnection); - - assertEquals(blockB, blockC.getParent()); - - return { - A: blockA, - B: blockB, - C: blockC - }; -} - -function setUpStackBlocks() { - var blockA = workspace.newBlock('stack_block'); - var blockB = workspace.newBlock('stack_block'); - var blockC = workspace.newBlock('stack_block'); - - blockA.nextConnection.connect(blockB.previousConnection); - blockB.nextConnection.connect(blockC.previousConnection); - - assertEquals(blockB, blockC.getParent()); - - return { - A: blockA, - B: blockB, - C: blockC - }; -} - - -function test_block_stack_unplug_noheal() { - blockTest_setUp(); - try { - var blocks = setUpStackBlocks(); - blocks.B.unplug(); - assertUnpluggedNoheal(blocks); - } finally { - blockTest_tearDown(); - } -} - -function test_block_stack_unplug_heal() { - blockTest_setUp(); - try { - var blocks = setUpStackBlocks(); - blocks.B.unplug(true); - assertUnpluggedHealed(blocks); - } finally { - blockTest_tearDown(); - } -} - -function test_block_stack_unplug_heal_bad_checks() { - blockTest_setUp(); - try { - var blocks = setUpStackBlocks(); - - // A and C can't connect, but both can connect to B. - blocks.A.nextConnection.setCheck('type1'); - blocks.C.previousConnection.setCheck('type2'); - - // The types don't work. - blocks.B.unplug(true); - - assertUnpluggedHealFailed(blocks); - } finally { - blockTest_tearDown(); - } -} - -function test_block_row_unplug_noheal() { - blockTest_setUp(); - try { - var blocks = setUpRowBlocks(); - blocks.B.unplug(false); - assertUnpluggedNoheal(blocks); - } finally { - blockTest_tearDown(); - } -} - -function test_block_row_unplug_heal() { - blockTest_setUp(); - try { - var blocks = setUpRowBlocks(); - // Each block has only one input, and the types work. - blocks.B.unplug(true); - assertUnpluggedHealed(blocks); - } finally { - blockTest_tearDown(); - } -} - -function test_block_row_unplug_heal_bad_checks() { - blockTest_setUp(); - try { - var blocks = setUpRowBlocks(); - - // A and C can't connect, but both can connect to B. - blocks.A.inputList[0].connection.setCheck('type1'); - blocks.C.outputConnection.setCheck('type2'); - - // Each block has only one input, but the types don't work. - blocks.B.unplug(true); - assertUnpluggedHealFailed(blocks); - } finally { - blockTest_tearDown(); - } -} - -function test_block_row_unplug_multi_inputs_parent() { - blockTest_setUp(); - try { - var blocks = setUpRowBlocks(); - // Add extra input to parent - blocks.A.appendValueInput('INPUT').setCheck(null); - - // Parent block has multiple inputs. - blocks.B.unplug(true); - assertUnpluggedHealed(blocks); - } finally { - blockTest_tearDown(); - } -} - -function test_block_row_unplug_multi_inputs_middle() { - blockTest_setUp(); - try { - var blocks = setUpRowBlocks(); - // Add extra input to middle block - blocks.B.appendValueInput('INPUT').setCheck(null); - - // Middle block has multiple inputs. - blocks.B.unplug(true); - assertUnpluggedHealed(blocks); - } finally { - blockTest_tearDown(); - } -} - -function test_block_row_unplug_multi_inputs_child() { - blockTest_setUp(); - try { - var blocks = setUpRowBlocks(); - // Add extra input to child block - blocks.C.appendValueInput('INPUT').setCheck(null); - - // Child block input count doesn't matter. - blocks.B.unplug(true); - assertUnpluggedHealed(blocks); - } finally { - blockTest_tearDown(); - } -} diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index d7d36a7d6..bbb0f24b6 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -17,7 +17,6 @@ - diff --git a/tests/mocha/block_test.js b/tests/mocha/block_test.js index 69a00b96e..dcdea6a61 100644 --- a/tests/mocha/block_test.js +++ b/tests/mocha/block_test.js @@ -49,6 +49,29 @@ suite('Blocks', function() { delete Blockly.Blocks['statement_block']; }); + function createTestBlocks(workspace, isRow) { + var blockType = isRow ? 'row_block' : 'stack_block'; + var blockA = workspace.newBlock(blockType); + var blockB = workspace.newBlock(blockType); + var blockC = workspace.newBlock(blockType); + + if (isRow) { + blockA.inputList[0].connection.connect(blockB.outputConnection); + blockB.inputList[0].connection.connect(blockC.outputConnection); + } else { + blockA.nextConnection.connect(blockB.previousConnection); + blockB.nextConnection.connect(blockC.previousConnection); + } + + assertEquals(blockB, blockC.getParent()); + + return { + A: blockA, /* Parent */ + B: blockB, /* Middle */ + C: blockC /* Child */ + }; + } + suite('Unplug', function() { function assertUnpluggedNoheal(blocks) { // A has nothing connected to it. @@ -80,20 +103,7 @@ suite('Blocks', function() { suite('Row', function() { setup(function() { - var blockA = this.workspace.newBlock('row_block'); - var blockB = this.workspace.newBlock('row_block'); - var blockC = this.workspace.newBlock('row_block'); - - blockA.inputList[0].connection.connect(blockB.outputConnection); - blockB.inputList[0].connection.connect(blockC.outputConnection); - - assertEquals(blockB, blockC.getParent()); - - this.blocks = { - A: blockA, - B: blockB, - C: blockC - }; + this.blocks = createTestBlocks(this.workspace, true); }); test('Don\'t heal', function() { @@ -116,21 +126,21 @@ suite('Blocks', function() { blocks.B.unplug(true); assertUnpluggedHealFailed(blocks); }); - test('A has multiple inputs', function() { + test('Parent has multiple inputs', function() { var blocks = this.blocks; // Add extra input to parent blocks.A.appendValueInput("INPUT").setCheck(null); blocks.B.unplug(true); assertUnpluggedHealed(blocks); }); - test('B has multiple inputs', function() { + test('Middle has multiple inputs', function() { var blocks = this.blocks; // Add extra input to middle block blocks.B.appendValueInput("INPUT").setCheck(null); blocks.B.unplug(true); assertUnpluggedHealed(blocks); }); - test('C has multiple inputs', function() { + test('Child has multiple inputs', function() { var blocks = this.blocks; // Add extra input to child block blocks.C.appendValueInput("INPUT").setCheck(null); @@ -138,7 +148,7 @@ suite('Blocks', function() { blocks.B.unplug(true); assertUnpluggedHealed(blocks); }); - test('C is Shadow', function() { + test('Child is shadow', function() { var blocks = this.blocks; blocks.C.setShadow(true); blocks.B.unplug(true); @@ -149,20 +159,7 @@ suite('Blocks', function() { }); suite('Stack', function() { setup(function() { - var blockA = this.workspace.newBlock('stack_block'); - var blockB = this.workspace.newBlock('stack_block'); - var blockC = this.workspace.newBlock('stack_block'); - - blockA.nextConnection.connect(blockB.previousConnection); - blockB.nextConnection.connect(blockC.previousConnection); - - assertEquals(blockB, blockC.getParent()); - - this.blocks = { - A: blockA, - B: blockB, - C: blockC - }; + this.blocks = createTestBlocks(this.workspace, false); }); test('Don\'t heal', function() { @@ -184,7 +181,7 @@ suite('Blocks', function() { assertUnpluggedHealFailed(blocks); }); - test('C is Shadow', function() { + test('Child is shadow', function() { var blocks = this.blocks; blocks.C.setShadow(true); blocks.B.unplug(true); @@ -226,20 +223,7 @@ suite('Blocks', function() { suite('Row', function() { setup(function() { - var blockA = this.workspace.newBlock('row_block'); - var blockB = this.workspace.newBlock('row_block'); - var blockC = this.workspace.newBlock('row_block'); - - blockA.inputList[0].connection.connect(blockB.outputConnection); - blockB.inputList[0].connection.connect(blockC.outputConnection); - - assertEquals(blockB, blockC.getParent()); - - this.blocks = { - A: blockA, - B: blockB, - C: blockC - }; + this.blocks = createTestBlocks(this.workspace, true); }); test('Don\'t heal', function() { @@ -262,21 +246,21 @@ suite('Blocks', function() { blocks.B.dispose(true); assertDisposedHealFailed(blocks); }); - test('A has multiple inputs', function() { + test('Parent has multiple inputs', function() { var blocks = this.blocks; // Add extra input to parent blocks.A.appendValueInput("INPUT").setCheck(null); blocks.B.dispose(true); assertDisposedHealed(blocks); }); - test('B has multiple inputs', function() { + test('Middle has multiple inputs', function() { var blocks = this.blocks; // Add extra input to middle block blocks.B.appendValueInput("INPUT").setCheck(null); blocks.B.dispose(true); assertDisposedHealed(blocks); }); - test('C has multiple inputs', function() { + test('Child has multiple inputs', function() { var blocks = this.blocks; // Add extra input to child block blocks.C.appendValueInput("INPUT").setCheck(null); @@ -284,7 +268,7 @@ suite('Blocks', function() { blocks.B.dispose(true); assertDisposedHealed(blocks); }); - test('C is Shadow', function() { + test('Child is shadow', function() { var blocks = this.blocks; blocks.C.setShadow(true); blocks.B.dispose(true); @@ -295,20 +279,7 @@ suite('Blocks', function() { }); suite('Stack', function() { setup(function() { - var blockA = this.workspace.newBlock('stack_block'); - var blockB = this.workspace.newBlock('stack_block'); - var blockC = this.workspace.newBlock('stack_block'); - - blockA.nextConnection.connect(blockB.previousConnection); - blockB.nextConnection.connect(blockC.previousConnection); - - assertEquals(blockB, blockC.getParent()); - - this.blocks = { - A: blockA, - B: blockB, - C: blockC - }; + this.blocks = createTestBlocks(this.workspace, false); }); test('Don\'t heal', function() { @@ -330,7 +301,7 @@ suite('Blocks', function() { assertDisposedHealFailed(blocks); }); - test('C is Shadow', function() { + test('Child is shadow', function() { var blocks = this.blocks; blocks.C.setShadow(true); blocks.B.dispose(true); From cdc34c243db019d522f31f094d683f06f16c8f1a Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Tue, 14 Apr 2020 05:20:05 +0200 Subject: [PATCH 011/139] Localisation updates from https://translatewiki.net. --- msg/json/he.json | 7 +++++- msg/json/kab.json | 59 ++++++++++++++++++++++++----------------------- msg/json/ta.json | 13 +++++++++++ 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/msg/json/he.json b/msg/json/he.json index 5be2f3a00..5f7e8077d 100644 --- a/msg/json/he.json +++ b/msg/json/he.json @@ -188,6 +188,7 @@ "MATH_ONLIST_OPERATOR_MAX": "מקסימום של רשימה", "MATH_ONLIST_TOOLTIP_MAX": "תחזיר את המספר הגדול ביותר ברשימה.", "MATH_ONLIST_OPERATOR_AVERAGE": "ממוצע של רשימה", + "MATH_ONLIST_TOOLTIP_AVERAGE": "החזרת הממוצע (ממוצע חשבוני) של הערכים המספריים שברשימה.", "MATH_ONLIST_OPERATOR_MEDIAN": "חציון של רשימה", "MATH_ONLIST_TOOLTIP_MEDIAN": "תחזיר את המספר החיצוני ביותר ברשימה.", "MATH_ONLIST_OPERATOR_MODE": "שכיחי הרשימה", @@ -196,10 +197,14 @@ "MATH_ONLIST_TOOLTIP_STD_DEV": "מחזיר את סטיית התקן של הרשימה.", "MATH_ONLIST_OPERATOR_RANDOM": "פריט אקראי מרשימה", "MATH_ONLIST_TOOLTIP_RANDOM": "תחזיר רכיב אקראי מרשימה.", + "MATH_MODULO_HELPURL": "https://he.wikipedia.org/wiki/חשבון_מודולרי", "MATH_MODULO_TITLE": "שארית החילוק %1 ÷ %2", "MATH_MODULO_TOOLTIP": "החזרת השארית מחלוקת שני המספרים.", "MATH_CONSTRAIN_TITLE": "הגבל %1 בין %2 ל %3", + "MATH_CONSTRAIN_TOOLTIP": "הגבלת מספר כך שיהיה בין המגבלות שמוגדרות (כולל).", + "MATH_RANDOM_INT_HELPURL": "https://he.wikipedia.org/wiki/מחולל_מספרים_אקראיים", "MATH_RANDOM_INT_TITLE": "מספר שלם אקראי בין %1 ל-%2 (כולל)", + "MATH_RANDOM_INT_TOOLTIP": "החזרת מספר שלם, חיובי ואקראי בין שני הגבולות שהוגדרו, כולל.", "MATH_RANDOM_FLOAT_TITLE_RANDOM": "שבר אקראי", "TEXT_TEXT_HELPURL": "https://he.wikipedia.org/wiki/מחרוזת_(מדעי_המחשב)", "TEXT_TEXT_TOOLTIP": "אות, מילה, או שורת טקסט.", @@ -321,7 +326,7 @@ "PROCEDURES_BEFORE_PARAMS": "עם:", "PROCEDURES_CALL_BEFORE_PARAMS": "עם:", "PROCEDURES_DEFNORETURN_TOOLTIP": "יצירת פונקציה ללא פלט.", - "PROCEDURES_DEFNORETURN_COMMENT": "תאר את הפונקציה הזו...", + "PROCEDURES_DEFNORETURN_COMMENT": "תאר את הפונקציה הזאת...", "PROCEDURES_DEFRETURN_RETURN": "להחזיר", "PROCEDURES_DEFRETURN_TOOLTIP": "יצירת פונקציה עם פלט.", "PROCEDURES_ALLOW_STATEMENTS": "לאפשר פעולות", diff --git a/msg/json/kab.json b/msg/json/kab.json index fe6bc150c..5736bd468 100644 --- a/msg/json/kab.json +++ b/msg/json/kab.json @@ -4,12 +4,13 @@ "Alem", "Amaziɣ maziɣ", "Belkacem77", + "K Messaoudi", "SlimaneAmiri", "YubaWissin" ] }, "VARIABLES_DEFAULT_NAME": "aferdis", - "UNNAMED_KEY": "warisem", + "UNNAMED_KEY": "war isem", "TODAY": "Ass-a", "DUPLICATE_BLOCK": "Sleg", "ADD_COMMENT": "Rnu awennit", @@ -18,7 +19,7 @@ "EXTERNAL_INPUTS": "Inekcam izɣarayen", "INLINE_INPUTS": "Inekcam srid", "DELETE_BLOCK": "Kkes iḥder", - "DELETE_X_BLOCKS": "Kkes %1 n yiḥderan", + "DELETE_X_BLOCKS": "Kkes %1 n yiḥedran", "DELETE_ALL_BLOCKS": "Kkes akk %1 n yiḥedran?", "CLEAN_UP": "Sfeḍ iḥedran", "COLLAPSE_BLOCK": "Fneẓ iḥder", @@ -53,37 +54,37 @@ "COLOUR_RGB_GREEN": "azegzaw", "COLOUR_RGB_BLUE": "anili", "COLOUR_RGB_TOOLTIP": "Rnu ini s tnecta yettunefk s tesmekta n uzeggaɣ, azegzaw, akked unili. Yessefk akk azalen ad ilin gar 0 akked 100.", - "COLOUR_BLEND_TITLE": "rkwec", + "COLOUR_BLEND_TITLE": "rkec", "COLOUR_BLEND_COLOUR1": "ini 1", "COLOUR_BLEND_COLOUR2": "ini 2", "COLOUR_BLEND_RATIO": "afmiḍi", "COLOUR_BLEND_TOOLTIP": "Sexleḍ sin n yiniten d tesmekta (gar 0.0 ar 1.0).", "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "Ales %1 n tikal", + "CONTROLS_REPEAT_TITLE": "Ales %1 n tikkal", "CONTROLS_REPEAT_INPUT_DO": "eg", "CONTROLS_REPEAT_TOOLTIP": "Selkem ddeqs n tinaḍin ddeqs n tikal.", "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ales skud", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ales arama", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ales armi", "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Skud azal d idetti, selkem ihi tinadin.", "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Skud azal d ucciḍ, selkem ihi tinadin.", - "CONTROLS_FOR_TOOLTIP": "Mudd i umutti '%1' azalen seg umḍan n tazwara arama d umḍan n tagara, stmerna n usurif yettunefken, sakin selkem tiaḍin yettunefken.", + "CONTROLS_FOR_TOOLTIP": "Mudd i umutti '%1' azalen seg umḍan n tazwara armi d amḍan n taggara, s tmerna n usurif yettunefken, sakin selkem tinaḍin yettunefken.", "CONTROLS_FOR_TITLE": "siḍen akked %1 seg %2 ar %3 s %4", "CONTROLS_FOREACH_TITLE": "i yal aferdis %1 di tebdart %2", "CONTROLS_FOREACH_TOOLTIP": "I yal aferdis n tebdart, mudd azal n uferdis i umutti '%1', sakin selkem tinaḍin.", "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ffeɣ seg tneddict", "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "kemmel s wallus d tneddict d-iteddun", "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Ffeɣ si tneddict tamagbart.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Zgel ayen i d-yeqqimen di tneddict-agi, sakin kemmel allus d-iteddun.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Ɣur-k: Iḥder-agi yessefk ad yettwaseqdec di tneddict.", - "CONTROLS_IF_TOOLTIP_1": "ma yella azal d idetti, ihi selkem kra n tinaḍin.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Zgel ayen i d-yeqqimen di tneddict-a, sakin kemmel allus d-itteddun.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Ɣur-k: Iḥder-a yessefk ad yettwaseqdec di tneddict.", + "CONTROLS_IF_TOOLTIP_1": "mayella azal d idetti, ihi selkem kra n tinaḍin.", "CONTROLS_IF_TOOLTIP_2": "Ma yella zal d idetti, selkem iḥder amezwaru. Neɣ ma ulac, selkem iḥder wis sin.", "CONTROLS_IF_TOOLTIP_3": "Ma yella azal amezwaru d idetti, selkem iḥder amezwaru. Neɣ ma azal wis sin d ucciḍ, selkem iḥ€der wis sin.", - "CONTROLS_IF_TOOLTIP_4": "Ma yella azal amezwaru d idetti, selkem iḥeder amezwaru. Neɣ, ma yella azal wis sin d idetti, selkem iḥder wis sin. Ma yella ula d yisen seg-sen mačči d idetti, selkem iḥder aneggaru.", + "CONTROLS_IF_TOOLTIP_4": "Mayella azal amezwaru d idetti, selkem iḥder amezwaru. Neɣ, mayella azal wis sin d idetti, selkem iḥder wis sin. Mayella ula d yiwen seg-sen ur yelli d idetti, selkem iḥder aneggaru.", "CONTROLS_IF_MSG_IF": "ma", "CONTROLS_IF_MSG_ELSEIF": "neɣ ma", "CONTROLS_IF_MSG_ELSE": "neɣ", - "CONTROLS_IF_IF_TOOLTIP": "Rnu, kkes, neq ales ales asmizzwer n tgezmiyin akken ad talseḍ tawila n iḥder-agi ma.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Rni tawtilt i yiḥder ma.", + "CONTROLS_IF_IF_TOOLTIP": "Rnu, kkes, neq ales asmizzwer n tgezmiyin akken ad talseḍ tawila n yiḥder-a ma.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Rnu tawtilt i yiḥder ma.", "CONTROLS_IF_ELSE_TOOLTIP": "Rnu tawtilt taneggarut i yiḥder ma igebren akk tinaḍin.", "IOS_OK": "IH", "IOS_CANCEL": "Sefsex", @@ -99,18 +100,18 @@ "IOS_VARIABLES_VARIABLE_NAME": "Isem n umutti", "IOS_VARIABLES_EMPTY_NAME_ERROR": "Ur tezmireḍ ara ad tesqedceḍ isem n umutti amaynut.", "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Ad yerr idetti ma yella i sin n inekcam d imegduya.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Ad d-yerr idetti ma yella i sin n inekcam mačči d imegduya.", - "LOGIC_COMPARE_TOOLTIP_LT": "Ad d-yerr idetti ma yella anekcam amezwaru meẓẓi ɣef wis sin.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Ad d-yerr idetti ma yella anekcam amezwaru meẓẓi neɣ yegda wis sin.", - "LOGIC_COMPARE_TOOLTIP_GT": "Ad d-yerr idetti ma yella anekcam amezwaru meqqeṛ ɣef wis sin.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Ad d-yerr idetti ma yella anekcam amezwaru meqqeṛ neɣ yegda wis sin.", - "LOGIC_OPERATION_TOOLTIP_AND": "Ad d-yerr idetti ma yella inekcam d idettiyen.", + "LOGIC_COMPARE_TOOLTIP_EQ": "Ad yerr idetti ma yella i sin n yinekcam d imegduya.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Ad d-yerr idetti mayella i sin n yinekcam mačči d imegduya.", + "LOGIC_COMPARE_TOOLTIP_LT": "Ad d-yerr idetti ma anekcam amezwaru meẓẓiy ɣef wis sin.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Ad d-yerr idetti ma anekcam amezwaru meẓẓiy neɣ yegda wis sin.", + "LOGIC_COMPARE_TOOLTIP_GT": "Ad d-yerr idetti ma anekcam amezwaru meqqer ɣef wis sin.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Ad d-yerr idetti ma anekcam amezwaru meqqer neɣ yegda wis sin.", + "LOGIC_OPERATION_TOOLTIP_AND": "Ad d-yerr idetti ma inekcam d idettiyen.", "LOGIC_OPERATION_AND": "akked", - "LOGIC_OPERATION_TOOLTIP_OR": "Ad d-yerr idetti ma yella ɣarsum yiwen seg inekcam d idetti.", + "LOGIC_OPERATION_TOOLTIP_OR": "Ad d-yerr idetti ma ɣarsum yiwen seg yinekcam d idetti.", "LOGIC_OPERATION_OR": "neɣ", "LOGIC_NEGATE_TITLE": "mačči %1", - "LOGIC_NEGATE_TOOLTIP": "Ad d-yerr idetti ma yella anekcam d ucciḍ. Ad d-yerr ucciḍ ma yella anekcam d idetti.", + "LOGIC_NEGATE_TOOLTIP": "Ad d-yerr idetti ma anekcam d ucciḍ. Ad d-yerr ucciḍ ma yella anekcam d idetti.", "LOGIC_BOOLEAN_TRUE": "idetti", "LOGIC_BOOLEAN_FALSE": "ucciḍ", "LOGIC_BOOLEAN_TOOLTIP": "Ad d-yerr idetti neɣ ucciḍ", @@ -118,19 +119,19 @@ "LOGIC_NULL_TOOLTIP": "Ad d-yerr ilem", "LOGIC_TERNARY_CONDITION": "sekyed", "LOGIC_TERNARY_IF_TRUE": "ma d idetti", - "LOGIC_TERNARY_IF_FALSE": "ma ucciḍ", - "LOGIC_TERNARY_TOOLTIP": "Senqed tawtilt deg 'sekyed'. Ma yella d idetti, ad d-yerr azal 'ma idetti', ma ulac ad d-yerr azam 'ma ucciḍ'.", + "LOGIC_TERNARY_IF_FALSE": "ma d ucciḍ", + "LOGIC_TERNARY_TOOLTIP": "Senqed tawtilt deg 'sekyed'. Ma d idetti, ad d-yerr azal 'ma idetti', ma ulac ad d-yerr azam 'ma ucciḍ'.", "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", "MATH_NUMBER_TOOLTIP": "Amḍan.", "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Ad d-yerr tmerni n sin n imiḍanen.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Ad d-yerr tmernit n sin n imiḍanen.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Ad d-yerr tukksa gar sin n imiḍanen.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Ad d-yerr aful n sin n imḍanen.", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Ad d-yerr tmerni n sin n yimiḍanen.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Ad d-yerr tmernit n sin n yimiḍanen.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Ad d-yerr tukksa gar sin n yimiḍanen.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Ad d-yerr aful n sin n yimḍanen.", "MATH_ARITHMETIC_TOOLTIP_POWER": "Ad d-yerr amḍan amezwaru uzmir wis sin.", "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", "MATH_SINGLE_OP_ROOT": "aẓar uzmir 2", - "MATH_SINGLE_TOOLTIP_ROOT": "Ad d-yerr aẓaṛ uzmir sin n umiḍan.", + "MATH_SINGLE_TOOLTIP_ROOT": "Ad d-yerr aẓar uzmir sin n umḍan.", "MATH_SINGLE_OP_ABSOLUTE": "azal amagdez", "MATH_SINGLE_TOOLTIP_ABS": "Ad d-yerr azal amagdez n umiḍan.", "MATH_SINGLE_TOOLTIP_NEG": "Ad d-yerr ugmiḍ n umḍan.", @@ -154,7 +155,7 @@ "MATH_IS_POSITIVE": "d ufrar", "MATH_IS_NEGATIVE": "d uzdir", "MATH_IS_DIVISIBLE_BY": "d ubṭay ɣef", - "MATH_IS_TOOLTIP": "Senqed ma yella amḍan d ayugan, d aryugan, d amenzu, d ummid, d ufrar, d uzdir, neɣ d ybṭay ɣef kra n umḍan. Ad d-yerr idettu neɣ ucciḍ.", + "MATH_IS_TOOLTIP": "Senqed ma amḍan d ayugan, d aryugan, d amenzu, d ummid, d ufrar, d uzdir, neɣ d ubṭay ɣef kra n umḍan. Ad d-yerr idetti neɣ ucciḍ.", "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", "MATH_CHANGE_TITLE": "snifel %1 s %2", "MATH_CHANGE_TOOLTIP": "Rnu amḍan i umutti '%1'.", diff --git a/msg/json/ta.json b/msg/json/ta.json index 0efbfaad3..6c0ed1d50 100644 --- a/msg/json/ta.json +++ b/msg/json/ta.json @@ -1,6 +1,7 @@ { "@metadata": { "authors": [ + "Aswn", "ElangoRamanujam", "Ezhillang", "Karuthan", @@ -26,10 +27,13 @@ "DISABLE_BLOCK": "உறுப்பை இயங்காது செய்", "ENABLE_BLOCK": "உறுப்பை இயங்குமாரு செய்", "HELP": "உதவி", + "UNDO": "மீளமை", + "REDO": "மீண்டும் செய்", "CHANGE_VALUE_TITLE": "மதிப்பை மாற்றவும்:", "RENAME_VARIABLE": "மாறிலியை மறுபெயரிடுக...", "RENAME_VARIABLE_TITLE": "அனைத்து '%1' மாறிலிகளையும் பின்வருமாறு மறுபெயரிடுக:", "NEW_VARIABLE": "மாறிலியை உருவாக்குக...", + "NEW_VARIABLE_TYPE_TITLE": "புதிய மாறிலியின் பெயர்:", "NEW_VARIABLE_TITLE": "புதிய மாறிலியின் பெயர்:", "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", "COLOUR_PICKER_TOOLTIP": "வண்ண தட்டிலிருந்து ஒரு நிறத்தைத் தேர்ந்தெடுக்கவும்.", @@ -72,9 +76,14 @@ "CONTROLS_IF_IF_TOOLTIP": "கட்டளைகளை தொகுப்பு திருத்துதம் செய்", "CONTROLS_IF_ELSEIF_TOOLTIP": "ஆனால் தொகுப்பிற்கு நிபந்தனை சேர்க்க", "CONTROLS_IF_ELSE_TOOLTIP": "ஆனால் தொகுப்பிற்கு விதிவிலக்கு காப்பை சேர்க்க", + "IOS_OK": "சரி", + "IOS_CANCEL": "இரத்து செய்", + "IOS_ERROR": "பிழை", + "IOS_VARIABLES_ADD_VARIABLE": "+ மாறிலியினை சேர்", "IOS_VARIABLES_ADD_BUTTON": "சேர்க்கவும்", "IOS_VARIABLES_RENAME_BUTTON": "பெயர் மாற்றுக", "IOS_VARIABLES_DELETE_BUTTON": "நீக்கவும்", + "IOS_VARIABLES_VARIABLE_NAME": "மாறிலியின் பெயர்", "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", "LOGIC_COMPARE_TOOLTIP_EQ": "இரண்டு மாறியும் ஈடானால், மெய் பின்கொடு.", "LOGIC_COMPARE_TOOLTIP_NEQ": "இரண்டு மாறியும் ஈடாகாவிட்டால், மெய் பின்கொடு.", @@ -267,6 +276,10 @@ "LISTS_GET_SUBLIST_END_FROM_END": "முடிவில் இருந்து # வரை", "LISTS_GET_SUBLIST_END_LAST": "முடிவு வரை", "LISTS_GET_SUBLIST_TOOLTIP": "குறிப்பட்ட பகுதி பட்டியலின் நகலை கொடு", + "LISTS_SORT_ORDER_ASCENDING": "ஏறுவரிசை", + "LISTS_SORT_ORDER_DESCENDING": "இறங்குவரிசை", + "LISTS_SORT_TYPE_NUMERIC": "எண்வரிசை", + "LISTS_SORT_TYPE_TEXT": "அகரவரிசை", "LISTS_SPLIT_LIST_FROM_TEXT": "உரையில் இருந்து பட்டியல் உருவாக்கு", "LISTS_SPLIT_TEXT_FROM_LIST": "பட்டியலில் இருந்து உரை உருவாக்கு", "LISTS_SPLIT_WITH_DELIMITER": "தடை எழுத்து", From b1b2af2a485dad1ca3e2c54a759b71e43e988742 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Tue, 14 Apr 2020 13:21:48 -0700 Subject: [PATCH 012/139] Converting utils tests to mocha and removing duplicates. (#3813) * Converting utils tests to mocha and removing duplicates. * Adding eslint exception for helper function. * Splitting tokenizeInterpolation into chunks. --- tests/jsunit/index.html | 4 - tests/jsunit/utils_dom_test.js | 47 ------ tests/jsunit/utils_math_test.js | 28 ---- tests/jsunit/utils_string_test.js | 67 -------- tests/jsunit/utils_test.js | 210 ------------------------- tests/mocha/.eslintrc.json | 1 + tests/mocha/utils_test.js | 249 ++++++++++++++++++++++++++++++ 7 files changed, 250 insertions(+), 356 deletions(-) delete mode 100644 tests/jsunit/utils_dom_test.js delete mode 100644 tests/jsunit/utils_math_test.js delete mode 100644 tests/jsunit/utils_string_test.js delete mode 100644 tests/jsunit/utils_test.js diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index bbb0f24b6..da931cf70 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -21,10 +21,6 @@ - - - - diff --git a/tests/jsunit/utils_dom_test.js b/tests/jsunit/utils_dom_test.js deleted file mode 100644 index 90c58a8a8..000000000 --- a/tests/jsunit/utils_dom_test.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - -function test_addClass() { - var p = document.createElement('p'); - Blockly.utils.dom.addClass(p, 'one'); - assertEquals('Adding "one"', 'one', p.className); - Blockly.utils.dom.addClass(p, 'one'); - assertEquals('Adding duplicate "one"', 'one', p.className); - Blockly.utils.dom.addClass(p, 'two'); - assertEquals('Adding "two"', 'one two', p.className); - Blockly.utils.dom.addClass(p, 'two'); - assertEquals('Adding duplicate "two"', 'one two', p.className); - Blockly.utils.dom.addClass(p, 'three'); - assertEquals('Adding "three"', 'one two three', p.className); -} - -function test_hasClass() { - var p = document.createElement('p'); - p.className = ' one three two three '; - assertTrue('Has "one"', Blockly.utils.dom.hasClass(p, 'one')); - assertTrue('Has "two"', Blockly.utils.dom.hasClass(p, 'two')); - assertTrue('Has "three"', Blockly.utils.dom.hasClass(p, 'three')); - assertFalse('Has no "four"', Blockly.utils.dom.hasClass(p, 'four')); - assertFalse('Has no "t"', Blockly.utils.dom.hasClass(p, 't')); - } - -function test_removeClass() { - var p = document.createElement('p'); - p.className = ' one three two three '; - Blockly.utils.dom.removeClass(p, 'two'); - assertEquals('Removing "two"', 'one three three', p.className); - Blockly.utils.dom.removeClass(p, 'four'); - assertEquals('Removing "four"', 'one three three', p.className); - Blockly.utils.dom.removeClass(p, 'three'); - assertEquals('Removing "three"', 'one', p.className); - Blockly.utils.dom.removeClass(p, 'ne'); - assertEquals('Removing "ne"', 'one', p.className); - Blockly.utils.dom.removeClass(p, 'one'); - assertEquals('Removing "one"', '', p.className); - Blockly.utils.dom.removeClass(p, 'zero'); - assertEquals('Removing "zero"', '', p.className); -} diff --git a/tests/jsunit/utils_math_test.js b/tests/jsunit/utils_math_test.js deleted file mode 100644 index 6f56ec8b1..000000000 --- a/tests/jsunit/utils_math_test.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - -function test_toRadians() { - var quarter = Math.PI / 2; - assertEquals('-90', -quarter, Blockly.utils.math.toRadians(-90)); - assertEquals('0', 0, Blockly.utils.math.toRadians(0)); - assertEquals('90', quarter, Blockly.utils.math.toRadians(90)); - assertEquals('180', 2 * quarter, Blockly.utils.math.toRadians(180)); - assertEquals('270', 3 * quarter, Blockly.utils.math.toRadians(270)); - assertEquals('360', 4 * quarter, Blockly.utils.math.toRadians(360)); - assertEquals('450', 5 * quarter, Blockly.utils.math.toRadians(360 + 90)); -} - -function test_toDegrees() { - var quarter = Math.PI / 2; - assertEquals('-90', -90, Blockly.utils.math.toDegrees(-quarter)); - assertEquals('0', 0, Blockly.utils.math.toDegrees(0)); - assertEquals('90', 90, Blockly.utils.math.toDegrees(quarter)); - assertEquals('180', 180, Blockly.utils.math.toDegrees(2 * quarter)); - assertEquals('270', 270, Blockly.utils.math.toDegrees(3 * quarter)); - assertEquals('360', 360, Blockly.utils.math.toDegrees(4 * quarter)); - assertEquals('450', 360 + 90, Blockly.utils.math.toDegrees(5 * quarter)); -} diff --git a/tests/jsunit/utils_string_test.js b/tests/jsunit/utils_string_test.js deleted file mode 100644 index 507368b8b..000000000 --- a/tests/jsunit/utils_string_test.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - -function test_startsWith() { - assertEquals('Does not start with', false, Blockly.utils.string.startsWith('123', '2')); - assertEquals('Start with', true, Blockly.utils.string.startsWith('123', '12')); - assertEquals('Start with empty string 1', true, Blockly.utils.string.startsWith('123', '')); - assertEquals('Start with empty string 2', true, Blockly.utils.string.startsWith('', '')); -} - -function test_commonWordPrefix() { - var len = Blockly.utils.string.commonWordPrefix('one,two,three,four,five'.split(',')); - assertEquals('No prefix', 0, len); - len = Blockly.utils.string.commonWordPrefix('Xone,Xtwo,Xthree,Xfour,Xfive'.split(',')); - assertEquals('No word prefix', 0, len); - len = Blockly.utils.string.commonWordPrefix('abc de,abc de,abc de,abc de'.split(',')); - assertEquals('Full equality', 6, len); - len = Blockly.utils.string.commonWordPrefix('abc deX,abc deY'.split(',')); - assertEquals('One word prefix', 4, len); - len = Blockly.utils.string.commonWordPrefix('abc de,abc deY'.split(',')); - assertEquals('Overflow no', 4, len); - len = Blockly.utils.string.commonWordPrefix('abc de,abc de Y'.split(',')); - assertEquals('Overflow yes', 6, len); - len = Blockly.utils.string.commonWordPrefix(['Hello World']); - assertEquals('List of one', 11, len); - len = Blockly.utils.string.commonWordPrefix([]); - assertEquals('Empty list', 0, len); - len = Blockly.utils.string.commonWordPrefix('turn left,turn right'.split(',')); - assertEquals('No prefix due to &nbsp;', 0, len); - len = Blockly.utils.string.commonWordPrefix('turn\u00A0left,turn\u00A0right'.split(',')); - assertEquals('No prefix due to \\u00A0', 0, len); -} - -function test_commonWordSuffix() { - var len = Blockly.utils.string.commonWordSuffix('one,two,three,four,five'.split(',')); - assertEquals('No prefix', 0, len); - len = Blockly.utils.string.commonWordSuffix('oneX,twoX,threeX,fourX,fiveX'.split(',')); - assertEquals('No word prefix', 0, len); - len = Blockly.utils.string.commonWordSuffix('abc de,abc de,abc de,abc de'.split(',')); - assertEquals('Full equality', 6, len); - len = Blockly.utils.string.commonWordSuffix('Xabc de,Yabc de'.split(',')); - assertEquals('One word prefix', 3, len); - len = Blockly.utils.string.commonWordSuffix('abc de,Yabc de'.split(',')); - assertEquals('Overflow no', 3, len); - len = Blockly.utils.string.commonWordSuffix('abc de,Y abc de'.split(',')); - assertEquals('Overflow yes', 6, len); - len = Blockly.utils.string.commonWordSuffix(['Hello World']); - assertEquals('List of one', 11, len); - len = Blockly.utils.string.commonWordSuffix([]); - assertEquals('Empty list', 0, len); -} - -function test_shortestStringLength() { - var len = Blockly.utils.string.shortestStringLength('one,two,three,four,five'.split(',')); - assertEquals('Length of "one"', 3, len); - len = Blockly.utils.string.shortestStringLength('one,two,three,four,five,'.split(',')); - assertEquals('Length of ""', 0, len); - len = Blockly.utils.string.shortestStringLength(['Hello World']); - assertEquals('List of one', 11, len); - len = Blockly.utils.string.shortestStringLength([]); - assertEquals('Empty list', 0, len); -} - diff --git a/tests/jsunit/utils_test.js b/tests/jsunit/utils_test.js deleted file mode 100644 index 6e701a385..000000000 --- a/tests/jsunit/utils_test.js +++ /dev/null @@ -1,210 +0,0 @@ -/** - * @license - * Copyright 2011 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - -function test_genUid() { - var uuids = {}; - for (var i = 0; i < 1000; i++) { - var uuid = Blockly.utils.genUid(); - assertFalse('UUID different: ' + uuid, uuid in uuids); - uuids[uuid] = true; - } -} - -function test_tokenizeInterpolation() { - var tokens = Blockly.utils.tokenizeInterpolation(''); - assertArrayEquals('Null interpolation', [], tokens); - - tokens = Blockly.utils.tokenizeInterpolation('Hello'); - assertArrayEquals('No interpolation', ['Hello'], tokens); - - tokens = Blockly.utils.tokenizeInterpolation('Hello%World'); - assertArrayEquals('Unescaped %.', ['Hello%World'], tokens); - - tokens = Blockly.utils.tokenizeInterpolation('Hello%%World'); - assertArrayEquals('Escaped %.', ['Hello%World'], tokens); - - tokens = Blockly.utils.tokenizeInterpolation('Hello %1 World'); - assertArrayEquals('Interpolation.', ['Hello ', 1, ' World'], tokens); - - tokens = Blockly.utils.tokenizeInterpolation('%123Hello%456World%789'); - assertArrayEquals('Interpolations.', [123, 'Hello', 456, 'World', 789], tokens); - - tokens = Blockly.utils.tokenizeInterpolation('%%%x%%0%00%01%'); - assertArrayEquals('Torture interpolations.', ['%%x%0', 0, 1, '%'], tokens); - - Blockly.Msg = Blockly.Msg || {}; - - Blockly.Msg.STRING_REF = 'test string'; - tokens = Blockly.utils.tokenizeInterpolation('%{bky_string_ref}'); - assertArrayEquals('String table reference, lowercase', ['test string'], tokens); - tokens = Blockly.utils.tokenizeInterpolation('%{BKY_STRING_REF}'); - assertArrayEquals('String table reference, uppercase', ['test string'], tokens); - - Blockly.Msg.WITH_PARAM = 'before %1 after'; - tokens = Blockly.utils.tokenizeInterpolation('%{bky_with_param}'); - assertArrayEquals('String table reference, with parameter', ['before ', 1, ' after'], tokens); - - Blockly.Msg.RECURSE = 'before %{bky_string_ref} after'; - tokens = Blockly.utils.tokenizeInterpolation('%{bky_recurse}'); - assertArrayEquals('String table reference, with subreference', ['before test string after'], tokens); - - // Error cases... - tokens = Blockly.utils.tokenizeInterpolation('%{bky_undefined}'); - assertArrayEquals('Undefined string table reference', ['%{bky_undefined}'], tokens); - - Blockly.Msg['1'] = 'Will not match'; - tokens = Blockly.utils.tokenizeInterpolation('before %{1} after'); - assertArrayEquals('Invalid initial digit in string table reference', ['before %{1} after'], tokens); - - Blockly.Msg['TWO WORDS'] = 'Will not match'; - tokens = Blockly.utils.tokenizeInterpolation('before %{two words} after'); - assertArrayEquals('Invalid character in string table reference: space', ['before %{two words} after'], tokens); - - Blockly.Msg['TWO-WORDS'] = 'Will not match'; - tokens = Blockly.utils.tokenizeInterpolation('before %{two-words} after'); - assertArrayEquals('Invalid character in string table reference: dash', ['before %{two-words} after'], tokens); - - Blockly.Msg['TWO.WORDS'] = 'Will not match'; - tokens = Blockly.utils.tokenizeInterpolation('before %{two.words} after'); - assertArrayEquals('Invalid character in string table reference: period', ['before %{two.words} after'], tokens); - - Blockly.Msg['AB&C'] = 'Will not match'; - tokens = Blockly.utils.tokenizeInterpolation('before %{ab&c} after'); - assertArrayEquals('Invalid character in string table reference: &', ['before %{ab&c} after'], tokens); - - Blockly.Msg['UNCLOSED'] = 'Will not match'; - tokens = Blockly.utils.tokenizeInterpolation('before %{unclosed'); - assertArrayEquals('String table reference, with parameter', ['before %{unclosed'], tokens); -} - -function test_replaceMessageReferences() { - Blockly.Msg = Blockly.Msg || {}; - Blockly.Msg.STRING_REF = 'test string'; - Blockly.Msg.SUBREF = 'subref'; - Blockly.Msg.STRING_REF_WITH_ARG = 'test %1 string'; - Blockly.Msg.STRING_REF_WITH_SUBREF = 'test %{bky_subref} string'; - - var resultString = Blockly.utils.replaceMessageReferences(''); - assertEquals('Empty string produces empty string', '', resultString); - - resultString = Blockly.utils.replaceMessageReferences('%%'); - assertEquals('Escaped %', '%', resultString); - resultString = Blockly.utils.replaceMessageReferences('%%{bky_string_ref}'); - assertEquals('Escaped %', '%{bky_string_ref}', resultString); - - resultString = Blockly.utils.replaceMessageReferences('%a'); - assertEquals('Unrecognized % escape code treated as literal', '%a', resultString); - - resultString = Blockly.utils.replaceMessageReferences('%1'); - assertEquals('Interpolation tokens ignored.', '%1', resultString); - resultString = Blockly.utils.replaceMessageReferences('%1 %2'); - assertEquals('Interpolation tokens ignored.', '%1 %2', resultString); - resultString = Blockly.utils.replaceMessageReferences('before %1 after'); - assertEquals('Interpolation tokens ignored.', 'before %1 after', resultString); - - // Blockly.Msg.STRING_REF cases: - resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref}'); - assertEquals('Message ref dereferenced.', 'test string', resultString); - resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref} after'); - assertEquals('Message ref dereferenced.', 'before test string after', resultString); - - // Blockly.Msg.STRING_REF_WITH_ARG cases: - resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref_with_arg}'); - assertEquals('Message ref dereferenced with argument preserved.', 'test %1 string', resultString); - resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref_with_arg} after'); - assertEquals('Message ref dereferenced with argument preserved.', 'before test %1 string after', resultString); - - // Blockly.Msg.STRING_REF_WITH_SUBREF cases: - resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref_with_subref}'); - assertEquals('Message ref and subref dereferenced.', 'test subref string', resultString); - resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref_with_subref} after'); - assertEquals('Message ref and subref dereferenced.', 'before test subref string after', resultString); -} - -function test_arrayRemove() { - var arr = [1, 2, 3, 2]; - assertEquals('Remove Not found', false, Blockly.utils.arrayRemove(arr, 0)); - assertEquals('Remove Not found result', '1,2,3,2', arr.join(',')); - assertEquals('Remove item', true, Blockly.utils.arrayRemove(arr, 2)); - assertEquals('Remove item result', '1,3,2', arr.join(',')); - assertEquals('Remove item again', true, Blockly.utils.arrayRemove(arr, 2)); - assertEquals('Remove item again result', '1,3', arr.join(',')); -} - -function test_XY_REGEX() { - var regex = Blockly.utils.getRelativeXY.XY_REGEX_; - var m; - m = 'INVALID'.match(regex); - assertNull(m); - - m = 'translate(10)'.match(regex); - assertEquals('translate(10), x', '10', m[1]); - assertUndefined('translate(10), y', m[3]); - - m = 'translate(11, 12)'.match(regex); - assertEquals('translate(11, 12), x', '11', m[1]); - assertEquals('translate(11, 12), y', '12', m[3]); - - m = 'translate(13,14)'.match(regex); - assertEquals('translate(13,14), x', '13', m[1]); - assertEquals('translate(13,14), y', '14', m[3]); - - m = 'translate(15 16)'.match(regex); - assertEquals('translate(15 16), x', '15', m[1]); - assertEquals('translate(15 16), y', '16', m[3]); - - m = 'translate(1.23456e+42 0.123456e-42)'.match(regex); - assertEquals('translate(1.23456e+42 0.123456e-42), x', '1.23456e+42', m[1]); - assertEquals('translate(1.23456e+42 0.123456e-42), y', '0.123456e-42', m[3]); -} - -function XY_STYLE_REGEX_() { - var regex = Blockly.utils.getRelativeXY.XY_STYLE_REGEX_; - var m; - m = 'INVALID'.match(regex); - assertNull(m); - - m = 'transform:translate(9px)'.match(regex); - assertEquals('transform:translate(9px), x', '9', m[1]); - assertUndefined('transform:translate(9px), y', m[3]); - - m = 'transform:translate3d(10px)'.match(regex); - assertEquals('transform:translate3d(10px), x', '10', m[1]); - assertUndefined('transform:translate(10px), y', m[3]); - - m = 'transform: translate(11px, 12px)'.match(regex); - assertEquals('transform: translate(11px, 12px), x', '11', m[1]); - assertEquals('transform: translate(11px, 12px), y', '12', m[3]); - - m = 'transform: translate(13px,14px)'.match(regex); - assertEquals('transform: translate(13px,14px), x', '13', m[1]); - assertEquals('transform: translate(13px,14px), y', '14', m[3]); - - m = 'transform: translate(15px 16px)'.match(regex); - assertEquals('transform: translate(15px 16px), x', '15', m[1]); - assertEquals('transform: translate(15px 16px), y', '16', m[3]); - - m = 'transform: translate(1.23456e+42px 0.123456e-42px)'.match(regex); - assertEquals('transform: translate(1.23456e+42px 0.123456e-42px), x', '1.23456e+42', m[1]); - assertEquals('transform: translate(1.23456e+42px 0.123456e-42px), y', '0.123456e-42', m[3]); - - m = 'transform:translate3d(20px, 21px, 22px)'.match(regex); - assertEquals('transform:translate3d(20px, 21px, 22px), x', '21', m[1]); - assertEquals('transform:translate3d(20px, 21px, 22px), y', '22', m[3]); - - m = 'transform:translate3d(23px,24px,25px)'.match(regex); - assertEquals('transform:translate3d(23px,24px,25px), x', '23', m[1]); - assertEquals('transform:translate3d(23px,24px,25px), y', '24', m[3]); - - m = 'transform:translate3d(26px 27px 28px)'.match(regex); - assertEquals('transform:translate3d(26px 27px 28px), x', '26', m[1]); - assertEquals('transform:translate3d(26px 27px 28px), y', '27', m[3]); - - m = 'transform:translate3d(1.23456e+42px 0.123456e-42px 42px)'.match(regex); - assertEquals('transform:translate3d(1.23456e+42px 0.123456e-42px 42px), x', '1.23456e+42', m[1]); - assertEquals('transform:translate3d(1.23456e+42px 0.123456e-42px 42px), y', '0.123456e-42', m[3]); -} diff --git a/tests/mocha/.eslintrc.json b/tests/mocha/.eslintrc.json index 8e3fd2a25..48d7af0e7 100644 --- a/tests/mocha/.eslintrc.json +++ b/tests/mocha/.eslintrc.json @@ -6,6 +6,7 @@ "globals": { "chai": false, "sinon": false, + "assertArrayEquals": true, "assertNull": true, "assertNotNull": true, "assertEquals": true, diff --git a/tests/mocha/utils_test.js b/tests/mocha/utils_test.js index 9db5443ac..2f06958d5 100644 --- a/tests/mocha/utils_test.js +++ b/tests/mocha/utils_test.js @@ -15,6 +15,205 @@ suite('Utils', function() { } }); + suite('tokenizeInterpolation', function() { + test('Basic', function() { + var tokens = Blockly.utils.tokenizeInterpolation(''); + assertArrayEquals('Null interpolation', [], tokens); + + tokens = Blockly.utils.tokenizeInterpolation('Hello'); + assertArrayEquals('No interpolation', ['Hello'], tokens); + + tokens = Blockly.utils.tokenizeInterpolation('Hello%World'); + assertArrayEquals('Unescaped %.', ['Hello%World'], tokens); + + tokens = Blockly.utils.tokenizeInterpolation('Hello%%World'); + assertArrayEquals('Escaped %.', ['Hello%World'], tokens); + + tokens = Blockly.utils.tokenizeInterpolation('Hello %1 World'); + assertArrayEquals('Interpolation.', ['Hello ', 1, ' World'], tokens); + + tokens = Blockly.utils.tokenizeInterpolation('%123Hello%456World%789'); + assertArrayEquals('Interpolations.', [123, 'Hello', 456, 'World', 789], tokens); + + tokens = Blockly.utils.tokenizeInterpolation('%%%x%%0%00%01%'); + assertArrayEquals('Torture interpolations.', ['%%x%0', 0, 1, '%'], tokens); + }); + + test('String table', function() { + Blockly.Msg = Blockly.Msg || {}; + Blockly.Msg.STRING_REF = 'test string'; + var tokens = Blockly.utils.tokenizeInterpolation('%{bky_string_ref}'); + assertArrayEquals('String table reference, lowercase', ['test string'], tokens); + tokens = Blockly.utils.tokenizeInterpolation('%{BKY_STRING_REF}'); + assertArrayEquals('String table reference, uppercase', ['test string'], tokens); + + Blockly.Msg.WITH_PARAM = 'before %1 after'; + tokens = Blockly.utils.tokenizeInterpolation('%{bky_with_param}'); + assertArrayEquals('String table reference, with parameter', ['before ', 1, ' after'], tokens); + + Blockly.Msg.RECURSE = 'before %{bky_string_ref} after'; + tokens = Blockly.utils.tokenizeInterpolation('%{bky_recurse}'); + assertArrayEquals('String table reference, with subreference', ['before test string after'], tokens); + }); + + test('Error cases', function() { + var tokens = Blockly.utils.tokenizeInterpolation('%{bky_undefined}'); + assertArrayEquals('Undefined string table reference', ['%{bky_undefined}'], tokens); + + Blockly.Msg['1'] = 'Will not match'; + tokens = Blockly.utils.tokenizeInterpolation('before %{1} after'); + assertArrayEquals('Invalid initial digit in string table reference', ['before %{1} after'], tokens); + + Blockly.Msg['TWO WORDS'] = 'Will not match'; + tokens = Blockly.utils.tokenizeInterpolation('before %{two words} after'); + assertArrayEquals('Invalid character in string table reference: space', ['before %{two words} after'], tokens); + + Blockly.Msg['TWO-WORDS'] = 'Will not match'; + tokens = Blockly.utils.tokenizeInterpolation('before %{two-words} after'); + assertArrayEquals('Invalid character in string table reference: dash', ['before %{two-words} after'], tokens); + + Blockly.Msg['TWO.WORDS'] = 'Will not match'; + tokens = Blockly.utils.tokenizeInterpolation('before %{two.words} after'); + assertArrayEquals('Invalid character in string table reference: period', ['before %{two.words} after'], tokens); + + Blockly.Msg['AB&C'] = 'Will not match'; + tokens = Blockly.utils.tokenizeInterpolation('before %{ab&c} after'); + assertArrayEquals('Invalid character in string table reference: &', ['before %{ab&c} after'], tokens); + + Blockly.Msg['UNCLOSED'] = 'Will not match'; + tokens = Blockly.utils.tokenizeInterpolation('before %{unclosed'); + assertArrayEquals('String table reference, with parameter', ['before %{unclosed'], tokens); + }); + }); + + test('replaceMessageReferences', function() { + Blockly.Msg = Blockly.Msg || {}; + Blockly.Msg.STRING_REF = 'test string'; + Blockly.Msg.SUBREF = 'subref'; + Blockly.Msg.STRING_REF_WITH_ARG = 'test %1 string'; + Blockly.Msg.STRING_REF_WITH_SUBREF = 'test %{bky_subref} string'; + + var resultString = Blockly.utils.replaceMessageReferences(''); + assertEquals('Empty string produces empty string', '', resultString); + + resultString = Blockly.utils.replaceMessageReferences('%%'); + assertEquals('Escaped %', '%', resultString); + resultString = Blockly.utils.replaceMessageReferences('%%{bky_string_ref}'); + assertEquals('Escaped %', '%{bky_string_ref}', resultString); + + resultString = Blockly.utils.replaceMessageReferences('%a'); + assertEquals('Unrecognized % escape code treated as literal', '%a', resultString); + + resultString = Blockly.utils.replaceMessageReferences('%1'); + assertEquals('Interpolation tokens ignored.', '%1', resultString); + resultString = Blockly.utils.replaceMessageReferences('%1 %2'); + assertEquals('Interpolation tokens ignored.', '%1 %2', resultString); + resultString = Blockly.utils.replaceMessageReferences('before %1 after'); + assertEquals('Interpolation tokens ignored.', 'before %1 after', resultString); + + // Blockly.Msg.STRING_REF cases: + resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref}'); + assertEquals('Message ref dereferenced.', 'test string', resultString); + resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref} after'); + assertEquals('Message ref dereferenced.', 'before test string after', resultString); + + // Blockly.Msg.STRING_REF_WITH_ARG cases: + resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref_with_arg}'); + assertEquals('Message ref dereferenced with argument preserved.', 'test %1 string', resultString); + resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref_with_arg} after'); + assertEquals('Message ref dereferenced with argument preserved.', 'before test %1 string after', resultString); + + // Blockly.Msg.STRING_REF_WITH_SUBREF cases: + resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref_with_subref}'); + assertEquals('Message ref and subref dereferenced.', 'test subref string', resultString); + resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref_with_subref} after'); + assertEquals('Message ref and subref dereferenced.', 'before test subref string after', resultString); + }); + + test('arrayRemove', function() { + var arr = [1, 2, 3, 2]; + assertEquals('Remove Not found', false, Blockly.utils.arrayRemove(arr, 0)); + assertEquals('Remove Not found result', '1,2,3,2', arr.join(',')); + assertEquals('Remove item', true, Blockly.utils.arrayRemove(arr, 2)); + assertEquals('Remove item result', '1,3,2', arr.join(',')); + assertEquals('Remove item again', true, Blockly.utils.arrayRemove(arr, 2)); + assertEquals('Remove item again result', '1,3', arr.join(',')); + }); + + test('XY_REGEX_', function() { + var regex = Blockly.utils.getRelativeXY.XY_REGEX_; + var m; + m = 'INVALID'.match(regex); + assertNull(m); + + m = 'translate(10)'.match(regex); + assertEquals('translate(10), x', '10', m[1]); + assertUndefined('translate(10), y', m[3]); + + m = 'translate(11, 12)'.match(regex); + assertEquals('translate(11, 12), x', '11', m[1]); + assertEquals('translate(11, 12), y', '12', m[3]); + + m = 'translate(13,14)'.match(regex); + assertEquals('translate(13,14), x', '13', m[1]); + assertEquals('translate(13,14), y', '14', m[3]); + + m = 'translate(15 16)'.match(regex); + assertEquals('translate(15 16), x', '15', m[1]); + assertEquals('translate(15 16), y', '16', m[3]); + + m = 'translate(1.23456e+42 0.123456e-42)'.match(regex); + assertEquals('translate(1.23456e+42 0.123456e-42), x', '1.23456e+42', m[1]); + assertEquals('translate(1.23456e+42 0.123456e-42), y', '0.123456e-42', m[3]); + }); + + test('XY_STYLE_REGEX_', function() { + var regex = Blockly.utils.getRelativeXY.XY_STYLE_REGEX_; + var m; + m = 'INVALID'.match(regex); + assertNull(m); + + m = 'transform:translate(9px)'.match(regex); + assertEquals('transform:translate(9px), x', '9', m[1]); + assertUndefined('transform:translate(9px), y', m[3]); + + m = 'transform:translate3d(10px)'.match(regex); + assertEquals('transform:translate3d(10px), x', '10', m[1]); + assertUndefined('transform:translate(10px), y', m[3]); + + m = 'transform: translate(11px, 12px)'.match(regex); + assertEquals('transform: translate(11px, 12px), x', '11', m[1]); + assertEquals('transform: translate(11px, 12px), y', '12', m[3]); + + m = 'transform: translate(13px,14px)'.match(regex); + assertEquals('transform: translate(13px,14px), x', '13', m[1]); + assertEquals('transform: translate(13px,14px), y', '14', m[3]); + + m = 'transform: translate(15px 16px)'.match(regex); + assertEquals('transform: translate(15px 16px), x', '15', m[1]); + assertEquals('transform: translate(15px 16px), y', '16', m[3]); + + m = 'transform: translate(1.23456e+42px 0.123456e-42px)'.match(regex); + assertEquals('transform: translate(1.23456e+42px 0.123456e-42px), x', '1.23456e+42', m[1]); + assertEquals('transform: translate(1.23456e+42px 0.123456e-42px), y', '0.123456e-42', m[3]); + + m = 'transform:translate3d(20px, 21px, 22px)'.match(regex); + assertEquals('transform:translate3d(20px, 21px, 22px), x', '20', m[1]); + assertEquals('transform:translate3d(20px, 21px, 22px), y', '21', m[3]); + + m = 'transform:translate3d(23px,24px,25px)'.match(regex); + assertEquals('transform:translate3d(23px,24px,25px), x', '23', m[1]); + assertEquals('transform:translate3d(23px,24px,25px), y', '24', m[3]); + + m = 'transform:translate3d(26px 27px 28px)'.match(regex); + assertEquals('transform:translate3d(26px 27px 28px), x', '26', m[1]); + assertEquals('transform:translate3d(26px 27px 28px), y', '27', m[3]); + + m = 'transform:translate3d(1.23456e+42px 0.123456e-42px 42px)'.match(regex); + assertEquals('transform:translate3d(1.23456e+42px 0.123456e-42px 42px), x', '1.23456e+42', m[1]); + assertEquals('transform:translate3d(1.23456e+42px 0.123456e-42px 42px), y', '0.123456e-42', m[3]); + }); + suite('DOM', function() { test('addClass', function() { var p = document.createElement('p'); @@ -59,6 +258,13 @@ suite('Utils', function() { }); suite('String', function() { + test('starts with', function() { + assertEquals('Does not start with', false, Blockly.utils.string.startsWith('123', '2')); + assertEquals('Start with', true, Blockly.utils.string.startsWith('123', '12')); + assertEquals('Start with empty string 1', true, Blockly.utils.string.startsWith('123', '')); + assertEquals('Start with empty string 2', true, Blockly.utils.string.startsWith('', '')); + }); + test('shortest string length', function() { var len = Blockly.utils.string.shortestStringLength('one,two,three,four,five'.split(',')); assertEquals('Length of "one"', 3, len); @@ -92,5 +298,48 @@ suite('Utils', function() { len = Blockly.utils.string.commonWordPrefix('turn\u00A0left,turn\u00A0right'.split(',')); assertEquals('No prefix due to \\u00A0', 0, len); }); + + test('comment word suffix', function() { + var len = Blockly.utils.string.commonWordSuffix('one,two,three,four,five'.split(',')); + assertEquals('No suffix', 0, len); + len = Blockly.utils.string.commonWordSuffix('oneX,twoX,threeX,fourX,fiveX'.split(',')); + assertEquals('No word suffix', 0, len); + len = Blockly.utils.string.commonWordSuffix('abc de,abc de,abc de,abc de'.split(',')); + assertEquals('Full equality', 6, len); + len = Blockly.utils.string.commonWordSuffix('Xabc de,Yabc de'.split(',')); + assertEquals('One word suffix', 3, len); + len = Blockly.utils.string.commonWordSuffix('abc de,Yabc de'.split(',')); + assertEquals('Overflow no', 3, len); + len = Blockly.utils.string.commonWordSuffix('abc de,Y abc de'.split(',')); + assertEquals('Overflow yes', 6, len); + len = Blockly.utils.string.commonWordSuffix(['Hello World']); + assertEquals('List of one', 11, len); + len = Blockly.utils.string.commonWordSuffix([]); + assertEquals('Empty list', 0, len); + }); + }); + + suite('Math', function() { + test('toRadians', function() { + var quarter = Math.PI / 2; + assertEquals('-90', -quarter, Blockly.utils.math.toRadians(-90)); + assertEquals('0', 0, Blockly.utils.math.toRadians(0)); + assertEquals('90', quarter, Blockly.utils.math.toRadians(90)); + assertEquals('180', 2 * quarter, Blockly.utils.math.toRadians(180)); + assertEquals('270', 3 * quarter, Blockly.utils.math.toRadians(270)); + assertEquals('360', 4 * quarter, Blockly.utils.math.toRadians(360)); + assertEquals('450', 5 * quarter, Blockly.utils.math.toRadians(360 + 90)); + }); + + test('toDegrees', function() { + var quarter = Math.PI / 2; + assertEquals('-90', -90, Blockly.utils.math.toDegrees(-quarter)); + assertEquals('0', 0, Blockly.utils.math.toDegrees(0)); + assertEquals('90', 90, Blockly.utils.math.toDegrees(quarter)); + assertEquals('180', 180, Blockly.utils.math.toDegrees(2 * quarter)); + assertEquals('270', 270, Blockly.utils.math.toDegrees(3 * quarter)); + assertEquals('360', 360, Blockly.utils.math.toDegrees(4 * quarter)); + assertEquals('450', 360 + 90, Blockly.utils.math.toDegrees(5 * quarter)); + }); }); }); From e0521265b246d2a082f45809a27bcaf77c1838c4 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Tue, 14 Apr 2020 13:22:06 -0700 Subject: [PATCH 013/139] Fixing event tests and removing duplicate tests. (#3810) --- tests/jsunit/event_test.js | 443 ------------------------------------- tests/mocha/event_test.js | 58 +++-- 2 files changed, 26 insertions(+), 475 deletions(-) diff --git a/tests/jsunit/event_test.js b/tests/jsunit/event_test.js index 1e2414a91..9a1b2a19a 100644 --- a/tests/jsunit/event_test.js +++ b/tests/jsunit/event_test.js @@ -51,76 +51,6 @@ function eventTest_tearDownWithMockBlocks() { delete Blockly.Blocks.field_variable_test_block; } -function test_block_base_constructor() { - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, '1'); - try { - var block = createSimpleTestBlock(workspace); - - // Here's the event we care about. - var event = new Blockly.Events.BlockBase(block); - assertUndefined(event.varId); - checkExactEventValues(event, {'blockId': '1', 'workspaceId': workspace.id, - 'group': '', 'recordUndo': true}); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_var_base_constructor() { - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, '1'); - try { - var variable = workspace.createVariable('name1', 'type1', 'id1'); - - var event = new Blockly.Events.VarBase(variable); - assertUndefined(event.blockId); - checkExactEventValues(event, {'varId': 'id1', - 'workspaceId': workspace.id, 'group': '', 'recordUndo': true}); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_abstract_constructor() { - eventTest_setUpWithMockBlocks(); - try { - var event = new Blockly.Events.Abstract(); - assertUndefined(event.blockId); - assertUndefined(event.workspaceId); - assertUndefined(event.varId); - checkExactEventValues(event, {'group': '', 'recordUndo': true}); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -// Test util -function checkCreateEventValues(event, block, ids, type) { - var expected_xml = Blockly.Xml.domToText(Blockly.Xml.blockToDom(block)); - var result_xml = Blockly.Xml.domToText(event.xml); - assertEquals(expected_xml, result_xml); - isEqualArrays(ids, event.ids); - assertEquals(type, event.type); -} - -// Test util -function checkDeleteEventValues(event, block, ids, type) { - var expected_xml = Blockly.Xml.domToText(Blockly.Xml.blockToDom(block)); - var result_xml = Blockly.Xml.domToText(event.oldXml); - assertEquals(expected_xml, result_xml); - isEqualArrays(ids, event.ids); - assertEquals(type, event.type); -} - -// Test util -function checkExactEventValues(event, values) { - var keys = Object.keys(values); - for (var i = 0, field; field = keys[i]; i++) { - assertEquals(values[field], event[field]); - } -} - // Test util function createSimpleTestBlock(workspace) { // Disable events while constructing the block: this is a test of the @@ -131,379 +61,6 @@ function createSimpleTestBlock(workspace) { return block; } -function test_create_constructor() { - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1']); - try { - var block = createSimpleTestBlock(workspace); - - var event = new Blockly.Events.Create(block); - checkCreateEventValues(event, block, ['1'], 'create'); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_blockCreate_constructor() { - // expect that blockCreate behaves the same as create. - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1']); - try { - var block = createSimpleTestBlock(workspace); - - var event = new Blockly.Events.BlockCreate(block); - checkCreateEventValues(event, block, ['1'], 'create'); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_delete_constructor() { - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1']); - try { - var block = createSimpleTestBlock(workspace); - var event = new Blockly.Events.Delete(block); - checkDeleteEventValues(event, block, ['1'], 'delete'); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_blockDelete_constructor() { - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1']); - try { - var block = createSimpleTestBlock(workspace); - block.setCommentText('test comment'); - var event = new Blockly.Events.BlockDelete(block); - checkDeleteEventValues(event, block, ['1'], 'delete'); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_change_constructor() { - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1']); - try { - Blockly.Events.disable(); - var block = new Blockly.Block(workspace, 'field_variable_test_block'); - Blockly.Events.enable(); - - var event = new Blockly.Events.Change(block, 'field', 'VAR', 'id1', 'id2'); - checkExactEventValues(event, {'element': 'field', 'name': 'VAR', - 'oldValue': 'id1', 'newValue': 'id2', 'type': 'change'}); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_blockChange_constructor() { - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1']); - try { - Blockly.Events.disable(); - var block = new Blockly.Block(workspace, 'field_variable_test_block'); - Blockly.Events.enable(); - - var event = new Blockly.Events.BlockChange(block, 'field', 'VAR', 'id1', - 'id2'); - checkExactEventValues(event, {'element': 'field', 'name': 'VAR', - 'oldValue': 'id1', 'newValue': 'id2', 'type': 'change'}); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_move_constructorCoordinate() { - // Expect the oldCoordinate to be set. - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '2']); - try { - var block1 = createSimpleTestBlock(workspace); - var coordinate = new Blockly.utils.Coordinate(3, 4); - block1.xy_ = coordinate; - - var event = new Blockly.Events.Move(block1); - checkExactEventValues(event, {'oldCoordinate': coordinate, - 'type': 'move'}); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_move_constructoroldParentId() { - // Expect the oldParentId to be set but not the oldCoordinate to be set. - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '2']); - try { - var block1 = createSimpleTestBlock(workspace); - var block2 = createSimpleTestBlock(workspace); - block1.parentBlock_ = block2; - block1.xy_ = new Blockly.utils.Coordinate(3, 4); - - var event = new Blockly.Events.Move(block1); - checkExactEventValues(event, {'oldCoordinate': undefined, - 'oldParentId': '2', 'type': 'move'}); - block1.parentBlock_ = null; - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_blockMove_constructorCoordinate() { - // Expect the oldCoordinate to be set. - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '2']); - try { - var block1 = createSimpleTestBlock(workspace); - var coordinate = new Blockly.utils.Coordinate(3, 4); - block1.xy_ = coordinate; - - var event = new Blockly.Events.BlockMove(block1); - checkExactEventValues(event, {'oldCoordinate': coordinate, - 'type': 'move'}); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_blockMove_constructoroldParentId() { - // Expect the oldParentId to be set but not the oldCoordinate to be set. - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '2']); - try { - var block1 = createSimpleTestBlock(workspace); - var block2 = createSimpleTestBlock(workspace); - block1.parentBlock_ = block2; - block1.xy_ = new Blockly.utils.Coordinate(3, 4); - - var event = new Blockly.Events.BlockMove(block1); - checkExactEventValues(event, {'oldCoordinate': undefined, - 'oldParentId': '2', 'type': 'move'}); - block1.parentBlock_ = null; - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_uiEvent_constructor_null() { - try { - Blockly.Events.setGroup('testGroup'); - var event = new Blockly.Events.Ui(null, 'foo', 'bar', 'baz'); - checkExactEventValues(event, - { - 'blockId': null, - 'workspaceId': null, - 'type': 'ui', - 'oldValue': 'bar', - 'newValue': 'baz', - 'element': 'foo', - 'recordUndo': false, - 'group': 'testGroup' - } - ); - } finally { - Blockly.Events.setGroup(false); - } -} - -function test_uiEvent_constructor_block() { - eventTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1']); - try { - var block1 = createSimpleTestBlock(workspace); - Blockly.Events.setGroup('testGroup'); - var event = new Blockly.Events.Ui(block1, 'foo', 'bar', 'baz'); - checkExactEventValues(event, - { - 'blockId': '1', - 'workspaceId': workspace.id, - 'type': 'ui', - 'oldValue': 'bar', - 'newValue': 'baz', - 'element': 'foo', - 'recordUndo': false, - 'group': 'testGroup' - } - ); - } finally { - Blockly.Events.setGroup(false); - eventTest_tearDownWithMockBlocks(); - } -} - -function test_varCreate_constructor() { - eventTest_setUp(); - try { - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarCreate(variable); - checkExactEventValues(event, {'varName': 'name1', 'varType': 'type1', - 'type': 'var_create'}); - } finally { - eventTest_tearDown(); - } -} - -function test_varCreate_toJson() { - eventTest_setUp(); - try { - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarCreate(variable); - var json = event.toJson(); - var expectedJson = ({type: "var_create", varId: "id1", varType: "type1", - varName: "name1"}); - - assertEquals(JSON.stringify(expectedJson), JSON.stringify(json)); - } finally { - eventTest_tearDown(); - } -} - -function test_varCreate_fromJson() { - eventTest_setUp(); - try { - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarCreate(variable); - var event2 = new Blockly.Events.VarCreate(null); - var json = event.toJson(); - event2.fromJson(json); - - assertEquals(JSON.stringify(json), JSON.stringify(event2.toJson())); - } finally { - eventTest_tearDown(); - } -} - -function test_varCreate_runForward() { - eventTest_setUp(); - var json = {type: "var_create", varId: "id1", varType: "type1", - varName: "name1"}; - var event = Blockly.Events.fromJson(json, workspace); - assertNull(workspace.getVariableById('id1')); - event.run(true); - checkVariableValues(workspace, 'name1', 'type1', 'id1'); - eventTest_tearDown(); -} - -function test_varCreate_runBackwards() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarCreate(variable); - assertNotNull(workspace.getVariableById('id1')); - event.run(false); - assertNull(workspace.getVariableById('id1')); - eventTest_tearDown(); -} - -function test_varDelete_constructor() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarDelete(variable); - checkExactEventValues(event, {'varName': 'name1', 'varType': 'type1', - 'varId':'id1', 'type': 'var_delete'}); - eventTest_tearDown(); -} - -function test_varDelete_toJson() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarDelete(variable); - var json = event.toJson(); - var expectedJson = ({type: "var_delete", varId: "id1", varType: "type1", - varName: "name1"}); - - assertEquals(JSON.stringify(expectedJson), JSON.stringify(json)); - eventTest_tearDown(); -} - -function test_varDelete_fromJson() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarDelete(variable); - var event2 = new Blockly.Events.VarDelete(null); - var json = event.toJson(); - event2.fromJson(json); - - assertEquals(JSON.stringify(json), JSON.stringify(event2.toJson())); - eventTest_tearDown(); -} - -function test_varDelete_runForwards() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarDelete(variable); - assertNotNull(workspace.getVariableById('id1')); - event.run(true); - assertNull(workspace.getVariableById('id1')); - eventTest_tearDown(); -} - -function test_varDelete_runBackwards() { - eventTest_setUp(); - var json = {type: "var_delete", varId: "id1", varType: "type1", - varName: "name1"}; - var event = Blockly.Events.fromJson(json, workspace); - assertNull(workspace.getVariableById('id1')); - event.run(false); - checkVariableValues(workspace, 'name1', 'type1', 'id1'); - eventTest_tearDown(); -} - -function test_varRename_constructor() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarRename(variable, 'name2'); - checkExactEventValues(event, {'varId': 'id1', 'oldName': 'name1', - 'newName': 'name2', 'type': 'var_rename'}); - eventTest_tearDown(); -} - -function test_varRename_toJson() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarRename(variable, 'name2'); - var json = event.toJson(); - var expectedJson = ({type: "var_rename", varId: "id1", oldName: "name1", - newName: "name2"}); - - assertEquals(JSON.stringify(expectedJson), JSON.stringify(json)); - eventTest_tearDown(); -} - -function test_varRename_fromJson() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarRename(variable, ''); - var event2 = new Blockly.Events.VarRename(null); - var json = event.toJson(); - event2.fromJson(json); - - assertEquals(JSON.stringify(json), JSON.stringify(event2.toJson())); - eventTest_tearDown(); -} - -function test_varRename_runForward() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarRename(variable, 'name2'); - event.run(true); - assertNull(workspace.getVariable('name1')); - checkVariableValues(workspace, 'name2', 'type1', 'id1'); - eventTest_tearDown(); -} - -function test_varBackard_runForward() { - eventTest_setUp(); - var variable = workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarRename(variable, 'name2'); - event.run(false); - assertNull(workspace.getVariable('name2')); - checkVariableValues(workspace, 'name1', 'type1', 'id1'); - eventTest_tearDown(); -} - function test_events_filter() { eventTest_setUpWithMockBlocks(); try { diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index 4b157925f..86af27f48 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -58,6 +58,16 @@ suite('Events', function() { assertEquals(type, event.type); } + function createSimpleTestBlock(workspace, opt_prototypeName) { + // Disable events while constructing the block: this is a test of the + // Blockly.Event constructors, not the block constructor. + Blockly.Events.disable(); + var block = new Blockly.Block( + workspace, opt_prototypeName || 'simple_test_block'); + Blockly.Events.enable(); + return block; + } + suite('Constructors', function() { test('Abstract', function() { var event = new Blockly.Events.Abstract(); @@ -87,12 +97,7 @@ suite('Events', function() { setup(function() { this.FAKE_ID = 'hedgehog'; sinon.stub(Blockly.utils, "genUid").returns(this.FAKE_ID); - - // Disable events while constructing the block: this is a test of the - // Blockly.Event constructors, not the block constructor. - Blockly.Events.disable(); - this.block = new Blockly.Block(this.workspace, 'simple_test_block'); - Blockly.Events.enable(); + this.block = createSimpleTestBlock(this.workspace); sinon.restore(); }); @@ -169,9 +174,7 @@ suite('Events', function() { suite('Move by parent', function() { setup(function() { sinon.stub(Blockly.utils, "genUid").returns("parent"); - Blockly.Events.disable(); - this.parentBlock = new Blockly.Block(this.workspace, 'simple_test_block'); - Blockly.Events.enable(); + this.parentBlock = createSimpleTestBlock(this.workspace); sinon.restore(); this.block.parentBlock_ = this.parentBlock; @@ -201,15 +204,7 @@ suite('Events', function() { suite('With variable getter blocks', function() { setup(function() { - // Disable events while constructing the block: this is a test of the - // Blockly.Event constructors, not the block constructor. - Blockly.Events.disable(); - this.block = new Blockly.Block(this.workspace, 'field_variable_test_block'); - Blockly.Events.enable(); - }); - - teardown(function() { - + this.block = createSimpleTestBlock(this.workspace, 'field_variable_test_block'); }); test('Change', function() { @@ -304,8 +299,7 @@ suite('Events', function() { suite('toJson', function() { test('Var create', function() { - var variable = this.workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarCreate(variable); + var event = new Blockly.Events.VarCreate(this.variable); var json = event.toJson(); var expectedJson = ({type: "var_create", varId: "id1", varType: "type1", varName: "name1"}); @@ -332,14 +326,15 @@ suite('Events', function() { }); }); - suite.skip('Run Forward', function() { + suite('Run Forward', function() { test('Var create', function() { - var json = {type: "var_create", varId: "id1", varType: "type1", - varName: "name1"}; + var json = {type: "var_create", varId: "id2", varType: "type2", + varName: "name2"}; var event = Blockly.Events.fromJson(json, this.workspace); - assertNull(this.workspace.getVariableById('id1')); + var x = this.workspace.getVariableById('id2'); + assertNull(x); event.run(true); - checkVariableValues(this.workspace, 'name1', 'type1', 'id1'); + checkVariableValues(this.workspace, 'name2', 'type2', 'id2'); }); test('Var delete', function() { @@ -356,21 +351,20 @@ suite('Events', function() { checkVariableValues(this.workspace, 'name2', 'type1', 'id1'); }); }); - suite.skip('Run Backward', function() { + suite('Run Backward', function() { test('Var create', function() { - var variable = this.workspace.createVariable('name1', 'type1', 'id1'); - var event = new Blockly.Events.VarCreate(variable); + var event = new Blockly.Events.VarCreate(this.variable); assertNotNull(this.workspace.getVariableById('id1')); event.run(false); }); test('Var delete', function() { - var json = {type: "var_delete", varId: "id1", varType: "type1", - varName: "name1"}; + var json = {type: "var_delete", varId: "id2", varType: "type2", + varName: "name2"}; var event = Blockly.Events.fromJson(json, this.workspace); - assertNull(this.workspace.getVariableById('id1')); + assertNull(this.workspace.getVariableById('id2')); event.run(false); - checkVariableValues(this.workspace, 'name1', 'type1', 'id1'); + checkVariableValues(this.workspace, 'name2', 'type2', 'id2'); }); test('Var rename', function() { From 8a2fe6411f65141978e2a8236ca8ed30976c456b Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Tue, 14 Apr 2020 14:10:10 -0700 Subject: [PATCH 014/139] Converting xml tests to mocha. (#3818) * Converting xml tests to mocha. * Remove async * Updating no variable test. * Addressing PR comments. --- tests/jsunit/index.html | 1 - tests/jsunit/xml_test.js | 375 ------------------------- tests/mocha/xml_test.js | 583 +++++++++++++++++++++++++-------------- 3 files changed, 381 insertions(+), 578 deletions(-) delete mode 100644 tests/jsunit/xml_test.js diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index da931cf70..29a3e4d51 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -29,7 +29,6 @@ - diff --git a/tests/jsunit/xml_test.js b/tests/jsunit/xml_test.js deleted file mode 100644 index 117cd4ed6..000000000 --- a/tests/jsunit/xml_test.js +++ /dev/null @@ -1,375 +0,0 @@ -/** - * @license - * Copyright 2014 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - -var mockControl_; -var workspace; -var XML_TEXT = ['', - ' ', - ' ', - ' ', - ' 10', - ' ', - ' ', - ' ', - ' ', - ' item', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' Hello', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ''].join('\n'); - -function xmlTest_setUp() { - workspace = new Blockly.Workspace(); -} - -function xmlTest_setUpWithMockBlocks() { - xmlTest_setUp(); - Blockly.defineBlocksWithJsonArray([{ - 'type': 'field_variable_test_block', - 'message0': '%1', - 'args0': [ - { - 'type': 'field_variable', - 'name': 'VAR', - 'variable': 'item' - } - ] - }]); -} - -function xmlTest_tearDown() { - if (mockControl_) { - mockControl_.restore(); - } - workspace.dispose(); -} - -function xmlTest_tearDownWithMockBlocks() { - xmlTest_tearDown(); - delete Blockly.Blocks.field_variable_test_block; -} - -/** - * 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('textContent', text, fieldDom.textContent); - assertEquals('name', name, fieldDom.getAttribute('name')); - assertNull('id', fieldDom.getAttribute('id')); - assertNull('variabletype', 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_checkVariableFieldDomValues(fieldDom, name, type, id, text) { - assertEquals('name', name, fieldDom.getAttribute('name')); - assertEquals('variabletype', type, fieldDom.getAttribute('variabletype')); - assertEquals('id', id, fieldDom.getAttribute('id')); - assertEquals('textContent', text, fieldDom.textContent); -} - -/** - * Check the values of the variable DOM. - * @param {!Element} variableDom The XML DOM 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(variableDom, type, id, text) { - assertEquals('type', type, variableDom.getAttribute('type')); - assertEquals('id', id, variableDom.getAttribute('id')); - assertEquals('textContent', text, variableDom.textContent); -} - -function test_textToDom() { - var dom = Blockly.Xml.textToDom(XML_TEXT); - assertEquals('XML tag', 'xml', dom.nodeName); - assertEquals('Block tags', 6, dom.getElementsByTagName('block').length); -} - -function test_domToText() { - var dom = Blockly.Xml.textToDom(XML_TEXT); - var text = Blockly.Xml.domToText(dom); - assertEquals('Round trip', XML_TEXT.replace(/\s+/g, ''), - text.replace(/\s+/g, '')); -} - -function test_domToWorkspace_BackwardCompatibility() { - // Expect that workspace still loads without serialized variables. - xmlTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '1']); - try { - var dom = Blockly.Xml.textToDom( - '' + - ' ' + - ' name1' + - ' ' + - ''); - Blockly.Xml.domToWorkspace(dom, workspace); - assertEquals('Block count', 1, workspace.getAllBlocks(false).length); - checkVariableValues(workspace, 'name1', '', '1'); - } finally { - xmlTest_tearDownWithMockBlocks(); - } -} - -function test_domToWorkspace_VariablesAtTop() { - // Expect that unused variables are preserved. - xmlTest_setUpWithMockBlocks(); - try { - var dom = Blockly.Xml.textToDom( - '' + - ' ' + - ' name1' + - ' name2' + - ' name3' + - ' ' + - ' ' + - ' name3' + - ' ' + - ''); - Blockly.Xml.domToWorkspace(dom, workspace); - assertEquals('Block count', 1, workspace.getAllBlocks(false).length); - checkVariableValues(workspace, 'name1', 'type1', 'id1'); - checkVariableValues(workspace, 'name2', 'type2', 'id2'); - checkVariableValues(workspace, 'name3', '', 'id3'); - } finally { - xmlTest_tearDownWithMockBlocks(); - } -} - -function test_domToWorkspace_VariablesAtTop_DuplicateVariablesTag() { - // Expect thrown Error because of duplicate 'variables' tag. - xmlTest_setUpWithMockBlocks(); - try { - var dom = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ' ' + - ' ' + - ''); - Blockly.Xml.domToWorkspace(dom, workspace); - fail(); - } - catch (e) { - // expected - } finally { - xmlTest_tearDownWithMockBlocks(); - } -} - -function test_domToWorkspace_VariablesAtTop_MissingType() { - // Expect thrown error when a variable tag is missing the type attribute. - workspace = new Blockly.Workspace(); - try { - var dom = Blockly.Xml.textToDom( - '' + - ' ' + - ' name1' + - ' ' + - ' ' + - ' name3' + - ' ' + - ''); - Blockly.Xml.domToWorkspace(dom, workspace); - fail(); - } catch (e) { - // expected - } finally { - workspace.dispose(); - } -} - -function test_domToWorkspace_VariablesAtTop_MismatchBlockType() { - // Expect thrown error when the serialized type of a variable does not match - // the type of a variable field that references it. - xmlTest_setUpWithMockBlocks(); - try { - var dom = Blockly.Xml.textToDom( - '' + - ' ' + - ' name1' + - ' ' + - ' ' + - ' name1' + - ' ' + - ''); - Blockly.Xml.domToWorkspace(dom, workspace); - fail(); - } catch (e) { - // expected - } finally { - xmlTest_tearDownWithMockBlocks(); - } -} - -function test_domToPrettyText() { - var dom = Blockly.Xml.textToDom(XML_TEXT); - var text = Blockly.Xml.domToPrettyText(dom); - assertEquals('Round trip', XML_TEXT.replace(/\s+/g, ''), - text.replace(/\s+/g, '')); -} - -/** - * Tests the that appendDomToWorkspace works in a headless mode. - * Also see test_appendDomToWorkspace() in workspace_svg_test.js. - */ -function test_appendDomToWorkspace() { - Blockly.Blocks.test_block = { - init: function() { - this.jsonInit({ - message0: 'test', - }); - } - }; - - try { - var dom = Blockly.Xml.textToDom( - '' + - ' ' + - ' ' + - ''); - workspace = new Blockly.Workspace(); - Blockly.Xml.appendDomToWorkspace(dom, workspace); - assertEquals('Block count', 1, workspace.getAllBlocks(false).length); - var newBlockIds = Blockly.Xml.appendDomToWorkspace(dom, workspace); - assertEquals('Block count', 2, workspace.getAllBlocks(false).length); - assertEquals('Number of new block ids',1,newBlockIds.length); - } finally { - delete Blockly.Blocks.test_block; - workspace.dispose(); - } -} - -function test_blockToDom_fieldToDom_defaultCase() { - xmlTest_setUpWithMockBlocks(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '1']); - try { - workspace.createVariable('name1'); - - Blockly.Events.disable(); - var block = new Blockly.Block(workspace, 'field_variable_test_block'); - block.inputList[0].fieldRow[0].setValue('1'); - Blockly.Events.enable(); - - var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - // Expect type is null and ID is '1' since we don't specify type and ID. - xmlTest_checkVariableFieldDomValues(resultFieldDom, 'VAR', null, '1', - 'name1'); - } finally { - 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(); -} - -function test_variablesToDom_oneVariable() { - xmlTest_setUp(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1']); - - workspace.createVariable('name1'); - var resultDom = Blockly.Xml.variablesToDom(workspace.getAllVariables()); - assertEquals(1, resultDom.children.length); - var resultVariableDom = resultDom.children[0]; - assertEquals('name1', resultVariableDom.textContent); - assertEquals(null, resultVariableDom.getAttribute('type')); - assertEquals('1', resultVariableDom.getAttribute('id')); - xmlTest_tearDown(); -} - -function test_variablesToDom_twoVariables_oneBlock() { - xmlTest_setUpWithMockBlocks(); - - workspace.createVariable('name1', '', 'id1'); - workspace.createVariable('name2', 'type2', 'id2'); - // If events are enabled during block construction, it will create a default - // variable. - Blockly.Events.disable(); - var block = new Blockly.Block(workspace, 'field_variable_test_block'); - block.inputList[0].fieldRow[0].setValue('id1'); - Blockly.Events.enable(); - - var resultDom = Blockly.Xml.variablesToDom(workspace.getAllVariables()); - assertEquals(2, resultDom.children.length); - xmlTest_checkVariableDomValues(resultDom.children[0], null, 'id1', - 'name1'); - xmlTest_checkVariableDomValues(resultDom.children[1], 'type2', 'id2', - 'name2'); - xmlTest_tearDownWithMockBlocks(); -} - -function test_variablesToDom_noVariables() { - xmlTest_setUp(); - workspace.createVariable('name1'); - var resultDom = Blockly.Xml.variablesToDom(workspace.getAllVariables()); - assertEquals(1, resultDom.children.length); - xmlTest_tearDown(); -} - -function test_variableFieldXml_caseSensitive() { - var id = 'testId'; - var type = 'testType'; - var name = 'testName'; - - var mockVariableModel = { - type: type, - name: name, - getId: function() { - return id; - } - }; - - var generatedXml = Blockly.Xml.domToText( - Blockly.Variables.generateVariableFieldDom(mockVariableModel)); - var goldenXml = - '' + name + ''; - assertEquals(goldenXml, generatedXml); -} diff --git a/tests/mocha/xml_test.js b/tests/mocha/xml_test.js index 51b39e684..05635de73 100644 --- a/tests/mocha/xml_test.js +++ b/tests/mocha/xml_test.js @@ -5,19 +5,35 @@ */ suite('XML', function() { - var assertSimpleField = function(fieldDom, name, text) { + var assertSimpleFieldDom = function(fieldDom, name, text) { assertEquals(text, fieldDom.textContent); assertEquals(name, fieldDom.getAttribute('name')); }; - var assertNonSerializingField = function(fieldDom) { + var assertNonSerializingFieldDom = function(fieldDom) { assertEquals(undefined, fieldDom.childNodes[0]); }; - var assertVariableField = function(fieldDom, name, type, id, text) { - assertEquals(name, fieldDom.getAttribute('name')); + var assertNonVariableField = function(fieldDom, name, text) { + assertSimpleFieldDom(fieldDom, name, text); + assertNull('id', fieldDom.getAttribute('id')); + assertNull('variabletype', fieldDom.getAttribute('variabletype')); + }; + var assertVariableDomField = function(fieldDom, name, type, id, text) { + assertSimpleFieldDom(fieldDom, name, text); assertEquals(type, fieldDom.getAttribute('variabletype')); assertEquals(id, fieldDom.getAttribute('id')); + }; + var assertVariableDom = function(fieldDom, type, id, text) { + assertEquals(type, fieldDom.getAttribute('type')); + assertEquals(id, fieldDom.getAttribute('id')); assertEquals(text, fieldDom.textContent); }; + var assertVariableValues = function(container, name, type, id) { + var variable = container.getVariableById(id); + assertNotUndefined(variable); + assertEquals(name, variable.name); + assertEquals(type, variable.type); + assertEquals(id, variable.getId()); + }; setup(function() { Blockly.defineBlocksWithJsonArray([ { @@ -26,11 +42,50 @@ suite('XML', function() { "args0": [] }, ]); + this.blockTypes_ = ['empty_block']; + this.complexXmlText = [ + '', + ' ', + ' ', + ' ', + ' 10', + ' ', + ' ', + ' ', + ' ', + ' item', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' Hello', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ''].join('\n'); }); teardown(function() { - delete Blockly.Blocks['empty_block']; + for (var i = 0; i < this.blockTypes_.length; i++) { + delete Blockly.Blocks[this.blockTypes_[i]]; + } + this.blockTypes_.length = 0; + sinon.restore(); }); - suite('Serialization', function() { + suite('textToDom', function() { + test('Basic', function() { + var dom = Blockly.Xml.textToDom(this.complexXmlText); + assertEquals('XML tag', 'xml', dom.nodeName); + assertEquals('Block tags', 6, dom.getElementsByTagName('block').length); + }); + }); + suite('blockToDom', function() { setup(function() { this.workspace = new Blockly.Workspace(); }); @@ -50,11 +105,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_angle_test_block'); var block = new Blockly.Block(this.workspace, 'field_angle_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertSimpleField(resultFieldDom, 'ANGLE', '90'); - delete Blockly.Blocks['field_angle_test_block']; + assertNonVariableField(resultFieldDom, 'ANGLE', '90'); }); test('Checkbox', function() { Blockly.defineBlocksWithJsonArray([{ @@ -68,11 +123,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_checkbox_test_block'); var block = new Blockly.Block(this.workspace, 'field_checkbox_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertSimpleField(resultFieldDom, 'CHECKBOX', 'TRUE'); - delete Blockly.Blocks['field_checkbox_test_block']; + assertNonVariableField(resultFieldDom, 'CHECKBOX', 'TRUE'); }); test('Colour', function() { Blockly.defineBlocksWithJsonArray([{ @@ -86,11 +141,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_colour_test_block'); var block = new Blockly.Block(this.workspace, 'field_colour_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertSimpleField(resultFieldDom, 'COLOUR', '#000099'); - delete Blockly.Blocks['field_colour_test_block']; + assertNonVariableField(resultFieldDom, 'COLOUR', '#000099'); }); /* If you want to run date tests add the date picker here: * https://github.com/google/blockly/blob/master/core/blockly.js#L41 @@ -108,11 +163,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_date_test_block'); var block = new Blockly.Block(this.workspace, 'field_date_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertSimpleField(resultFieldDom, 'DATE', '2020-02-20'); - delete Blockly.Blocks['field_date_test_block']; + assertNonVariableField(resultFieldDom, 'DATE', '2020-02-20'); }); test('Dropdown', function() { Blockly.defineBlocksWithJsonArray([{ @@ -139,11 +194,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_dropdown_test_block'); var block = new Blockly.Block(this.workspace, 'field_dropdown_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertSimpleField(resultFieldDom, 'DROPDOWN', 'A'); - delete Blockly.Blocks['field_dropdown_test_block']; + assertNonVariableField(resultFieldDom, 'DROPDOWN', 'A'); }); test('Image', function() { Blockly.defineBlocksWithJsonArray([{ @@ -160,11 +215,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_image_test_block'); var block = new Blockly.Block(this.workspace, 'field_image_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block); - assertNonSerializingField(resultFieldDom); - delete Blockly.Blocks['field_image_test_block']; + assertNonSerializingFieldDom(resultFieldDom); }); test('Label', function() { Blockly.defineBlocksWithJsonArray([{ @@ -178,11 +233,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_label_test_block'); var block = new Blockly.Block(this.workspace, 'field_label_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block); - assertNonSerializingField(resultFieldDom); - delete Blockly.Blocks['field_label_test_block']; + assertNonSerializingFieldDom(resultFieldDom); }); test('Label Serializable', function() { Blockly.defineBlocksWithJsonArray([{ @@ -196,11 +251,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_label_serializable_test_block'); var block = new Blockly.Block(this.workspace, 'field_label_serializable_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertSimpleField(resultFieldDom, 'LABEL', 'default'); - delete Blockly.Blocks['field_label_serializable_test_block']; + assertNonVariableField(resultFieldDom, 'LABEL', 'default'); }); test('Number', function() { Blockly.defineBlocksWithJsonArray([{ @@ -214,11 +269,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_number_test_block'); var block = new Blockly.Block(this.workspace, 'field_number_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertSimpleField(resultFieldDom, 'NUMBER', '97'); - delete Blockly.Blocks['field_number_test_block']; + assertNonVariableField(resultFieldDom, 'NUMBER', '97'); }); test('Text Input', function() { Blockly.defineBlocksWithJsonArray([{ @@ -232,10 +287,11 @@ suite('XML', function() { } ], }]); + this.blockTypes_.push('field_text_input_test_block'); var block = new Blockly.Block(this.workspace, 'field_text_input_test_block'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertSimpleField(resultFieldDom, 'TEXT', 'default'); + assertNonVariableField(resultFieldDom, 'TEXT', 'default'); }); suite('Variable Fields', function() { setup(function() { @@ -250,9 +306,7 @@ suite('XML', function() { } ] }]); - }); - teardown(function() { - delete Blockly.Blocks['field_variable_test_block']; + this.blockTypes_.push('field_variable_test_block'); }); test('Variable Trivial', function() { this.workspace.createVariable('name1', '', 'id1'); @@ -260,7 +314,7 @@ suite('XML', function() { 'field_variable_test_block'); block.inputList[0].fieldRow[0].setValue('id1'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertVariableField(resultFieldDom, 'VAR', null, 'id1', 'name1'); + assertVariableDomField(resultFieldDom, 'VAR', null, 'id1', 'name1'); }); test('Variable Typed', function() { this.workspace.createVariable('name1', 'string', 'id1'); @@ -268,29 +322,21 @@ suite('XML', function() { 'field_variable_test_block'); block.inputList[0].fieldRow[0].setValue('id1'); var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - assertVariableField(resultFieldDom, 'VAR', 'string', 'id1', 'name1'); + assertVariableDomField(resultFieldDom, 'VAR', 'string', 'id1', 'name1'); }); test('Variable Default Case', function() { - var cacheGenUid = Blockly.utils.genUid; - Blockly.utils.genUid = function() { - return '1'; - }; + sinon.stub(Blockly.utils, 'genUid').returns('1'); + this.workspace.createVariable('name1'); - try { - this.workspace.createVariable('name1'); + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, + 'field_variable_test_block'); + block.inputList[0].fieldRow[0].setValue('1'); + Blockly.Events.enable(); - Blockly.Events.disable(); - var block = new Blockly.Block(this.workspace, - 'field_variable_test_block'); - block.inputList[0].fieldRow[0].setValue('1'); - Blockly.Events.enable(); - - var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; - // Expect type is null and ID is '1' since we don't specify type and ID. - assertVariableField(resultFieldDom, 'VAR', null, '1', 'name1'); - } finally { - Blockly.utils.genUid = cacheGenUid; - } + var resultFieldDom = Blockly.Xml.blockToDom(block).childNodes[0]; + // Expect type is null and ID is '1' since we don't specify type and ID. + assertVariableDomField(resultFieldDom, 'VAR', null, '1', 'name1'); }); }); }); @@ -369,143 +415,151 @@ suite('XML', function() { }); }); }); - suite('Deserialization', function() { + suite('variablesToDom', function() { setup(function() { this.workspace = new Blockly.Workspace(); + Blockly.defineBlocksWithJsonArray([{ + 'type': 'field_variable_test_block', + 'message0': '%1', + 'args0': [ + { + 'type': 'field_variable', + 'name': 'VAR', + 'variable': 'item' + } + ] + }]); + this.blockTypes_.push('field_variable_test_block'); + }); + teardown(function() { + this.workspace.dispose(); + }); + test('One Variable', function() { + sinon.stub(Blockly.utils, 'genUid').returns('1'); + this.workspace.createVariable('name1'); + var resultDom = + Blockly.Xml.variablesToDom(this.workspace.getAllVariables()); + assertEquals(1, resultDom.children.length); + var resultVariableDom = resultDom.children[0]; + assertEquals('name1', resultVariableDom.textContent); + assertEquals(null, resultVariableDom.getAttribute('type')); + assertEquals('1', resultVariableDom.getAttribute('id')); + }); + test('Two Variable one block', function() { + this.workspace.createVariable('name1', '', 'id1'); + this.workspace.createVariable('name2', 'type2', 'id2'); + // If events are enabled during block construction, it will create a + // default variable. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'field_variable_test_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + Blockly.Events.enable(); + + var resultDom = Blockly.Xml.variablesToDom(this.workspace.getAllVariables()); + assertEquals(2, resultDom.children.length); + assertVariableDom(resultDom.children[0], null, 'id1', + 'name1'); + assertVariableDom(resultDom.children[1], 'type2', 'id2', + 'name2'); + }); + test('No variables', function() { + var resultDom = + Blockly.Xml.variablesToDom(this.workspace.getAllVariables()); + assertEquals(0, resultDom.children.length); + }); + }); + suite('domToText', function() { + test('Round tripping', function() { + var dom = Blockly.Xml.textToDom(this.complexXmlText); + var text = Blockly.Xml.domToText(dom); + assertEquals('Round trip', this.complexXmlText.replace(/\s+/g, ''), + text.replace(/\s+/g, '')); + }); + }); + suite('domToPrettyText', function() { + test('Round tripping', function() { + var dom = Blockly.Xml.textToDom(this.complexXmlText); + var text = Blockly.Xml.domToPrettyText(dom); + assertEquals('Round trip', this.complexXmlText.replace(/\s+/g, ''), + text.replace(/\s+/g, '')); + }); + }); + suite('domToBlock', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + Blockly.defineBlocksWithJsonArray([{ + "type": "variables_get", + "message0": "%1", + "args0": [ + { + "type": "field_variable", + "name": "VAR" + } + ] + }, + { + "type": "variables_set", + "message0": "%1 %2", + "args0": [ + { + "type": "field_variable", + "name": "VAR" + }, + { + "type": "input_value", + "name": "VALUE" + } + ] + }, + { + "type": "math_change", + "message0": "%1 %2", + "args0": [ + { + "type": "field_variable", + "name": "VAR" + }, + { + "type": "input_value", + "name": "DELTA", + "check": "Number" + } + ] + }, + { + "type": "math_number", + "message0": "%1", + "args0": [{ + "type": "field_number", + "name": "NUM", + "value": 0 + }], + "output": "Number" + }]); + Array.prototype.push.apply( + this.blockTypes_, + ['variables_get', 'variables_set', 'math_change', 'math_number']); }); teardown(function() { this.workspace.dispose(); }); suite('Dynamic Category Blocks', function() { test('Untyped Variables', function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "variables_get", - "message0": "%1", - "args0": [ - { - "type": "field_variable", - "name": "VAR", - } - ] - }, - { - "type": "variables_set", - "message0": "%1 %2", - "args0": [ - { - "type": "field_variable", - "name": "VAR" - }, - { - "type": "input_value", - "name": "VALUE" - } - ] - }, - { - "type": "math_change", - "message0": "%1 %2", - "args0": [ - { - "type": "field_variable", - "name": "VAR", - }, - { - "type": "input_value", - "name": "DELTA", - "check": "Number" - } - ] - }, - { - "type": "math_number", - "message0": "%1", - "args0": [{ - "type": "field_number", - "name": "NUM", - "value": 0 - }], - "output": "Number" - }]); - this.workspace.createVariable('name1', '', 'id1'); - var blocksArray = Blockly.Variables.flyoutCategoryBlocks(this.workspace); - try { - for (var i = 0, xml; (xml = blocksArray[i]); i++) { - Blockly.Xml.domToBlock(xml, this.workspace); - } - } finally { - delete Blockly.Blocks['variables_get']; - delete Blockly.Blocks['variables_set']; - delete Blockly.Blocks['math_change']; - delete Blockly.Blocks['math_number']; + var blocksArray = + Blockly.Variables.flyoutCategoryBlocks(this.workspace); + for (var i = 0, xml; (xml = blocksArray[i]); i++) { + Blockly.Xml.domToBlock(xml, this.workspace); } }); test('Typed Variables', function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "variables_get", - "message0": "%1", - "args0": [ - { - "type": "field_variable", - "name": "VAR", - } - ] - }, - { - "type": "variables_set", - "message0": "%1 %2", - "args0": [ - { - "type": "field_variable", - "name": "VAR" - }, - { - "type": "input_value", - "name": "VALUE" - } - ] - }, - { - "type": "math_change", - "message0": "%1 %2", - "args0": [ - { - "type": "field_variable", - "name": "VAR", - }, - { - "type": "input_value", - "name": "DELTA", - "check": "Number" - } - ] - }, - { - "type": "math_number", - "message0": "%1", - "args0": [{ - "type": "field_number", - "name": "NUM", - "value": 0 - }], - "output": "Number" - }]); - this.workspace.createVariable('name1', 'String', 'id1'); this.workspace.createVariable('name2', 'Number', 'id2'); this.workspace.createVariable('name3', 'Colour', 'id3'); - var blocksArray = Blockly.VariablesDynamic - .flyoutCategoryBlocks(this.workspace); - try { - for (var i = 0, xml; (xml = blocksArray[i]); i++) { - Blockly.Xml.domToBlock(xml, this.workspace); - } - } finally { - delete Blockly.Blocks['variables_get']; - delete Blockly.Blocks['variables_set']; - delete Blockly.Blocks['math_change']; - delete Blockly.Blocks['math_number']; + var blocksArray = + Blockly.VariablesDynamic.flyoutCategoryBlocks(this.workspace); + for (var i = 0, xml; (xml = blocksArray[i]); i++) { + Blockly.Xml.domToBlock(xml, this.workspace); } }); }); @@ -600,9 +654,6 @@ suite('XML', function() { setup(function() { this.clock = sinon.useFakeTimers(); }); - teardown(function() { - this.clock.restore(); - }); test('Pinned True', function() { var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( '' + @@ -640,7 +691,125 @@ suite('XML', function() { }); }); }); - suite('Round Tripping', function() { + suite('domToWorkspace', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + Blockly.defineBlocksWithJsonArray([{ + 'type': 'field_variable_test_block', + 'message0': '%1', + 'args0': [ + { + 'type': 'field_variable', + 'name': 'VAR', + 'variable': 'item' + } + ] + }]); + this.blockTypes_.push('field_variable_test_block'); + }); + teardown(function() { + this.workspace.dispose(); + }); + test('Backwards compatibility', function() { + sinon.stub(Blockly.utils, 'genUid').returns('1'); + var dom = Blockly.Xml.textToDom( + '' + + ' ' + + ' name1' + + ' ' + + ''); + Blockly.Xml.domToWorkspace(dom, this.workspace); + assertEquals('Block count', 1, this.workspace.getAllBlocks(false).length); + assertVariableValues(this.workspace, 'name1', '', '1'); + }); + test('Variables at top', function() { + var dom = Blockly.Xml.textToDom( + '' + + ' ' + + ' name1' + + ' name2' + + ' name3' + + ' ' + + ' ' + + ' name3' + + ' ' + + ''); + Blockly.Xml.domToWorkspace(dom, this.workspace); + assertEquals('Block count', 1, this.workspace.getAllBlocks(false).length); + assertVariableValues(this.workspace, 'name1', 'type1', 'id1'); + assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); + assertVariableValues(this.workspace, 'name3', '', 'id3'); + }); + test('Variables at top duplicated variables tag', function() { + var dom = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ''); + chai.assert.throws(function() { + Blockly.Xml.domToWorkspace(dom, this.workspace); + }); + }); + test('Variables at top missing type', function() { + var dom = Blockly.Xml.textToDom( + '' + + ' ' + + ' name1' + + ' ' + + ' ' + + ' name3' + + ' ' + + ''); + chai.assert.throws(function() { + Blockly.Xml.domToWorkspace(dom, this.workspace); + }); + }); + test('Variables at top mismatch block type', function() { + var dom = Blockly.Xml.textToDom( + '' + + ' ' + + ' name1' + + ' ' + + ' ' + + ' name1' + + ' ' + + ''); + chai.assert.throws(function() { + Blockly.Xml.domToWorkspace(dom, this.workspace); + }); + }); + }); + suite('appendDomToWorkspace', function() { + setup(function() { + Blockly.Blocks.test_block = { + init: function() { + this.jsonInit({ + message0: 'test', + }); + } + }; + this.workspace = new Blockly.Workspace(); + }); + teardown(function() { + delete Blockly.Blocks.test_block; + this.workspace.dispose(); + }); + test('Headless', function() { + var dom = Blockly.Xml.textToDom( + '' + + ' ' + + ' ' + + ''); + Blockly.Xml.appendDomToWorkspace(dom, this.workspace); + assertEquals('Block count', 1, this.workspace.getAllBlocks(false).length); + var newBlockIds = Blockly.Xml.appendDomToWorkspace(dom, this.workspace); + assertEquals('Block count', 2, this.workspace.getAllBlocks(false).length); + assertEquals('Number of new block ids', 1, newBlockIds.length); + }); + }); + suite('workspaceToDom -> domToWorkspace -> workspaceToDom', function() { setup(function() { var options = { comments: true @@ -653,19 +822,17 @@ suite('XML', function() { this.renderedWorkspace.dispose(); this.headlessWorkspace.dispose(); }); + var assertRoundTrip = function(originWs, targetWs) { + var originXml = Blockly.Xml.workspaceToDom(originWs); + Blockly.Xml.domToWorkspace(originXml, targetWs); + var targetXml = Blockly.Xml.workspaceToDom(targetWs); + + var expectedXmlText = Blockly.Xml.domToText(originXml); + var actualXmlText = Blockly.Xml.domToText(targetXml); + + chai.assert.equal(actualXmlText, expectedXmlText); + }; suite('Rendered -> XML -> Headless -> XML', function() { - setup(function() { - this.assertRoundTrip = function() { - var renderedXml = Blockly.Xml.workspaceToDom(this.renderedWorkspace); - Blockly.Xml.domToWorkspace(renderedXml, this.headlessWorkspace); - var headlessXml = Blockly.Xml.workspaceToDom(this.headlessWorkspace); - - var renderedText = Blockly.Xml.domToText(renderedXml); - var headlessText = Blockly.Xml.domToText(headlessXml); - - chai.assert.equal(headlessText, renderedText); - }; - }); test('Comment', function() { var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( '' @@ -673,23 +840,10 @@ suite('XML', function() { block.setCommentText('test text'); block.getCommentIcon().setBubbleSize(100, 100); block.getCommentIcon().setVisible(true); - - this.assertRoundTrip(); + assertRoundTrip(this.renderedWorkspace, this.headlessWorkspace); }); }); suite('Headless -> XML -> Rendered -> XML', function() { - setup(function() { - this.assertRoundTrip = function() { - var headlessXml = Blockly.Xml.workspaceToDom(this.headlessWorkspace); - Blockly.Xml.domToWorkspace(headlessXml, this.renderedWorkspace); - var renderedXml = Blockly.Xml.workspaceToDom(this.renderedWorkspace); - - var renderedText = Blockly.Xml.domToText(renderedXml); - var headlessText = Blockly.Xml.domToText(headlessXml); - - chai.assert.equal(renderedText, headlessText); - }; - }); test('Comment', function() { var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom( '' @@ -697,9 +851,34 @@ suite('XML', function() { block.setCommentText('test text'); block.commentModel.size = new Blockly.utils.Size(100, 100); block.commentModel.pinned = true; - - this.assertRoundTrip(); + + assertRoundTrip(this.headlessWorkspace, this.renderedWorkspace); }); }); }); + suite('generateVariableFieldDom', function() { + test('Case Sensitive', function() { + var varId = 'testId'; + var type = 'testType'; + var name = 'testName'; + + var mockVariableModel = { + type: type, + name: name, + getId: function() { + return varId; + } + }; + + var generatedXml = Blockly.Xml.domToText( + Blockly.Variables.generateVariableFieldDom(mockVariableModel)); + var expectedXml = + '' + name + ''; + assertEquals(expectedXml, generatedXml); + }); + }); }); From c740d2781c09efdd10fe0569871ed1508577d681 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Tue, 14 Apr 2020 18:17:34 -0700 Subject: [PATCH 015/139] Converting json junit test to mocha. (#3809) * Converting json_test to mocha. * Adding exceptions to mocha eslint config. * Address PR comments. --- tests/jsunit/index.html | 1 - tests/jsunit/json_test.js | 356 ------------------------------------- tests/mocha/.eslintrc.json | 2 + tests/mocha/index.html | 1 + tests/mocha/json_test.js | 343 +++++++++++++++++++++++++++++++++++ 5 files changed, 346 insertions(+), 357 deletions(-) delete mode 100644 tests/jsunit/json_test.js create mode 100644 tests/mocha/json_test.js diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index 29a3e4d51..cf10ff987 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -20,7 +20,6 @@ - diff --git a/tests/jsunit/json_test.js b/tests/jsunit/json_test.js deleted file mode 100644 index 197b8b620..000000000 --- a/tests/jsunit/json_test.js +++ /dev/null @@ -1,356 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - -/** Ensure a block can be instantiated from a JSON definition. */ -function test_json_minimal() { - var BLOCK_TYPE = 'test_json_minimal'; - - var workspace = new Blockly.Workspace(); - var block; - try { - var warnings = captureWarnings(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": BLOCK_TYPE - }]); - block = new Blockly.Block(workspace, BLOCK_TYPE); - }); - - assertEquals(BLOCK_TYPE, block.type); - assertEquals( - 'Expecting no warnings when defining and creating a simple block.', - warnings.length, 0); - // TODO: asserts - } finally { - block.dispose(); - workspace.dispose(); - delete Blockly.Blocks[BLOCK_TYPE]; - } -} - -/** - * Ensure a block without a type id fails with a warning, but does not block - * later definitions. - */ -function test_json_nullOrUndefinedBlockTypeId() { - var BLOCK_TYPE1 = 'test_json_before_bad_blocks'; - var BLOCK_TYPE2 = 'test_json_after_bad_blocks'; - - assertUndefined(Blockly.Blocks[BLOCK_TYPE1]); - assertUndefined(Blockly.Blocks[BLOCK_TYPE2]); - var blockTypeCount = Object.keys(Blockly.Blocks).length; - - try { - var warnings = captureWarnings(function() { - Blockly.defineBlocksWithJsonArray([ - {"type": BLOCK_TYPE1}, - {"type": undefined}, - {"type": null}, - {"type": BLOCK_TYPE2}]); - }); - - assertNotNullNorUndefined('Block before bad blocks should be defined.', - Blockly.Blocks[BLOCK_TYPE1]); - assertNotNullNorUndefined('Block after bad blocks should be defined.', - Blockly.Blocks[BLOCK_TYPE2]); - assertEquals(Object.keys(Blockly.Blocks).length, blockTypeCount + 2); - assertEquals( - 'Expecting 2 warnings, one for each bad block.', warnings.length, 2); - } finally { - delete Blockly.Blocks[BLOCK_TYPE1]; - delete Blockly.Blocks[BLOCK_TYPE2]; - } -} - -/** Ensure message0 creates an input. */ -function test_json_message0() { - var BLOCK_TYPE = 'test_json_message0'; - var MESSAGE0 = 'message0'; - - var workspace = new Blockly.Workspace(); - var block; - try { - Blockly.defineBlocksWithJsonArray([{ - "type": BLOCK_TYPE, - "message0": MESSAGE0 - }]); - - block = new Blockly.Block(workspace, BLOCK_TYPE); - assertEquals(1, block.inputList.length); - assertEquals(1, block.inputList[0].fieldRow.length); - var textField = block.inputList[0].fieldRow[0]; - assertEquals(Blockly.FieldLabel, textField.constructor); - assertEquals(MESSAGE0, textField.getText()); - } finally { - block && block.dispose(); - workspace.dispose(); - delete Blockly.Blocks[BLOCK_TYPE]; - } -} - -/** Ensure message1 creates a new input. */ -function test_json_message1() { - var BLOCK_TYPE = 'test_json_message1'; - var MESSAGE0 = 'message0'; - var MESSAGE1 = 'message1'; - - var workspace = new Blockly.Workspace(); - var block; - try { - Blockly.defineBlocksWithJsonArray([{ - "type": BLOCK_TYPE, - "message0": MESSAGE0, - "message1": MESSAGE1 - }]); - - block = new Blockly.Block(workspace, BLOCK_TYPE); - assertEquals(2, block.inputList.length); - - assertEquals(1, block.inputList[0].fieldRow.length); - var textField = block.inputList[0].fieldRow[0]; - assertEquals(Blockly.FieldLabel, textField.constructor); - assertEquals(MESSAGE0, textField.getText()); - - assertEquals(1, block.inputList[1].fieldRow.length); - var textField = block.inputList[1].fieldRow[0]; - assertEquals(Blockly.FieldLabel, textField.constructor); - assertEquals(MESSAGE1, textField.getText()); - } finally { - block && block.dispose(); - workspace.dispose(); - delete Blockly.Blocks[BLOCK_TYPE]; - } -} - -/** Ensure message string is dereferenced. */ -function test_json_message0_i18n() { - var BLOCK_TYPE = 'test_json_message0_i18n'; - var MESSAGE0 = '%{BKY_MESSAGE}'; - var MESSAGE = 'message'; - - Blockly.Msg['MESSAGE'] = MESSAGE; - - var workspace = new Blockly.Workspace(); - var block; - try { - Blockly.defineBlocksWithJsonArray([{ - "type": BLOCK_TYPE, - "message0": MESSAGE0 - }]); - - block = new Blockly.Block(workspace, BLOCK_TYPE); - assertEquals(1, block.inputList.length); - assertEquals(1, block.inputList[0].fieldRow.length); - var textField = block.inputList[0].fieldRow[0]; - assertEquals(Blockly.FieldLabel, textField.constructor); - assertEquals(MESSAGE, textField.getText()); - } finally { - block && block.dispose(); // Disposes of textField, too. - workspace.dispose(); - delete Blockly.Blocks[BLOCK_TYPE]; - delete Blockly.Msg['MESSAGE']; - } -} - -function test_json_dropdown() { - var BLOCK_TYPE = 'test_json_dropdown'; - var FIELD_NAME = 'FIELD_NAME'; - var LABEL0 = 'LABEL0'; - var VALUE0 = 'VALUE0'; - var LABEL1 = 'LABEL1'; - var VALUE1 = 'VALUE1'; - - var workspace = new Blockly.Workspace(); - var block; - try { - Blockly.defineBlocksWithJsonArray([{ - "type": BLOCK_TYPE, - "message0": "%1", - "args0": [ - { - "type": "field_dropdown", - "name": FIELD_NAME, - "options": [ - [LABEL0, VALUE0], - [LABEL1, VALUE1] - ] - } - ] - }]); - - block = new Blockly.Block(workspace, BLOCK_TYPE); - assertEquals(1, block.inputList.length); - assertEquals(1, block.inputList[0].fieldRow.length); - var dropdown = block.inputList[0].fieldRow[0]; - assertEquals(dropdown, block.getField(FIELD_NAME)); - assertEquals(Blockly.FieldDropdown, dropdown.constructor); - assertEquals(VALUE0, dropdown.getValue()); - - var options = dropdown.getOptions(); - assertEquals(LABEL0, options[0][0]); - assertEquals(VALUE0, options[0][1]); - assertEquals(LABEL1, options[1][0]); - assertEquals(VALUE1, options[1][1]); - } finally { - block && block.dispose(); // Disposes of dropdown, too. - workspace.dispose(); - delete Blockly.Blocks[BLOCK_TYPE]; - } -} - -function test_json_dropdown_image() { - var BLOCK_TYPE = 'test_json_dropdown'; - var FIELD_NAME = 'FIELD_NAME'; - var IMAGE1_ALT_TEXT = 'Localized message.'; - Blockly.Msg['ALT_TEXT'] = IMAGE1_ALT_TEXT; - var IMAGE0 = { - 'width': 12, - 'height': 34, - 'src': 'http://image0.src', - 'alt': 'IMAGE0 alt text' - }; - var VALUE0 = 'VALUE0'; - var IMAGE1 = { - 'width': 56, - 'height': 78, - 'src': 'http://image1.src', - 'alt': '%{BKY_ALT_TEXT}' - }; - var VALUE1 = 'VALUE1'; - var IMAGE2 = { - 'width': 90, - 'height': 123, - 'src': 'http://image2.src' - }; - var VALUE2 = 'VALUE2'; - - var workspace = new Blockly.Workspace(); - var block; - try { - Blockly.defineBlocksWithJsonArray([{ - "type": BLOCK_TYPE, - "message0": "%1", - "args0": [ - { - "type": "field_dropdown", - "name": FIELD_NAME, - "options": [ - [IMAGE0, VALUE0], - [IMAGE1, VALUE1], - [IMAGE2, VALUE2] - ] - } - ] - }]); - - block = new Blockly.Block(workspace, BLOCK_TYPE); - assertEquals(1, block.inputList.length); - assertEquals(1, block.inputList[0].fieldRow.length); - var dropdown = block.inputList[0].fieldRow[0]; - assertEquals(dropdown, block.getField(FIELD_NAME)); - assertEquals(Blockly.FieldDropdown, dropdown.constructor); - assertEquals(VALUE0, dropdown.getValue()); - - var options = dropdown.getOptions(); - var image0 = options[0][0]; - assertEquals(IMAGE0.width, image0.width); - assertEquals(IMAGE0.height, image0.height); - assertEquals(IMAGE0.src, image0.src); - assertEquals(IMAGE0.alt, image0.alt); - assertEquals(VALUE0, options[0][1]); - - var image1 = options[1][0]; - assertEquals(IMAGE1.width, image1.width); - assertEquals(IMAGE1.height, image1.height); - assertEquals(IMAGE1.src, image1.src); - assertEquals(IMAGE1.alt, IMAGE1_ALT_TEXT); // Via Msg reference - assertEquals(VALUE1, options[1][1]); - - var image2 = options[2][0]; - assertEquals(IMAGE2.width, image2.width); - assertEquals(IMAGE2.height, image2.height); - assertEquals(IMAGE2.src, image2.src); - assert(image2.alt == null); // No alt specified. - assertEquals(VALUE2, options[2][1]); - } finally { - block && block.dispose(); // Disposes of dropdown, too. - workspace.dispose(); - delete Blockly.Blocks[BLOCK_TYPE]; - delete Blockly.Msg['ALTTEXT']; - } -} - -function test_defineBlocksWithJsonArray_nullItem() { - var BLOCK_TYPE1 = 'test_block_before_null'; - var BLOCK_TYPE2 = 'test_block_after_null'; - - assertUndefined(Blockly.Blocks[BLOCK_TYPE1]); - assertUndefined(Blockly.Blocks[BLOCK_TYPE2]); - var blockTypeCount = Object.keys(Blockly.Blocks).length; - - try { - var warnings = captureWarnings(function() { - Blockly.defineBlocksWithJsonArray([ - { - "type": BLOCK_TYPE1, - "message0": 'before' - }, - null, - { - "type": BLOCK_TYPE2, - "message0": 'after' - }]); - }); - assertNotNullNorUndefined( - 'Block before null in array should be defined.', - Blockly.Blocks[BLOCK_TYPE1]); - assertNotNullNorUndefined( - 'Block after null in array should be defined.', - Blockly.Blocks[BLOCK_TYPE2]); - assertEquals(Object.keys(Blockly.Blocks).length, blockTypeCount + 2); - assertEquals('Expected 1 warning for the bad block.', warnings.length, 1); - } finally { - workspace.dispose(); - delete Blockly.Blocks[BLOCK_TYPE1]; - delete Blockly.Blocks[BLOCK_TYPE2]; - } -} - -function test_defineBlocksWithJsonArray_undefinedItem() { - var BLOCK_TYPE1 = 'test_block_before_undefined'; - var BLOCK_TYPE2 = 'test_block_after_undefined'; - - assertUndefined(Blockly.Blocks[BLOCK_TYPE1]); - assertUndefined(Blockly.Blocks[BLOCK_TYPE2]); - var blockTypeCount = Object.keys(Blockly.Blocks).length; - - try { - var warnings = captureWarnings(function() { - Blockly.defineBlocksWithJsonArray([ - { - "type": BLOCK_TYPE1, - "message0": 'before' - }, - undefined, - { - "type": BLOCK_TYPE2, - "message0": 'after' - }]); - }); - assertNotNullNorUndefined( - 'Block before undefined in array should be defined.', - Blockly.Blocks[BLOCK_TYPE1]); - assertNotNullNorUndefined( - 'Block after undefined in array should be defined.', - Blockly.Blocks[BLOCK_TYPE2]); - assertEquals(Object.keys(Blockly.Blocks).length, blockTypeCount + 2); - assertEquals('Expected 1 warning for the bad block.', warnings.length, 1); - } finally { - workspace.dispose(); - delete Blockly.Blocks[BLOCK_TYPE1]; - delete Blockly.Blocks[BLOCK_TYPE2]; - } -} diff --git a/tests/mocha/.eslintrc.json b/tests/mocha/.eslintrc.json index 48d7af0e7..c6ae36484 100644 --- a/tests/mocha/.eslintrc.json +++ b/tests/mocha/.eslintrc.json @@ -6,6 +6,7 @@ "globals": { "chai": false, "sinon": false, + "assert": true, "assertArrayEquals": true, "assertNull": true, "assertNotNull": true, @@ -15,6 +16,7 @@ "isEqualArrays": true, "assertUndefined": true, "assertNotUndefined": true, + "assertNotNullNorUndefined": true, "defineStackBlock": true, "defineRowBlock": true, "defineStatementBlock": true, diff --git a/tests/mocha/index.html b/tests/mocha/index.html index f535ba2e1..ee645b79e 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -48,6 +48,7 @@ + diff --git a/tests/mocha/json_test.js b/tests/mocha/json_test.js new file mode 100644 index 000000000..b6b79123b --- /dev/null +++ b/tests/mocha/json_test.js @@ -0,0 +1,343 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +suite('JSON Block Definitions', function() { + setup(function() { + this.workspace_ = new Blockly.Workspace(); + this.blocks_ = []; + this.blockTypes_ = []; + this.messages_ = []; + }); + + teardown(function() { + for (var i = 0; i < this.blocks_.length; i++) { + var block = this.blocks_[i]; + block.dispose(); + } + for (var i = 0, blockType; (blockType = this.blockTypes_[i]); i++) { + delete Blockly.Blocks[blockType]; + } + for (var i = 0, message; (message = this.messages_[i]); i++) { + delete Blockly.Msg[message]; + } + this.workspace_.dispose(); + }); + + /** + * Captures the strings sent to console.warn() when calling a function. + * @param {function} innerFunc The function where warnings may called. + * @return {string[]} The warning messages (only the first arguments). + */ + function captureWarnings(innerFunc) { + var msgs = []; + var nativeConsoleWarn = console.warn; + try { + console.warn = function(msg) { + msgs.push(msg); + nativeConsoleWarn.apply(console, arguments); + }; + innerFunc(); + } finally { + console.warn = nativeConsoleWarn; + } + return msgs; + } + + suite('defineBlocksWithJsonArray', function() { + test('Basic block', function() { + /** Ensure a block can be instantiated from a JSON definition. */ + var BLOCK_TYPE = 'test_json_minimal'; + this.blockTypes_.push(BLOCK_TYPE); + var workspace = this.workspace_; + var block; + var warnings = captureWarnings(function() { + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE + }]); + block = new Blockly.Block(workspace, BLOCK_TYPE); + }); + this.blocks_.push(block); + + assertNotNull(block); + assertEquals(BLOCK_TYPE, block.type); + assertEquals( + 'Expecting no warnings when defining and creating a simple block.', + warnings.length, 0); + }); + + test('Null or undefined type id', function() { + var BLOCK_TYPE1 = 'test_json_before_bad_blocks'; + var BLOCK_TYPE2 = 'test_json_after_bad_blocks'; + this.blockTypes_.push(BLOCK_TYPE1); + this.blockTypes_.push(BLOCK_TYPE2); + + assertUndefined(Blockly.Blocks[BLOCK_TYPE1]); + assertUndefined(Blockly.Blocks[BLOCK_TYPE2]); + var blockTypeCount = Object.keys(Blockly.Blocks).length; + + var warnings = captureWarnings(function() { + Blockly.defineBlocksWithJsonArray([ + {"type": BLOCK_TYPE1}, + {"type": undefined}, + {"type": null}, + {"type": BLOCK_TYPE2}]); + }); + + assertNotNullNorUndefined('Block before bad blocks should be defined.', + Blockly.Blocks[BLOCK_TYPE1]); + assertNotNullNorUndefined('Block after bad blocks should be defined.', + Blockly.Blocks[BLOCK_TYPE2]); + assertEquals(Object.keys(Blockly.Blocks).length, blockTypeCount + 2); + assertEquals( + 'Expecting 2 warnings, one for each bad block.', warnings.length, 2); + }); + + test('Null item', function() { + var BLOCK_TYPE1 = 'test_block_before_null'; + var BLOCK_TYPE2 = 'test_block_after_null'; + this.blockTypes_.push(BLOCK_TYPE1); + this.blockTypes_.push(BLOCK_TYPE2); + + assertUndefined(Blockly.Blocks[BLOCK_TYPE1]); + assertUndefined(Blockly.Blocks[BLOCK_TYPE2]); + var blockTypeCount = Object.keys(Blockly.Blocks).length; + + var warnings = captureWarnings(function() { + Blockly.defineBlocksWithJsonArray([ + { + "type": BLOCK_TYPE1, + "message0": 'before' + }, + null, + { + "type": BLOCK_TYPE2, + "message0": 'after' + }]); + }); + assertNotNullNorUndefined( + 'Block before null in array should be defined.', + Blockly.Blocks[BLOCK_TYPE1]); + assertNotNullNorUndefined( + 'Block after null in array should be defined.', + Blockly.Blocks[BLOCK_TYPE2]); + assertEquals(Object.keys(Blockly.Blocks).length, blockTypeCount + 2); + assertEquals('Expected 1 warning for the bad block.', warnings.length, 1); + }); + + test('Undefined item', function() { + var BLOCK_TYPE1 = 'test_block_before_undefined'; + var BLOCK_TYPE2 = 'test_block_after_undefined'; + this.blockTypes_.push(BLOCK_TYPE1); + this.blockTypes_.push(BLOCK_TYPE2); + + assertUndefined(Blockly.Blocks[BLOCK_TYPE1]); + assertUndefined(Blockly.Blocks[BLOCK_TYPE2]); + var blockTypeCount = Object.keys(Blockly.Blocks).length; + var warnings = captureWarnings(function() { + Blockly.defineBlocksWithJsonArray([ + { + "type": BLOCK_TYPE1, + "message0": 'before' + }, + undefined, + { + "type": BLOCK_TYPE2, + "message0": 'after' + }]); + }); + assertNotNullNorUndefined( + 'Block before undefined in array should be defined.', + Blockly.Blocks[BLOCK_TYPE1]); + assertNotNullNorUndefined( + 'Block after undefined in array should be defined.', + Blockly.Blocks[BLOCK_TYPE2]); + assertEquals(Object.keys(Blockly.Blocks).length, blockTypeCount + 2); + assertEquals('Expected 1 warning for the bad block.', warnings.length, 1); + }); + + test('message0 creates input', function() { + var BLOCK_TYPE = 'test_json_message0'; + this.blockTypes_.push(BLOCK_TYPE); + var MESSAGE0 = 'message0'; + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": MESSAGE0 + }]); + + var block = new Blockly.Block(this.workspace_, BLOCK_TYPE); + assertEquals(1, block.inputList.length); + assertEquals(1, block.inputList[0].fieldRow.length); + var textField = block.inputList[0].fieldRow[0]; + assertEquals(Blockly.FieldLabel, textField.constructor); + assertEquals(MESSAGE0, textField.getText()); + }); + + test('message1 and message0 creates two inputs', function() { + /** Ensure message1 creates a new input. */ + var BLOCK_TYPE = 'test_json_message1'; + this.blockTypes_.push(BLOCK_TYPE); + var MESSAGE0 = 'message0'; + var MESSAGE1 = 'message1'; + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": MESSAGE0, + "message1": MESSAGE1 + }]); + + var block = new Blockly.Block(this.workspace_, BLOCK_TYPE); + this.blocks_.push(block); + assertEquals(2, block.inputList.length); + + assertEquals(1, block.inputList[0].fieldRow.length); + var textField = block.inputList[0].fieldRow[0]; + assertEquals(Blockly.FieldLabel, textField.constructor); + assertEquals(MESSAGE0, textField.getText()); + + assertEquals(1, block.inputList[1].fieldRow.length); + var textField = block.inputList[1].fieldRow[0]; + assertEquals(Blockly.FieldLabel, textField.constructor); + assertEquals(MESSAGE1, textField.getText()); + }); + + test('Message string is dereferenced', function() { + var BLOCK_TYPE = 'test_json_message0_i18n'; + this.blockTypes_.push(BLOCK_TYPE); + var MESSAGE0 = '%{BKY_MESSAGE}'; + var MESSAGE = 'message'; + + Blockly.Msg['MESSAGE'] = MESSAGE; + this.messages_.push('MESSAGE'); + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": MESSAGE0 + }]); + + var block = new Blockly.Block(this.workspace_, BLOCK_TYPE); + this.blocks_.push(block); + assertEquals(1, block.inputList.length); + assertEquals(1, block.inputList[0].fieldRow.length); + var textField = block.inputList[0].fieldRow[0]; + assertEquals(Blockly.FieldLabel, textField.constructor); + assertEquals(MESSAGE, textField.getText()); + }); + + test('Dropdown', function() { + var BLOCK_TYPE = 'test_json_dropdown'; + this.blockTypes_.push(BLOCK_TYPE); + var FIELD_NAME = 'FIELD_NAME'; + var LABEL0 = 'LABEL0'; + var VALUE0 = 'VALUE0'; + var LABEL1 = 'LABEL1'; + var VALUE1 = 'VALUE1'; + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": "%1", + "args0": [ + { + "type": "field_dropdown", + "name": FIELD_NAME, + "options": [ + [LABEL0, VALUE0], + [LABEL1, VALUE1] + ] + } + ] + }]); + + var block = new Blockly.Block(this.workspace_, BLOCK_TYPE); + this.blocks_.push(block); + assertEquals(1, block.inputList.length); + assertEquals(1, block.inputList[0].fieldRow.length); + var dropdown = block.inputList[0].fieldRow[0]; + assertEquals(dropdown, block.getField(FIELD_NAME)); + assertEquals(Blockly.FieldDropdown, dropdown.constructor); + assertEquals(VALUE0, dropdown.getValue()); + + var options = dropdown.getOptions(); + assertEquals(LABEL0, options[0][0]); + assertEquals(VALUE0, options[0][1]); + assertEquals(LABEL1, options[1][0]); + assertEquals(VALUE1, options[1][1]); + }); + + + test('Dropdown with images', function() { + var BLOCK_TYPE = 'test_json_dropdown'; + this.blockTypes_.push(BLOCK_TYPE); + var FIELD_NAME = 'FIELD_NAME'; + var IMAGE1_ALT_TEXT = 'Localized message.'; + Blockly.Msg['ALT_TEXT'] = IMAGE1_ALT_TEXT; + this.messages_.push('ALT_TEXT'); + var IMAGE0 = { + 'width': 12, + 'height': 34, + 'src': 'http://image0.src', + 'alt': 'IMAGE0 alt text' + }; + var VALUE0 = 'VALUE0'; + var IMAGE1 = { + 'width': 56, + 'height': 78, + 'src': 'http://image1.src', + 'alt': '%{BKY_ALT_TEXT}' + }; + var VALUE1 = 'VALUE1'; + var IMAGE2 = { + 'width': 90, + 'height': 123, + 'src': 'http://image2.src' + }; + var VALUE2 = 'VALUE2'; + + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": "%1", + "args0": [ + { + "type": "field_dropdown", + "name": FIELD_NAME, + "options": [ + [IMAGE0, VALUE0], + [IMAGE1, VALUE1], + [IMAGE2, VALUE2] + ] + } + ] + }]); + + var block = new Blockly.Block(this.workspace_, BLOCK_TYPE); + this.blocks_.push(block); + assertEquals(1, block.inputList.length); + assertEquals(1, block.inputList[0].fieldRow.length); + var dropdown = block.inputList[0].fieldRow[0]; + assertEquals(dropdown, block.getField(FIELD_NAME)); + assertEquals(Blockly.FieldDropdown, dropdown.constructor); + assertEquals(VALUE0, dropdown.getValue()); + + function assertImageEquals(actualImage, expectedImage) { + assertEquals(actualImage.width, expectedImage.width); + assertEquals(actualImage.height, expectedImage.height); + assertEquals(actualImage.src, expectedImage.src); + } + + var options = dropdown.getOptions(); + var image0 = options[0][0]; + assertImageEquals(IMAGE0, image0); + assertEquals(IMAGE0.alt, image0.alt); + assertEquals(options[0][1], VALUE0); + + var image1 = options[1][0]; + assertImageEquals(IMAGE1, image1); + assertEquals(IMAGE1.alt, IMAGE1_ALT_TEXT); // Via Msg reference + assertEquals(VALUE1, options[1][1]); + + var image2 = options[2][0]; + assertImageEquals(IMAGE1, image1); + assert(image2.alt == null); // No alt specified. + assertEquals(VALUE2, options[2][1]); + }); + }); +}); From 7e4e6c72867aca0d219547f7b2ff4b5eb3dec5ca Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 15 Apr 2020 09:44:25 -0700 Subject: [PATCH 016/139] Add typings modules to match UMD modules. (#3821) * Add typings modules to match UMD modules. --- gulpfile.js | 2 +- package.json | 2 +- scripts/gulpfiles/package_tasks.js | 2 +- scripts/gulpfiles/typings.js | 19 +- typings/blocks.d.ts | 15 + typings/core.d.ts | 15 + typings/dart.d.ts | 15 + typings/index.d.ts | 22 + typings/javascript.d.ts | 15 + typings/lua.d.ts | 15 + typings/msg/ab.d.ts | 16 + typings/msg/ar.d.ts | 16 + typings/msg/az.d.ts | 16 + typings/msg/ba.d.ts | 16 + typings/msg/bcc.d.ts | 16 + typings/msg/be-tarask.d.ts | 16 + typings/msg/be.d.ts | 16 + typings/msg/bg.d.ts | 16 + typings/msg/bn.d.ts | 16 + typings/msg/br.d.ts | 16 + typings/msg/ca.d.ts | 16 + typings/msg/constants.d.ts | 16 + typings/msg/cs.d.ts | 16 + typings/msg/da.d.ts | 16 + typings/msg/de.d.ts | 16 + typings/msg/diq.d.ts | 16 + typings/msg/dty.d.ts | 16 + typings/msg/ee.d.ts | 16 + typings/msg/el.d.ts | 16 + typings/msg/en-gb.d.ts | 16 + typings/msg/en.d.ts | 16 + typings/msg/eo.d.ts | 16 + typings/msg/es.d.ts | 16 + typings/msg/et.d.ts | 16 + typings/msg/eu.d.ts | 16 + typings/msg/fa.d.ts | 16 + typings/msg/fi.d.ts | 16 + typings/msg/fr.d.ts | 16 + typings/msg/gl.d.ts | 16 + typings/msg/gor.d.ts | 16 + typings/msg/ha.d.ts | 16 + typings/msg/he.d.ts | 16 + typings/msg/hi.d.ts | 16 + typings/msg/hrx.d.ts | 16 + typings/msg/hu.d.ts | 16 + typings/msg/hy.d.ts | 16 + typings/msg/ia.d.ts | 16 + typings/msg/id.d.ts | 16 + typings/msg/ig.d.ts | 16 + typings/msg/is.d.ts | 16 + typings/msg/it.d.ts | 16 + typings/msg/ja.d.ts | 16 + typings/msg/kab.d.ts | 16 + typings/msg/kn.d.ts | 16 + typings/msg/ko.d.ts | 16 + typings/msg/lb.d.ts | 16 + typings/msg/lki.d.ts | 16 + typings/msg/lo.d.ts | 16 + typings/msg/lrc.d.ts | 16 + typings/msg/lt.d.ts | 16 + typings/msg/lv.d.ts | 16 + typings/msg/mk.d.ts | 16 + typings/msg/mnw.d.ts | 16 + typings/msg/ms.d.ts | 16 + typings/msg/msg.d.ts | 444 ++++++++++++++++++ typings/msg/nb.d.ts | 16 + typings/msg/nl.d.ts | 16 + typings/msg/oc.d.ts | 16 + typings/msg/pl.d.ts | 16 + typings/msg/pms.d.ts | 16 + typings/msg/pt-br.d.ts | 16 + typings/msg/pt.d.ts | 16 + typings/msg/qqq.d.ts | 16 + typings/msg/ro.d.ts | 16 + typings/msg/ru.d.ts | 16 + typings/msg/sc.d.ts | 16 + typings/msg/sd.d.ts | 16 + typings/msg/shn.d.ts | 16 + typings/msg/sk.d.ts | 16 + typings/msg/skr-arab.d.ts | 16 + typings/msg/sl.d.ts | 16 + typings/msg/sq.d.ts | 16 + typings/msg/sr-latn.d.ts | 16 + typings/msg/sr.d.ts | 16 + typings/msg/sv.d.ts | 16 + typings/msg/synonyms.d.ts | 16 + typings/msg/ta.d.ts | 16 + typings/msg/tcy.d.ts | 16 + typings/msg/te.d.ts | 16 + typings/msg/th.d.ts | 16 + typings/msg/tl.d.ts | 16 + typings/msg/tlh.d.ts | 16 + typings/msg/tr.d.ts | 16 + typings/msg/ug-arab.d.ts | 16 + typings/msg/uk.d.ts | 16 + typings/msg/ur.d.ts | 16 + typings/msg/vi.d.ts | 16 + typings/msg/xmf.d.ts | 16 + typings/msg/yo.d.ts | 16 + typings/msg/zh-hans.d.ts | 16 + typings/msg/zh-hant.d.ts | 16 + typings/php.d.ts | 15 + typings/python.d.ts | 15 + .../blockly-header.template} | 0 .../blockly-interfaces.template} | 0 typings/templates/msg.template | 16 + 106 files changed, 2046 insertions(+), 6 deletions(-) create mode 100644 typings/blocks.d.ts create mode 100644 typings/core.d.ts create mode 100644 typings/dart.d.ts create mode 100644 typings/index.d.ts create mode 100644 typings/javascript.d.ts create mode 100644 typings/lua.d.ts create mode 100644 typings/msg/ab.d.ts create mode 100644 typings/msg/ar.d.ts create mode 100644 typings/msg/az.d.ts create mode 100644 typings/msg/ba.d.ts create mode 100644 typings/msg/bcc.d.ts create mode 100644 typings/msg/be-tarask.d.ts create mode 100644 typings/msg/be.d.ts create mode 100644 typings/msg/bg.d.ts create mode 100644 typings/msg/bn.d.ts create mode 100644 typings/msg/br.d.ts create mode 100644 typings/msg/ca.d.ts create mode 100644 typings/msg/constants.d.ts create mode 100644 typings/msg/cs.d.ts create mode 100644 typings/msg/da.d.ts create mode 100644 typings/msg/de.d.ts create mode 100644 typings/msg/diq.d.ts create mode 100644 typings/msg/dty.d.ts create mode 100644 typings/msg/ee.d.ts create mode 100644 typings/msg/el.d.ts create mode 100644 typings/msg/en-gb.d.ts create mode 100644 typings/msg/en.d.ts create mode 100644 typings/msg/eo.d.ts create mode 100644 typings/msg/es.d.ts create mode 100644 typings/msg/et.d.ts create mode 100644 typings/msg/eu.d.ts create mode 100644 typings/msg/fa.d.ts create mode 100644 typings/msg/fi.d.ts create mode 100644 typings/msg/fr.d.ts create mode 100644 typings/msg/gl.d.ts create mode 100644 typings/msg/gor.d.ts create mode 100644 typings/msg/ha.d.ts create mode 100644 typings/msg/he.d.ts create mode 100644 typings/msg/hi.d.ts create mode 100644 typings/msg/hrx.d.ts create mode 100644 typings/msg/hu.d.ts create mode 100644 typings/msg/hy.d.ts create mode 100644 typings/msg/ia.d.ts create mode 100644 typings/msg/id.d.ts create mode 100644 typings/msg/ig.d.ts create mode 100644 typings/msg/is.d.ts create mode 100644 typings/msg/it.d.ts create mode 100644 typings/msg/ja.d.ts create mode 100644 typings/msg/kab.d.ts create mode 100644 typings/msg/kn.d.ts create mode 100644 typings/msg/ko.d.ts create mode 100644 typings/msg/lb.d.ts create mode 100644 typings/msg/lki.d.ts create mode 100644 typings/msg/lo.d.ts create mode 100644 typings/msg/lrc.d.ts create mode 100644 typings/msg/lt.d.ts create mode 100644 typings/msg/lv.d.ts create mode 100644 typings/msg/mk.d.ts create mode 100644 typings/msg/mnw.d.ts create mode 100644 typings/msg/ms.d.ts create mode 100644 typings/msg/msg.d.ts create mode 100644 typings/msg/nb.d.ts create mode 100644 typings/msg/nl.d.ts create mode 100644 typings/msg/oc.d.ts create mode 100644 typings/msg/pl.d.ts create mode 100644 typings/msg/pms.d.ts create mode 100644 typings/msg/pt-br.d.ts create mode 100644 typings/msg/pt.d.ts create mode 100644 typings/msg/qqq.d.ts create mode 100644 typings/msg/ro.d.ts create mode 100644 typings/msg/ru.d.ts create mode 100644 typings/msg/sc.d.ts create mode 100644 typings/msg/sd.d.ts create mode 100644 typings/msg/shn.d.ts create mode 100644 typings/msg/sk.d.ts create mode 100644 typings/msg/skr-arab.d.ts create mode 100644 typings/msg/sl.d.ts create mode 100644 typings/msg/sq.d.ts create mode 100644 typings/msg/sr-latn.d.ts create mode 100644 typings/msg/sr.d.ts create mode 100644 typings/msg/sv.d.ts create mode 100644 typings/msg/synonyms.d.ts create mode 100644 typings/msg/ta.d.ts create mode 100644 typings/msg/tcy.d.ts create mode 100644 typings/msg/te.d.ts create mode 100644 typings/msg/th.d.ts create mode 100644 typings/msg/tl.d.ts create mode 100644 typings/msg/tlh.d.ts create mode 100644 typings/msg/tr.d.ts create mode 100644 typings/msg/ug-arab.d.ts create mode 100644 typings/msg/uk.d.ts create mode 100644 typings/msg/ur.d.ts create mode 100644 typings/msg/vi.d.ts create mode 100644 typings/msg/xmf.d.ts create mode 100644 typings/msg/yo.d.ts create mode 100644 typings/msg/zh-hans.d.ts create mode 100644 typings/msg/zh-hant.d.ts create mode 100644 typings/php.d.ts create mode 100644 typings/python.d.ts rename typings/{parts/blockly-header.d.ts => templates/blockly-header.template} (100%) rename typings/{parts/blockly-interfaces.d.ts => templates/blockly-interfaces.template} (100%) create mode 100644 typings/templates/msg.template diff --git a/gulpfile.js b/gulpfile.js index a7e26ee47..c0bc2694d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -57,7 +57,7 @@ module.exports = { gitCreateRC: gitTasks.createRC, gitRecompile: gitTasks.recompile, gitUpdateGithubPages: gitTasks.updateGithubPages, - typings: typings.typings, + typings: gulp.series(typings.typings, typings.msgTypings), package: packageTasks.package, checkLicenses: licenseTasks.checkLicenses }; diff --git a/package.json b/package.json index 463f17d06..537a07b47 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "main": "./index.js", "umd": "./blockly.min.js", "unpkg": "./blockly.min.js", - "types": "./blockly.d.ts", + "types": "./index.d.ts", "browser": { "./node.js": "./browser.js", "./core.js": "./core-browser.js", diff --git a/scripts/gulpfiles/package_tasks.js b/scripts/gulpfiles/package_tasks.js index c711231af..c69ce50e8 100644 --- a/scripts/gulpfiles/package_tasks.js +++ b/scripts/gulpfiles/package_tasks.js @@ -365,7 +365,7 @@ function packageReadme() { * The bundled declaration file is referenced in package.json in the types property. */ function packageDTS() { - return gulp.src('./typings/blockly.d.ts') + return gulp.src(['./typings/*.d.ts', './typings/msg/*.d.ts'], {base: './typings'}) .pipe(gulp.dest(`${packageDistribution}`)); }; diff --git a/scripts/gulpfiles/typings.js b/scripts/gulpfiles/typings.js index 86ba78b38..81dbe7ea6 100644 --- a/scripts/gulpfiles/typings.js +++ b/scripts/gulpfiles/typings.js @@ -62,8 +62,8 @@ function typings() { }); const srcs = [ - 'typings/parts/blockly-header.d.ts', - 'typings/parts/blockly-interfaces.d.ts', + 'typings/templates/blockly-header.template', + 'typings/templates/blockly-interfaces.template', `${tmpDir}/core/**`, `${tmpDir}/core/components/**`, `${tmpDir}/core/components/tree/**`, @@ -86,6 +86,19 @@ function typings() { }); }; +// Generates the TypeScript definition files (d.ts) for Blockly locales. +function msgTypings(cb) { + const template = fs.readFileSync(path.join('typings/templates/msg.template'), 'utf-8'); + const msgFiles = fs.readdirSync(path.join('msg', 'json')); + msgFiles.forEach(msg => { + const localeName = msg.substring(0, msg.indexOf('.json')); + const msgTypings = template.slice().replace(/<%= locale %>/gi, localeName); + fs.writeFileSync(path.join('typings', 'msg', localeName + '.d.ts'), msgTypings, 'utf-8'); + }) + cb(); +} + module.exports = { - typings: typings + typings: typings, + msgTypings: msgTypings }; diff --git a/typings/blocks.d.ts b/typings/blocks.d.ts new file mode 100644 index 000000000..851c08ddd --- /dev/null +++ b/typings/blocks.d.ts @@ -0,0 +1,15 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for Blockly Blocks. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import * as Blockly from './core'; +export = Blockly.Blocks; diff --git a/typings/core.d.ts b/typings/core.d.ts new file mode 100644 index 000000000..5453fd24a --- /dev/null +++ b/typings/core.d.ts @@ -0,0 +1,15 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for Blockly core. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import * as Blockly from './blockly'; +export = Blockly; diff --git a/typings/dart.d.ts b/typings/dart.d.ts new file mode 100644 index 000000000..c04eda2a8 --- /dev/null +++ b/typings/dart.d.ts @@ -0,0 +1,15 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Dart generator. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import * as Blockly from './core'; +export = Blockly.Generator; diff --git a/typings/index.d.ts b/typings/index.d.ts new file mode 100644 index 000000000..10324babc --- /dev/null +++ b/typings/index.d.ts @@ -0,0 +1,22 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for Blockly. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// +/// +/// +/// + +import * as Blockly from './core'; +import './blocks'; +import './javascript'; +import './msg/en'; + +export = Blockly; diff --git a/typings/javascript.d.ts b/typings/javascript.d.ts new file mode 100644 index 000000000..f1a14baaf --- /dev/null +++ b/typings/javascript.d.ts @@ -0,0 +1,15 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the JavaScript generator. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import * as Blockly from './core'; +export = Blockly.Generator; diff --git a/typings/lua.d.ts b/typings/lua.d.ts new file mode 100644 index 000000000..a5170bc82 --- /dev/null +++ b/typings/lua.d.ts @@ -0,0 +1,15 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Lua generator. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import * as Blockly from './core'; +export = Blockly.Generator; diff --git a/typings/msg/ab.d.ts b/typings/msg/ab.d.ts new file mode 100644 index 000000000..eb87b9bf3 --- /dev/null +++ b/typings/msg/ab.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ab locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ar.d.ts b/typings/msg/ar.d.ts new file mode 100644 index 000000000..e2435d743 --- /dev/null +++ b/typings/msg/ar.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ar locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/az.d.ts b/typings/msg/az.d.ts new file mode 100644 index 000000000..a87778131 --- /dev/null +++ b/typings/msg/az.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly az locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ba.d.ts b/typings/msg/ba.d.ts new file mode 100644 index 000000000..21cc21cc1 --- /dev/null +++ b/typings/msg/ba.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ba locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/bcc.d.ts b/typings/msg/bcc.d.ts new file mode 100644 index 000000000..e60e54df5 --- /dev/null +++ b/typings/msg/bcc.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly bcc locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/be-tarask.d.ts b/typings/msg/be-tarask.d.ts new file mode 100644 index 000000000..91640bb40 --- /dev/null +++ b/typings/msg/be-tarask.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly be-tarask locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/be.d.ts b/typings/msg/be.d.ts new file mode 100644 index 000000000..0857b6328 --- /dev/null +++ b/typings/msg/be.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly be locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/bg.d.ts b/typings/msg/bg.d.ts new file mode 100644 index 000000000..81905151a --- /dev/null +++ b/typings/msg/bg.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly bg locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/bn.d.ts b/typings/msg/bn.d.ts new file mode 100644 index 000000000..8207499d7 --- /dev/null +++ b/typings/msg/bn.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly bn locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/br.d.ts b/typings/msg/br.d.ts new file mode 100644 index 000000000..319e7ade3 --- /dev/null +++ b/typings/msg/br.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly br locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ca.d.ts b/typings/msg/ca.d.ts new file mode 100644 index 000000000..a89b9374b --- /dev/null +++ b/typings/msg/ca.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ca locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/constants.d.ts b/typings/msg/constants.d.ts new file mode 100644 index 000000000..41cb98e40 --- /dev/null +++ b/typings/msg/constants.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly constants locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/cs.d.ts b/typings/msg/cs.d.ts new file mode 100644 index 000000000..fd8998d2b --- /dev/null +++ b/typings/msg/cs.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly cs locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/da.d.ts b/typings/msg/da.d.ts new file mode 100644 index 000000000..9ae9615a0 --- /dev/null +++ b/typings/msg/da.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly da locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/de.d.ts b/typings/msg/de.d.ts new file mode 100644 index 000000000..84004ffdd --- /dev/null +++ b/typings/msg/de.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly de locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/diq.d.ts b/typings/msg/diq.d.ts new file mode 100644 index 000000000..2dadf5b23 --- /dev/null +++ b/typings/msg/diq.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly diq locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/dty.d.ts b/typings/msg/dty.d.ts new file mode 100644 index 000000000..995d93af2 --- /dev/null +++ b/typings/msg/dty.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly dty locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ee.d.ts b/typings/msg/ee.d.ts new file mode 100644 index 000000000..436e5b9ad --- /dev/null +++ b/typings/msg/ee.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ee locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/el.d.ts b/typings/msg/el.d.ts new file mode 100644 index 000000000..981a987b6 --- /dev/null +++ b/typings/msg/el.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly el locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/en-gb.d.ts b/typings/msg/en-gb.d.ts new file mode 100644 index 000000000..59032a4ff --- /dev/null +++ b/typings/msg/en-gb.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly en-gb locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/en.d.ts b/typings/msg/en.d.ts new file mode 100644 index 000000000..256aa7d44 --- /dev/null +++ b/typings/msg/en.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly en locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/eo.d.ts b/typings/msg/eo.d.ts new file mode 100644 index 000000000..a9b4004cc --- /dev/null +++ b/typings/msg/eo.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly eo locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/es.d.ts b/typings/msg/es.d.ts new file mode 100644 index 000000000..4dd0c585a --- /dev/null +++ b/typings/msg/es.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly es locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/et.d.ts b/typings/msg/et.d.ts new file mode 100644 index 000000000..01541ff11 --- /dev/null +++ b/typings/msg/et.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly et locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/eu.d.ts b/typings/msg/eu.d.ts new file mode 100644 index 000000000..1d0e85207 --- /dev/null +++ b/typings/msg/eu.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly eu locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/fa.d.ts b/typings/msg/fa.d.ts new file mode 100644 index 000000000..0e929790d --- /dev/null +++ b/typings/msg/fa.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly fa locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/fi.d.ts b/typings/msg/fi.d.ts new file mode 100644 index 000000000..dad65e992 --- /dev/null +++ b/typings/msg/fi.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly fi locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/fr.d.ts b/typings/msg/fr.d.ts new file mode 100644 index 000000000..6014c3b63 --- /dev/null +++ b/typings/msg/fr.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly fr locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/gl.d.ts b/typings/msg/gl.d.ts new file mode 100644 index 000000000..874c328f7 --- /dev/null +++ b/typings/msg/gl.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly gl locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/gor.d.ts b/typings/msg/gor.d.ts new file mode 100644 index 000000000..69c2999d4 --- /dev/null +++ b/typings/msg/gor.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly gor locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ha.d.ts b/typings/msg/ha.d.ts new file mode 100644 index 000000000..f5e92a6af --- /dev/null +++ b/typings/msg/ha.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ha locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/he.d.ts b/typings/msg/he.d.ts new file mode 100644 index 000000000..deb61f950 --- /dev/null +++ b/typings/msg/he.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly he locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/hi.d.ts b/typings/msg/hi.d.ts new file mode 100644 index 000000000..5abcff526 --- /dev/null +++ b/typings/msg/hi.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly hi locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/hrx.d.ts b/typings/msg/hrx.d.ts new file mode 100644 index 000000000..785916169 --- /dev/null +++ b/typings/msg/hrx.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly hrx locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/hu.d.ts b/typings/msg/hu.d.ts new file mode 100644 index 000000000..3f87f846d --- /dev/null +++ b/typings/msg/hu.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly hu locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/hy.d.ts b/typings/msg/hy.d.ts new file mode 100644 index 000000000..ee726e223 --- /dev/null +++ b/typings/msg/hy.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly hy locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ia.d.ts b/typings/msg/ia.d.ts new file mode 100644 index 000000000..b0324c970 --- /dev/null +++ b/typings/msg/ia.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ia locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/id.d.ts b/typings/msg/id.d.ts new file mode 100644 index 000000000..ddb57b7fb --- /dev/null +++ b/typings/msg/id.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly id locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ig.d.ts b/typings/msg/ig.d.ts new file mode 100644 index 000000000..90e5c7bec --- /dev/null +++ b/typings/msg/ig.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ig locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/is.d.ts b/typings/msg/is.d.ts new file mode 100644 index 000000000..88bfa07b8 --- /dev/null +++ b/typings/msg/is.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly is locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/it.d.ts b/typings/msg/it.d.ts new file mode 100644 index 000000000..0bff1ff74 --- /dev/null +++ b/typings/msg/it.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly it locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ja.d.ts b/typings/msg/ja.d.ts new file mode 100644 index 000000000..ed76fdf25 --- /dev/null +++ b/typings/msg/ja.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ja locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/kab.d.ts b/typings/msg/kab.d.ts new file mode 100644 index 000000000..98747fa49 --- /dev/null +++ b/typings/msg/kab.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly kab locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/kn.d.ts b/typings/msg/kn.d.ts new file mode 100644 index 000000000..9ac70f39f --- /dev/null +++ b/typings/msg/kn.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly kn locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ko.d.ts b/typings/msg/ko.d.ts new file mode 100644 index 000000000..344002e5d --- /dev/null +++ b/typings/msg/ko.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ko locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/lb.d.ts b/typings/msg/lb.d.ts new file mode 100644 index 000000000..0eee88ed5 --- /dev/null +++ b/typings/msg/lb.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly lb locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/lki.d.ts b/typings/msg/lki.d.ts new file mode 100644 index 000000000..9559de10e --- /dev/null +++ b/typings/msg/lki.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly lki locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/lo.d.ts b/typings/msg/lo.d.ts new file mode 100644 index 000000000..5a9071cea --- /dev/null +++ b/typings/msg/lo.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly lo locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/lrc.d.ts b/typings/msg/lrc.d.ts new file mode 100644 index 000000000..044134af1 --- /dev/null +++ b/typings/msg/lrc.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly lrc locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/lt.d.ts b/typings/msg/lt.d.ts new file mode 100644 index 000000000..9cc7516c1 --- /dev/null +++ b/typings/msg/lt.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly lt locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/lv.d.ts b/typings/msg/lv.d.ts new file mode 100644 index 000000000..88b41c7af --- /dev/null +++ b/typings/msg/lv.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly lv locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/mk.d.ts b/typings/msg/mk.d.ts new file mode 100644 index 000000000..951b027b7 --- /dev/null +++ b/typings/msg/mk.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly mk locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/mnw.d.ts b/typings/msg/mnw.d.ts new file mode 100644 index 000000000..962b8c5c9 --- /dev/null +++ b/typings/msg/mnw.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly mnw locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ms.d.ts b/typings/msg/ms.d.ts new file mode 100644 index 000000000..f154c4ef4 --- /dev/null +++ b/typings/msg/ms.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ms locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/msg.d.ts b/typings/msg/msg.d.ts new file mode 100644 index 000000000..65d7808ab --- /dev/null +++ b/typings/msg/msg.d.ts @@ -0,0 +1,444 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for Blockly Messages. + * @author samelh@google.com (Sam El-Husseini) + */ + + +declare namespace Blockly.Msg { + let ADD_COMMENT : string ; + let CANNOT_DELETE_VARIABLE_PROCEDURE : string ; + let CHANGE_VALUE_TITLE : string ; + let CLEAN_UP : string ; + let COLLAPSED_WARNINGS_WARNING : string ; + let COLLAPSE_ALL : string ; + let COLLAPSE_BLOCK : string ; + let COLOUR_BLEND_COLOUR1 : string ; + let COLOUR_BLEND_COLOUR2 : string ; + let COLOUR_BLEND_HELPURL : string ; + let COLOUR_BLEND_RATIO : string ; + let COLOUR_BLEND_TITLE : string ; + let COLOUR_BLEND_TOOLTIP : string ; + let COLOUR_HUE : string ; + let COLOUR_PICKER_HELPURL : string ; + let COLOUR_PICKER_TOOLTIP : string ; + let COLOUR_RANDOM_HELPURL : string ; + let COLOUR_RANDOM_TITLE : string ; + let COLOUR_RANDOM_TOOLTIP : string ; + let COLOUR_RGB_BLUE : string ; + let COLOUR_RGB_GREEN : string ; + let COLOUR_RGB_HELPURL : string ; + let COLOUR_RGB_RED : string ; + let COLOUR_RGB_TITLE : string ; + let COLOUR_RGB_TOOLTIP : string ; + let CONTROLS_FLOW_STATEMENTS_HELPURL : string ; + let CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK : string ; + let CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE : string ; + let CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK : string ; + let CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE : string ; + let CONTROLS_FLOW_STATEMENTS_WARNING : string ; + let CONTROLS_FOREACH_HELPURL : string ; + let CONTROLS_FOREACH_INPUT_DO : string ; + let CONTROLS_FOREACH_TITLE : string ; + let CONTROLS_FOREACH_TOOLTIP : string ; + let CONTROLS_FOR_HELPURL : string ; + let CONTROLS_FOR_INPUT_DO : string ; + let CONTROLS_FOR_TITLE : string ; + let CONTROLS_FOR_TOOLTIP : string ; + let CONTROLS_IF_ELSEIF_TITLE_ELSEIF : string ; + let CONTROLS_IF_ELSEIF_TOOLTIP : string ; + let CONTROLS_IF_ELSE_TITLE_ELSE : string ; + let CONTROLS_IF_ELSE_TOOLTIP : string ; + let CONTROLS_IF_HELPURL : string ; + let CONTROLS_IF_IF_TITLE_IF : string ; + let CONTROLS_IF_IF_TOOLTIP : string ; + let CONTROLS_IF_MSG_ELSE : string ; + let CONTROLS_IF_MSG_ELSEIF : string ; + let CONTROLS_IF_MSG_IF : string ; + let CONTROLS_IF_MSG_THEN : string ; + let CONTROLS_IF_TOOLTIP_1 : string ; + let CONTROLS_IF_TOOLTIP_2 : string ; + let CONTROLS_IF_TOOLTIP_3 : string ; + let CONTROLS_IF_TOOLTIP_4 : string ; + let CONTROLS_REPEAT_HELPURL : string ; + let CONTROLS_REPEAT_INPUT_DO : string ; + let CONTROLS_REPEAT_TITLE : string ; + let CONTROLS_REPEAT_TOOLTIP : string ; + let CONTROLS_WHILEUNTIL_HELPURL : string ; + let CONTROLS_WHILEUNTIL_INPUT_DO : string ; + let CONTROLS_WHILEUNTIL_OPERATOR_UNTIL : string ; + let CONTROLS_WHILEUNTIL_OPERATOR_WHILE : string ; + let CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL : string ; + let CONTROLS_WHILEUNTIL_TOOLTIP_WHILE : string ; + let DELETE_ALL_BLOCKS : string ; + let DELETE_BLOCK : string ; + let DELETE_VARIABLE : string ; + let DELETE_VARIABLE_CONFIRMATION : string ; + let DELETE_X_BLOCKS : string ; + let DISABLE_BLOCK : string ; + let DUPLICATE_BLOCK : string ; + let DUPLICATE_COMMENT : string ; + let ENABLE_BLOCK : string ; + let EXPAND_ALL : string ; + let EXPAND_BLOCK : string ; + let EXTERNAL_INPUTS : string ; + let HELP : string ; + let INLINE_INPUTS : string ; + let IOS_CANCEL : string ; + let IOS_ERROR : string ; + let IOS_OK : string ; + let IOS_PROCEDURES_ADD_INPUT : string ; + let IOS_PROCEDURES_ALLOW_STATEMENTS : string ; + let IOS_PROCEDURES_DUPLICATE_INPUTS_ERROR : string ; + let IOS_PROCEDURES_INPUTS : string ; + let IOS_VARIABLES_ADD_BUTTON : string ; + let IOS_VARIABLES_ADD_VARIABLE : string ; + let IOS_VARIABLES_DELETE_BUTTON : string ; + let IOS_VARIABLES_EMPTY_NAME_ERROR : string ; + let IOS_VARIABLES_RENAME_BUTTON : string ; + let IOS_VARIABLES_VARIABLE_NAME : string ; + let LISTS_CREATE_EMPTY_HELPURL : string ; + let LISTS_CREATE_EMPTY_TITLE : string ; + let LISTS_CREATE_EMPTY_TOOLTIP : string ; + let LISTS_CREATE_WITH_CONTAINER_TITLE_ADD : string ; + let LISTS_CREATE_WITH_CONTAINER_TOOLTIP : string ; + let LISTS_CREATE_WITH_HELPURL : string ; + let LISTS_CREATE_WITH_INPUT_WITH : string ; + let LISTS_CREATE_WITH_ITEM_TITLE : string ; + let LISTS_CREATE_WITH_ITEM_TOOLTIP : string ; + let LISTS_CREATE_WITH_TOOLTIP : string ; + let LISTS_GET_INDEX_FIRST : string ; + let LISTS_GET_INDEX_FROM_END : string ; + let LISTS_GET_INDEX_FROM_START : string ; + let LISTS_GET_INDEX_GET : string ; + let LISTS_GET_INDEX_GET_REMOVE : string ; + let LISTS_GET_INDEX_HELPURL : string ; + let LISTS_GET_INDEX_INPUT_IN_LIST : string ; + let LISTS_GET_INDEX_LAST : string ; + let LISTS_GET_INDEX_RANDOM : string ; + let LISTS_GET_INDEX_REMOVE : string ; + let LISTS_GET_INDEX_TAIL : string ; + let LISTS_GET_INDEX_TOOLTIP_GET_FIRST : string ; + let LISTS_GET_INDEX_TOOLTIP_GET_FROM : string ; + let LISTS_GET_INDEX_TOOLTIP_GET_LAST : string ; + let LISTS_GET_INDEX_TOOLTIP_GET_RANDOM : string ; + let LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST : string ; + let LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM : string ; + let LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST : string ; + let LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM : string ; + let LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST : string ; + let LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM : string ; + let LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST : string ; + let LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM : string ; + let LISTS_GET_SUBLIST_END_FROM_END : string ; + let LISTS_GET_SUBLIST_END_FROM_START : string ; + let LISTS_GET_SUBLIST_END_LAST : string ; + let LISTS_GET_SUBLIST_HELPURL : string ; + let LISTS_GET_SUBLIST_INPUT_IN_LIST : string ; + let LISTS_GET_SUBLIST_START_FIRST : string ; + let LISTS_GET_SUBLIST_START_FROM_END : string ; + let LISTS_GET_SUBLIST_START_FROM_START : string ; + let LISTS_GET_SUBLIST_TAIL : string ; + let LISTS_GET_SUBLIST_TOOLTIP : string ; + let LISTS_HUE : string ; + let LISTS_INDEX_FROM_END_TOOLTIP : string ; + let LISTS_INDEX_FROM_START_TOOLTIP : string ; + let LISTS_INDEX_OF_FIRST : string ; + let LISTS_INDEX_OF_HELPURL : string ; + let LISTS_INDEX_OF_INPUT_IN_LIST : string ; + let LISTS_INDEX_OF_LAST : string ; + let LISTS_INDEX_OF_TOOLTIP : string ; + let LISTS_INLIST : string ; + let LISTS_ISEMPTY_HELPURL : string ; + let LISTS_ISEMPTY_TITLE : string ; + let LISTS_ISEMPTY_TOOLTIP : string ; + let LISTS_LENGTH_HELPURL : string ; + let LISTS_LENGTH_TITLE : string ; + let LISTS_LENGTH_TOOLTIP : string ; + let LISTS_REPEAT_HELPURL : string ; + let LISTS_REPEAT_TITLE : string ; + let LISTS_REPEAT_TOOLTIP : string ; + let LISTS_REVERSE_HELPURL : string ; + let LISTS_REVERSE_MESSAGE0 : string ; + let LISTS_REVERSE_TOOLTIP : string ; + let LISTS_SET_INDEX_HELPURL : string ; + let LISTS_SET_INDEX_INPUT_IN_LIST : string ; + let LISTS_SET_INDEX_INPUT_TO : string ; + let LISTS_SET_INDEX_INSERT : string ; + let LISTS_SET_INDEX_SET : string ; + let LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST : string ; + let LISTS_SET_INDEX_TOOLTIP_INSERT_FROM : string ; + let LISTS_SET_INDEX_TOOLTIP_INSERT_LAST : string ; + let LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM : string ; + let LISTS_SET_INDEX_TOOLTIP_SET_FIRST : string ; + let LISTS_SET_INDEX_TOOLTIP_SET_FROM : string ; + let LISTS_SET_INDEX_TOOLTIP_SET_LAST : string ; + let LISTS_SET_INDEX_TOOLTIP_SET_RANDOM : string ; + let LISTS_SORT_HELPURL : string ; + let LISTS_SORT_ORDER_ASCENDING : string ; + let LISTS_SORT_ORDER_DESCENDING : string ; + let LISTS_SORT_TITLE : string ; + let LISTS_SORT_TOOLTIP : string ; + let LISTS_SORT_TYPE_IGNORECASE : string ; + let LISTS_SORT_TYPE_NUMERIC : string ; + let LISTS_SORT_TYPE_TEXT : string ; + let LISTS_SPLIT_HELPURL : string ; + let LISTS_SPLIT_LIST_FROM_TEXT : string ; + let LISTS_SPLIT_TEXT_FROM_LIST : string ; + let LISTS_SPLIT_TOOLTIP_JOIN : string ; + let LISTS_SPLIT_TOOLTIP_SPLIT : string ; + let LISTS_SPLIT_WITH_DELIMITER : string ; + let LOGIC_BOOLEAN_FALSE : string ; + let LOGIC_BOOLEAN_HELPURL : string ; + let LOGIC_BOOLEAN_TOOLTIP : string ; + let LOGIC_BOOLEAN_TRUE : string ; + let LOGIC_COMPARE_HELPURL : string ; + let LOGIC_COMPARE_TOOLTIP_EQ : string ; + let LOGIC_COMPARE_TOOLTIP_GT : string ; + let LOGIC_COMPARE_TOOLTIP_GTE : string ; + let LOGIC_COMPARE_TOOLTIP_LT : string ; + let LOGIC_COMPARE_TOOLTIP_LTE : string ; + let LOGIC_COMPARE_TOOLTIP_NEQ : string ; + let LOGIC_HUE : string ; + let LOGIC_NEGATE_HELPURL : string ; + let LOGIC_NEGATE_TITLE : string ; + let LOGIC_NEGATE_TOOLTIP : string ; + let LOGIC_NULL : string ; + let LOGIC_NULL_HELPURL : string ; + let LOGIC_NULL_TOOLTIP : string ; + let LOGIC_OPERATION_AND : string ; + let LOGIC_OPERATION_HELPURL : string ; + let LOGIC_OPERATION_OR : string ; + let LOGIC_OPERATION_TOOLTIP_AND : string ; + let LOGIC_OPERATION_TOOLTIP_OR : string ; + let LOGIC_TERNARY_CONDITION : string ; + let LOGIC_TERNARY_HELPURL : string ; + let LOGIC_TERNARY_IF_FALSE : string ; + let LOGIC_TERNARY_IF_TRUE : string ; + let LOGIC_TERNARY_TOOLTIP : string ; + let LOOPS_HUE : string ; + let MATH_ADDITION_SYMBOL : string ; + let MATH_ARITHMETIC_HELPURL : string ; + let MATH_ARITHMETIC_TOOLTIP_ADD : string ; + let MATH_ARITHMETIC_TOOLTIP_DIVIDE : string ; + let MATH_ARITHMETIC_TOOLTIP_MINUS : string ; + let MATH_ARITHMETIC_TOOLTIP_MULTIPLY : string ; + let MATH_ARITHMETIC_TOOLTIP_POWER : string ; + let MATH_ATAN2_HELPURL : string ; + let MATH_ATAN2_TITLE : string ; + let MATH_ATAN2_TOOLTIP : string ; + let MATH_CHANGE_HELPURL : string ; + let MATH_CHANGE_TITLE : string ; + let MATH_CHANGE_TITLE_ITEM : string ; + let MATH_CHANGE_TOOLTIP : string ; + let MATH_CONSTANT_HELPURL : string ; + let MATH_CONSTANT_TOOLTIP : string ; + let MATH_CONSTRAIN_HELPURL : string ; + let MATH_CONSTRAIN_TITLE : string ; + let MATH_CONSTRAIN_TOOLTIP : string ; + let MATH_DIVISION_SYMBOL : string ; + let MATH_HUE : string ; + let MATH_IS_DIVISIBLE_BY : string ; + let MATH_IS_EVEN : string ; + let MATH_IS_NEGATIVE : string ; + let MATH_IS_ODD : string ; + let MATH_IS_POSITIVE : string ; + let MATH_IS_PRIME : string ; + let MATH_IS_TOOLTIP : string ; + let MATH_IS_WHOLE : string ; + let MATH_MODULO_HELPURL : string ; + let MATH_MODULO_TITLE : string ; + let MATH_MODULO_TOOLTIP : string ; + let MATH_MULTIPLICATION_SYMBOL : string ; + let MATH_NUMBER_HELPURL : string ; + let MATH_NUMBER_TOOLTIP : string ; + let MATH_ONLIST_HELPURL : string ; + let MATH_ONLIST_OPERATOR_AVERAGE : string ; + let MATH_ONLIST_OPERATOR_MAX : string ; + let MATH_ONLIST_OPERATOR_MEDIAN : string ; + let MATH_ONLIST_OPERATOR_MIN : string ; + let MATH_ONLIST_OPERATOR_MODE : string ; + let MATH_ONLIST_OPERATOR_RANDOM : string ; + let MATH_ONLIST_OPERATOR_STD_DEV : string ; + let MATH_ONLIST_OPERATOR_SUM : string ; + let MATH_ONLIST_TOOLTIP_AVERAGE : string ; + let MATH_ONLIST_TOOLTIP_MAX : string ; + let MATH_ONLIST_TOOLTIP_MEDIAN : string ; + let MATH_ONLIST_TOOLTIP_MIN : string ; + let MATH_ONLIST_TOOLTIP_MODE : string ; + let MATH_ONLIST_TOOLTIP_RANDOM : string ; + let MATH_ONLIST_TOOLTIP_STD_DEV : string ; + let MATH_ONLIST_TOOLTIP_SUM : string ; + let MATH_POWER_SYMBOL : string ; + let MATH_RANDOM_FLOAT_HELPURL : string ; + let MATH_RANDOM_FLOAT_TITLE_RANDOM : string ; + let MATH_RANDOM_FLOAT_TOOLTIP : string ; + let MATH_RANDOM_INT_HELPURL : string ; + let MATH_RANDOM_INT_TITLE : string ; + let MATH_RANDOM_INT_TOOLTIP : string ; + let MATH_ROUND_HELPURL : string ; + let MATH_ROUND_OPERATOR_ROUND : string ; + let MATH_ROUND_OPERATOR_ROUNDDOWN : string ; + let MATH_ROUND_OPERATOR_ROUNDUP : string ; + let MATH_ROUND_TOOLTIP : string ; + let MATH_SINGLE_HELPURL : string ; + let MATH_SINGLE_OP_ABSOLUTE : string ; + let MATH_SINGLE_OP_ROOT : string ; + let MATH_SINGLE_TOOLTIP_ABS : string ; + let MATH_SINGLE_TOOLTIP_EXP : string ; + let MATH_SINGLE_TOOLTIP_LN : string ; + let MATH_SINGLE_TOOLTIP_LOG10 : string ; + let MATH_SINGLE_TOOLTIP_NEG : string ; + let MATH_SINGLE_TOOLTIP_POW10 : string ; + let MATH_SINGLE_TOOLTIP_ROOT : string ; + let MATH_SUBTRACTION_SYMBOL : string ; + let MATH_TRIG_ACOS : string ; + let MATH_TRIG_ASIN : string ; + let MATH_TRIG_ATAN : string ; + let MATH_TRIG_COS : string ; + let MATH_TRIG_HELPURL : string ; + let MATH_TRIG_SIN : string ; + let MATH_TRIG_TAN : string ; + let MATH_TRIG_TOOLTIP_ACOS : string ; + let MATH_TRIG_TOOLTIP_ASIN : string ; + let MATH_TRIG_TOOLTIP_ATAN : string ; + let MATH_TRIG_TOOLTIP_COS : string ; + let MATH_TRIG_TOOLTIP_SIN : string ; + let MATH_TRIG_TOOLTIP_TAN : string ; + let NEW_COLOUR_VARIABLE : string ; + let NEW_NUMBER_VARIABLE : string ; + let NEW_STRING_VARIABLE : string ; + let NEW_VARIABLE : string ; + let NEW_VARIABLE_TITLE : string ; + let NEW_VARIABLE_TYPE_TITLE : string ; + let ORDINAL_NUMBER_SUFFIX : string ; + let PROCEDURES_ALLOW_STATEMENTS : string ; + let PROCEDURES_BEFORE_PARAMS : string ; + let PROCEDURES_CALLNORETURN_HELPURL : string ; + let PROCEDURES_CALLNORETURN_TOOLTIP : string ; + let PROCEDURES_CALLRETURN_HELPURL : string ; + let PROCEDURES_CALLRETURN_TOOLTIP : string ; + let PROCEDURES_CALL_BEFORE_PARAMS : string ; + let PROCEDURES_CREATE_DO : string ; + let PROCEDURES_DEFNORETURN_COMMENT : string ; + let PROCEDURES_DEFNORETURN_DO : string ; + let PROCEDURES_DEFNORETURN_HELPURL : string ; + let PROCEDURES_DEFNORETURN_PROCEDURE : string ; + let PROCEDURES_DEFNORETURN_TITLE : string ; + let PROCEDURES_DEFNORETURN_TOOLTIP : string ; + let PROCEDURES_DEFRETURN_COMMENT : string ; + let PROCEDURES_DEFRETURN_DO : string ; + let PROCEDURES_DEFRETURN_HELPURL : string ; + let PROCEDURES_DEFRETURN_PROCEDURE : string ; + let PROCEDURES_DEFRETURN_RETURN : string ; + let PROCEDURES_DEFRETURN_TITLE : string ; + let PROCEDURES_DEFRETURN_TOOLTIP : string ; + let PROCEDURES_DEF_DUPLICATE_WARNING : string ; + let PROCEDURES_HIGHLIGHT_DEF : string ; + let PROCEDURES_HUE : string ; + let PROCEDURES_IFRETURN_HELPURL : string ; + let PROCEDURES_IFRETURN_TOOLTIP : string ; + let PROCEDURES_IFRETURN_WARNING : string ; + let PROCEDURES_MUTATORARG_TITLE : string ; + let PROCEDURES_MUTATORARG_TOOLTIP : string ; + let PROCEDURES_MUTATORCONTAINER_TITLE : string ; + let PROCEDURES_MUTATORCONTAINER_TOOLTIP : string ; + let REDO : string ; + let REMOVE_COMMENT : string ; + let RENAME_VARIABLE : string ; + let RENAME_VARIABLE_TITLE : string ; + let TEXTS_HUE : string ; + let TEXT_APPEND_HELPURL : string ; + let TEXT_APPEND_TITLE : string ; + let TEXT_APPEND_TOOLTIP : string ; + let TEXT_APPEND_VARIABLE : string ; + let TEXT_CHANGECASE_HELPURL : string ; + let TEXT_CHANGECASE_OPERATOR_LOWERCASE : string ; + let TEXT_CHANGECASE_OPERATOR_TITLECASE : string ; + let TEXT_CHANGECASE_OPERATOR_UPPERCASE : string ; + let TEXT_CHANGECASE_TOOLTIP : string ; + let TEXT_CHARAT_FIRST : string ; + let TEXT_CHARAT_FROM_END : string ; + let TEXT_CHARAT_FROM_START : string ; + let TEXT_CHARAT_HELPURL : string ; + let TEXT_CHARAT_LAST : string ; + let TEXT_CHARAT_RANDOM : string ; + let TEXT_CHARAT_TAIL : string ; + let TEXT_CHARAT_TITLE : string ; + let TEXT_CHARAT_TOOLTIP : string ; + let TEXT_COUNT_HELPURL : string ; + let TEXT_COUNT_MESSAGE0 : string ; + let TEXT_COUNT_TOOLTIP : string ; + let TEXT_CREATE_JOIN_ITEM_TITLE_ITEM : string ; + let TEXT_CREATE_JOIN_ITEM_TOOLTIP : string ; + let TEXT_CREATE_JOIN_TITLE_JOIN : string ; + let TEXT_CREATE_JOIN_TOOLTIP : string ; + let TEXT_GET_SUBSTRING_END_FROM_END : string ; + let TEXT_GET_SUBSTRING_END_FROM_START : string ; + let TEXT_GET_SUBSTRING_END_LAST : string ; + let TEXT_GET_SUBSTRING_HELPURL : string ; + let TEXT_GET_SUBSTRING_INPUT_IN_TEXT : string ; + let TEXT_GET_SUBSTRING_START_FIRST : string ; + let TEXT_GET_SUBSTRING_START_FROM_END : string ; + let TEXT_GET_SUBSTRING_START_FROM_START : string ; + let TEXT_GET_SUBSTRING_TAIL : string ; + let TEXT_GET_SUBSTRING_TOOLTIP : string ; + let TEXT_INDEXOF_HELPURL : string ; + let TEXT_INDEXOF_OPERATOR_FIRST : string ; + let TEXT_INDEXOF_OPERATOR_LAST : string ; + let TEXT_INDEXOF_TITLE : string ; + let TEXT_INDEXOF_TOOLTIP : string ; + let TEXT_ISEMPTY_HELPURL : string ; + let TEXT_ISEMPTY_TITLE : string ; + let TEXT_ISEMPTY_TOOLTIP : string ; + let TEXT_JOIN_HELPURL : string ; + let TEXT_JOIN_TITLE_CREATEWITH : string ; + let TEXT_JOIN_TOOLTIP : string ; + let TEXT_LENGTH_HELPURL : string ; + let TEXT_LENGTH_TITLE : string ; + let TEXT_LENGTH_TOOLTIP : string ; + let TEXT_PRINT_HELPURL : string ; + let TEXT_PRINT_TITLE : string ; + let TEXT_PRINT_TOOLTIP : string ; + let TEXT_PROMPT_HELPURL : string ; + let TEXT_PROMPT_TOOLTIP_NUMBER : string ; + let TEXT_PROMPT_TOOLTIP_TEXT : string ; + let TEXT_PROMPT_TYPE_NUMBER : string ; + let TEXT_PROMPT_TYPE_TEXT : string ; + let TEXT_REPLACE_HELPURL : string ; + let TEXT_REPLACE_MESSAGE0 : string ; + let TEXT_REPLACE_TOOLTIP : string ; + let TEXT_REVERSE_HELPURL : string ; + let TEXT_REVERSE_MESSAGE0 : string ; + let TEXT_REVERSE_TOOLTIP : string ; + let TEXT_TEXT_HELPURL : string ; + let TEXT_TEXT_TOOLTIP : string ; + let TEXT_TRIM_HELPURL : string ; + let TEXT_TRIM_OPERATOR_BOTH : string ; + let TEXT_TRIM_OPERATOR_LEFT : string ; + let TEXT_TRIM_OPERATOR_RIGHT : string ; + let TEXT_TRIM_TOOLTIP : string ; + let TODAY : string ; + let UNDO : string ; + let UNNAMED_KEY : string ; + let VARIABLES_DEFAULT_NAME : string ; + let VARIABLES_DYNAMIC_HUE : string ; + let VARIABLES_GET_CREATE_SET : string ; + let VARIABLES_GET_HELPURL : string ; + let VARIABLES_GET_TOOLTIP : string ; + let VARIABLES_HUE : string ; + let VARIABLES_SET : string ; + let VARIABLES_SET_CREATE_GET : string ; + let VARIABLES_SET_HELPURL : string ; + let VARIABLES_SET_TOOLTIP : string ; + let VARIABLE_ALREADY_EXISTS : string ; + let VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE : string ; + let WORKSPACE_ARIA_LABEL : string ; + let WORKSPACE_COMMENT_DEFAULT_TEXT : string ; +} + diff --git a/typings/msg/nb.d.ts b/typings/msg/nb.d.ts new file mode 100644 index 000000000..42aaa1b25 --- /dev/null +++ b/typings/msg/nb.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly nb locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/nl.d.ts b/typings/msg/nl.d.ts new file mode 100644 index 000000000..5d383fb0c --- /dev/null +++ b/typings/msg/nl.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly nl locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/oc.d.ts b/typings/msg/oc.d.ts new file mode 100644 index 000000000..f8eabb76e --- /dev/null +++ b/typings/msg/oc.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly oc locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/pl.d.ts b/typings/msg/pl.d.ts new file mode 100644 index 000000000..957f3820d --- /dev/null +++ b/typings/msg/pl.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly pl locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/pms.d.ts b/typings/msg/pms.d.ts new file mode 100644 index 000000000..35df33e31 --- /dev/null +++ b/typings/msg/pms.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly pms locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/pt-br.d.ts b/typings/msg/pt-br.d.ts new file mode 100644 index 000000000..065d639cd --- /dev/null +++ b/typings/msg/pt-br.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly pt-br locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/pt.d.ts b/typings/msg/pt.d.ts new file mode 100644 index 000000000..f89879cad --- /dev/null +++ b/typings/msg/pt.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly pt locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/qqq.d.ts b/typings/msg/qqq.d.ts new file mode 100644 index 000000000..4c58a607f --- /dev/null +++ b/typings/msg/qqq.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly qqq locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ro.d.ts b/typings/msg/ro.d.ts new file mode 100644 index 000000000..f2183fa49 --- /dev/null +++ b/typings/msg/ro.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ro locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ru.d.ts b/typings/msg/ru.d.ts new file mode 100644 index 000000000..95ffc8300 --- /dev/null +++ b/typings/msg/ru.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ru locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/sc.d.ts b/typings/msg/sc.d.ts new file mode 100644 index 000000000..2d5afcbde --- /dev/null +++ b/typings/msg/sc.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly sc locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/sd.d.ts b/typings/msg/sd.d.ts new file mode 100644 index 000000000..cafc97893 --- /dev/null +++ b/typings/msg/sd.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly sd locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/shn.d.ts b/typings/msg/shn.d.ts new file mode 100644 index 000000000..07a531329 --- /dev/null +++ b/typings/msg/shn.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly shn locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/sk.d.ts b/typings/msg/sk.d.ts new file mode 100644 index 000000000..3c26e48bc --- /dev/null +++ b/typings/msg/sk.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly sk locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/skr-arab.d.ts b/typings/msg/skr-arab.d.ts new file mode 100644 index 000000000..4ddb30fd8 --- /dev/null +++ b/typings/msg/skr-arab.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly skr-arab locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/sl.d.ts b/typings/msg/sl.d.ts new file mode 100644 index 000000000..51f1f568f --- /dev/null +++ b/typings/msg/sl.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly sl locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/sq.d.ts b/typings/msg/sq.d.ts new file mode 100644 index 000000000..e7997e2f4 --- /dev/null +++ b/typings/msg/sq.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly sq locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/sr-latn.d.ts b/typings/msg/sr-latn.d.ts new file mode 100644 index 000000000..f9bf0645e --- /dev/null +++ b/typings/msg/sr-latn.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly sr-latn locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/sr.d.ts b/typings/msg/sr.d.ts new file mode 100644 index 000000000..7d6ea16a5 --- /dev/null +++ b/typings/msg/sr.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly sr locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/sv.d.ts b/typings/msg/sv.d.ts new file mode 100644 index 000000000..11018f261 --- /dev/null +++ b/typings/msg/sv.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly sv locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/synonyms.d.ts b/typings/msg/synonyms.d.ts new file mode 100644 index 000000000..93e21974f --- /dev/null +++ b/typings/msg/synonyms.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly synonyms locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ta.d.ts b/typings/msg/ta.d.ts new file mode 100644 index 000000000..d74bd3c48 --- /dev/null +++ b/typings/msg/ta.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ta locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/tcy.d.ts b/typings/msg/tcy.d.ts new file mode 100644 index 000000000..64278359d --- /dev/null +++ b/typings/msg/tcy.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly tcy locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/te.d.ts b/typings/msg/te.d.ts new file mode 100644 index 000000000..c7acfb0c8 --- /dev/null +++ b/typings/msg/te.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly te locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/th.d.ts b/typings/msg/th.d.ts new file mode 100644 index 000000000..bf77eae8b --- /dev/null +++ b/typings/msg/th.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly th locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/tl.d.ts b/typings/msg/tl.d.ts new file mode 100644 index 000000000..0d51a38f3 --- /dev/null +++ b/typings/msg/tl.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly tl locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/tlh.d.ts b/typings/msg/tlh.d.ts new file mode 100644 index 000000000..5eb07eb8d --- /dev/null +++ b/typings/msg/tlh.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly tlh locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/tr.d.ts b/typings/msg/tr.d.ts new file mode 100644 index 000000000..2b1a29a02 --- /dev/null +++ b/typings/msg/tr.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly tr locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ug-arab.d.ts b/typings/msg/ug-arab.d.ts new file mode 100644 index 000000000..f9445a560 --- /dev/null +++ b/typings/msg/ug-arab.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ug-arab locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/uk.d.ts b/typings/msg/uk.d.ts new file mode 100644 index 000000000..1250e6cb1 --- /dev/null +++ b/typings/msg/uk.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly uk locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/ur.d.ts b/typings/msg/ur.d.ts new file mode 100644 index 000000000..b944aad7f --- /dev/null +++ b/typings/msg/ur.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly ur locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/vi.d.ts b/typings/msg/vi.d.ts new file mode 100644 index 000000000..86a0e7d6f --- /dev/null +++ b/typings/msg/vi.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly vi locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/xmf.d.ts b/typings/msg/xmf.d.ts new file mode 100644 index 000000000..e230058ac --- /dev/null +++ b/typings/msg/xmf.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly xmf locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/yo.d.ts b/typings/msg/yo.d.ts new file mode 100644 index 000000000..29120ab8d --- /dev/null +++ b/typings/msg/yo.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly yo locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/zh-hans.d.ts b/typings/msg/zh-hans.d.ts new file mode 100644 index 000000000..938f55356 --- /dev/null +++ b/typings/msg/zh-hans.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly zh-hans locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/msg/zh-hant.d.ts b/typings/msg/zh-hant.d.ts new file mode 100644 index 000000000..f2917aac6 --- /dev/null +++ b/typings/msg/zh-hant.d.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly zh-hant locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + diff --git a/typings/php.d.ts b/typings/php.d.ts new file mode 100644 index 000000000..75f2ef693 --- /dev/null +++ b/typings/php.d.ts @@ -0,0 +1,15 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the PHP generator. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import * as Blockly from './core'; +export = Blockly.Generator; diff --git a/typings/python.d.ts b/typings/python.d.ts new file mode 100644 index 000000000..ba328145a --- /dev/null +++ b/typings/python.d.ts @@ -0,0 +1,15 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Python generator. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import * as Blockly from './core'; +export = Blockly.Generator; diff --git a/typings/parts/blockly-header.d.ts b/typings/templates/blockly-header.template similarity index 100% rename from typings/parts/blockly-header.d.ts rename to typings/templates/blockly-header.template diff --git a/typings/parts/blockly-interfaces.d.ts b/typings/templates/blockly-interfaces.template similarity index 100% rename from typings/parts/blockly-interfaces.d.ts rename to typings/templates/blockly-interfaces.template diff --git a/typings/templates/msg.template b/typings/templates/msg.template new file mode 100644 index 000000000..7377e2543 --- /dev/null +++ b/typings/templates/msg.template @@ -0,0 +1,16 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Type definitions for the Blockly <%= locale %> locale. + * @author samelh@google.com (Sam El-Husseini) + */ + +/// + +import BlocklyMsg = Blockly.Msg; +export = BlocklyMsg; + From 3a902ee970e1f20054f825def2a20b4e664927ca Mon Sep 17 00:00:00 2001 From: alschmiedt Date: Wed, 15 Apr 2020 10:10:21 -0700 Subject: [PATCH 017/139] Update ast node (#3808) * Update ast node --- core/gesture.js | 2 +- core/keyboard_nav/ast_node.js | 18 ++ core/keyboard_nav/navigation.js | 23 +- core/renderers/common/marker_svg.js | 225 ++++++++------ core/renderers/zelos/marker_svg.js | 43 ++- tests/mocha/astnode_test.js | 446 ++++++++++++---------------- 6 files changed, 359 insertions(+), 398 deletions(-) diff --git a/core/gesture.js b/core/gesture.js index 3de14fc38..e7f99102f 100644 --- a/core/gesture.js +++ b/core/gesture.js @@ -489,7 +489,7 @@ Blockly.Gesture.prototype.doStart = function(e) { e.shiftKey && this.targetBlock_.workspace.keyboardAccessibilityMode) { this.creatorWorkspace_.getCursor().setCurNode( - Blockly.navigation.getTopNode(this.targetBlock_)); + Blockly.ASTNode.createTopNode(this.targetBlock_)); } else { this.targetBlock_.select(); } diff --git a/core/keyboard_nav/ast_node.js b/core/keyboard_nav/ast_node.js index 4f111b84c..cd9c94c67 100644 --- a/core/keyboard_nav/ast_node.js +++ b/core/keyboard_nav/ast_node.js @@ -199,6 +199,24 @@ Blockly.ASTNode.createWorkspaceNode = function(workspace, wsCoordinate) { Blockly.ASTNode.types.WORKSPACE, workspace, params); }; +/** + * Creates an AST node for the top position on a block. + * This is either an output connection, previous connection, or block. + * @param {!Blockly.Block} block The block to find the top most AST node on. + * @return {Blockly.ASTNode} The AST node holding the top most position on the + * block. + */ +Blockly.ASTNode.createTopNode = function(block) { + var astNode; + var topConnection = block.previousConnection || block.outputConnection; + if (topConnection) { + astNode = Blockly.ASTNode.createConnectionNode(topConnection); + } else { + astNode = Blockly.ASTNode.createBlockNode(block); + } + return astNode; +}; + /** * Parse the optional parameters. * @param {Object} params The user specified parameters. diff --git a/core/keyboard_nav/navigation.js b/core/keyboard_nav/navigation.js index 385ef676a..d37fe9973 100644 --- a/core/keyboard_nav/navigation.js +++ b/core/keyboard_nav/navigation.js @@ -167,7 +167,7 @@ Blockly.navigation.focusWorkspace_ = function() { Blockly.navigation.resetFlyout_(reset); Blockly.navigation.currentState_ = Blockly.navigation.STATE_WS; if (topBlocks.length > 0) { - cursor.setCurNode(Blockly.navigation.getTopNode(topBlocks[0])); + cursor.setCurNode(Blockly.ASTNode.createTopNode(topBlocks[0])); } else { // TODO: Find the center of the visible workspace. var wsCoord = new Blockly.utils.Coordinate(100, 100); @@ -230,7 +230,7 @@ Blockly.navigation.insertFromFlyout = function() { } Blockly.navigation.focusWorkspace_(); - workspace.getCursor().setCurNode(Blockly.navigation.getTopNode(newBlock)); + workspace.getCursor().setCurNode(Blockly.ASTNode.createTopNode(newBlock)); Blockly.navigation.removeMark_(); }; @@ -606,25 +606,6 @@ Blockly.navigation.setState = function(newState) { Blockly.navigation.currentState_ = newState; }; -/** - * Gets the top node on a block. - * This is either the previous connection, output connection or the block. - * @param {!Blockly.Block} block The block to find the top most AST node on. - * @return {Blockly.ASTNode} The AST node holding the top most node on the - * block. - * @package - */ -Blockly.navigation.getTopNode = function(block) { - var astNode; - var topConnection = block.previousConnection || block.outputConnection; - if (topConnection) { - astNode = Blockly.ASTNode.createConnectionNode(topConnection); - } else { - astNode = Blockly.ASTNode.createBlockNode(block); - } - return astNode; -}; - /** * Before a block is deleted move the cursor to the appropriate position. * @param {!Blockly.Block} deletedBlock The block that is being deleted. diff --git a/core/renderers/common/marker_svg.js b/core/renderers/common/marker_svg.js index a9b005b88..ce3225890 100644 --- a/core/renderers/common/marker_svg.js +++ b/core/renderers/common/marker_svg.js @@ -85,8 +85,7 @@ Blockly.blockRendering.MarkerSvg.MARKER_CLASS = 'blocklyMarker'; /** * What we multiply the height by to get the height of the marker. * Only used for the block and block connections. - * @type {number} - * @const + * @const {number} */ Blockly.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER = 3 / 4; @@ -98,6 +97,14 @@ Blockly.blockRendering.MarkerSvg.prototype.getSvgRoot = function() { return this.svgGroup_; }; +/** + * Get the marker. + * @return {!Blockly.Marker} The marker to draw for. + */ +Blockly.blockRendering.MarkerSvg.prototype.getMarker = function() { + return this.marker_; +}; + /** * True if the marker should be drawn as a cursor, false otherwise. * A cursor is drawn as a flashing line. A marker is drawn as a solid line. @@ -123,7 +130,6 @@ Blockly.blockRendering.MarkerSvg.prototype.createDom = function() { }, null); this.createDomInternal_(); - this.applyColour_(); return this.svgGroup_; }; @@ -149,6 +155,61 @@ Blockly.blockRendering.MarkerSvg.prototype.setParent_ = function(newParent) { this.parent_ = newParent; }; +/** + * Update the marker. + * @param {Blockly.ASTNode} oldNode The previous node the marker was on or null. + * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for. + */ +Blockly.blockRendering.MarkerSvg.prototype.draw = function(oldNode, curNode) { + if (!curNode) { + this.hide(); + return; + } + + this.constants_ = this.workspace_.getRenderer().getConstants(); + + var defaultColour = this.isCursor() ? this.constants_.CURSOR_COLOUR : + this.constants_.MARKER_COLOUR; + this.colour_ = this.marker_.colour || defaultColour; + this.applyColour_(curNode); + + this.showAtLocation_(curNode); + + this.fireMarkerEvent_(oldNode, curNode); + + // Ensures the marker will be visible immediately after the move. + var animate = this.currentMarkerSvg.childNodes[0]; + if (animate !== undefined) { + animate.beginElement && animate.beginElement(); + } +}; + + +/** + * Update the marker's visible state based on the type of curNode.. + * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @protected + */ +Blockly.blockRendering.MarkerSvg.prototype.showAtLocation_ = function(curNode) { + if (curNode.getType() == Blockly.ASTNode.types.BLOCK) { + this.showWithBlock_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.OUTPUT) { + this.showWithOutput_(curNode); + } else if (curNode.getLocation().type == Blockly.INPUT_VALUE) { + this.showWithInput_(curNode); + } else if (curNode.getLocation().type == Blockly.NEXT_STATEMENT) { + this.showWithNext_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.PREVIOUS) { + this.showWithPrevious_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.FIELD) { + this.showWithField_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.WORKSPACE) { + this.showWithCoordinates_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.STACK) { + this.showWithStack_(curNode); + } +}; + /************************** * Display **************************/ @@ -156,13 +217,12 @@ Blockly.blockRendering.MarkerSvg.prototype.setParent_ = function(newParent) { /** * Show the marker as a combination of the previous connection and block, * the output connection and block, or just the block. - * @param {Blockly.BlockSvg} block The block the marker is currently on. - * @protected + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @private */ -Blockly.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_ = function(block) { - if (!block) { - return; - } +Blockly.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_ = function( + curNode) { + var block = /** @type {!Blockly.BlockSvg} */ (curNode.getSourceBlock()); var width = block.width; var height = block.height; var markerHeight = height * Blockly.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER; @@ -177,18 +237,46 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_ = function(b } else { this.positionBlock_(width, markerOffset, markerHeight); } - this.setParent_(block); this.showCurrent_(); }; /** - * Show the visual representation of a workspace coordinate. - * This is a horizontal line. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * Position and display the marker for a block. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.showWithCoordinates_ = function(curNode) { +Blockly.blockRendering.MarkerSvg.prototype.showWithBlock_ = function(curNode) { + this.showWithBlockPrevOutput_(curNode); +}; + +/** + * Position and display the marker for a previous connection. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @protected + */ +Blockly.blockRendering.MarkerSvg.prototype.showWithPrevious_ = function( + curNode) { + this.showWithBlockPrevOutput_(curNode); +}; + +/** + * Position and display the marker for an output connection. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @protected + */ +Blockly.blockRendering.MarkerSvg.prototype.showWithOutput_ = function(curNode) { + this.showWithBlockPrevOutput_(curNode); +}; + +/** + * Position and display the marker for a workspace coordinate. + * This is a horizontal line. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @protected + */ +Blockly.blockRendering.MarkerSvg.prototype.showWithCoordinates_ = function( + curNode) { var wsCoordinate = curNode.getWsCoordinate(); var x = wsCoordinate.x; var y = wsCoordinate.y; @@ -203,9 +291,9 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithCoordinates_ = function(curNo }; /** - * Show the visual representation of a field. + * Position and display the marker for a field. * This is a box around the field. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ Blockly.blockRendering.MarkerSvg.prototype.showWithField_ = function(curNode) { @@ -219,9 +307,9 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithField_ = function(curNode) { }; /** - * Show the visual representation of an input. + * Position and display the marker for an input. * This is a puzzle piece. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ Blockly.blockRendering.MarkerSvg.prototype.showWithInput_ = function(curNode) { @@ -236,9 +324,9 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithInput_ = function(curNode) { /** - * Show the visual representation of a next connection. + * Position and display the marker for a next connection. * This is a horizontal line. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ Blockly.blockRendering.MarkerSvg.prototype.showWithNext_ = function(curNode) { @@ -256,9 +344,9 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithNext_ = function(curNode) { }; /** - * Show the visual representation of a stack. + * Position and display the marker for a stack. * This is a box with extra padding around the entire stack of blocks. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ Blockly.blockRendering.MarkerSvg.prototype.showWithStack_ = function(curNode) { @@ -305,7 +393,7 @@ Blockly.blockRendering.MarkerSvg.prototype.showCurrent_ = function() { * @param {number} width The width of the block. * @param {number} markerOffset The extra padding for around the block. * @param {number} markerHeight The height of the marker. - * @private + * @protected */ Blockly.blockRendering.MarkerSvg.prototype.positionBlock_ = function( width, markerOffset, markerHeight) { @@ -323,10 +411,12 @@ Blockly.blockRendering.MarkerSvg.prototype.positionBlock_ = function( /** * Position the marker for an input connection. * Displays a filled in puzzle piece. - * @param {!Blockly.RenderedConnection} connection The connection to position marker around. - * @private + * @param {!Blockly.RenderedConnection} connection The connection to position + * marker around. + * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function(connection) { +Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function( + connection) { var x = connection.getOffsetInBlock().x; var y = connection.getOffsetInBlock().y; @@ -335,7 +425,8 @@ Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function(connection) this.markerInput_.setAttribute('d', path); this.markerInput_.setAttribute('transform', - 'translate(' + x + ',' + y + ')' + (this.workspace_.RTL ? ' scale(-1 1)' : '')); + 'translate(' + x + ',' + y + ')' + + (this.workspace_.RTL ? ' scale(-1 1)' : '')); this.currentMarkerSvg = this.markerInput_; }; @@ -347,7 +438,8 @@ Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function(connection) * @param {number} width The new width, in workspace units. * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.positionLine_ = function(x, y, width) { +Blockly.blockRendering.MarkerSvg.prototype.positionLine_ = function( + x, y, width) { this.markerSvgLine_.setAttribute('x', x); this.markerSvgLine_.setAttribute('y', y); this.markerSvgLine_.setAttribute('width', width); @@ -360,7 +452,7 @@ Blockly.blockRendering.MarkerSvg.prototype.positionLine_ = function(x, y, width) * @param {number} width The width of the block. * @param {number} height The height of the block. * @param {!Object} connectionShape The shape object for the connection. - * @private + * @protected */ Blockly.blockRendering.MarkerSvg.prototype.positionOutput_ = function( width, height, connectionShape) { @@ -387,7 +479,7 @@ Blockly.blockRendering.MarkerSvg.prototype.positionOutput_ = function( * @param {number} markerOffset The offset of the marker from around the block. * @param {number} markerHeight The height of the marker. * @param {!Object} connectionShape The shape object for the connection. - * @private + * @protected */ Blockly.blockRendering.MarkerSvg.prototype.positionPrevious_ = function( width, markerOffset, markerHeight, connectionShape) { @@ -415,7 +507,8 @@ Blockly.blockRendering.MarkerSvg.prototype.positionPrevious_ = function( * @param {number} height The new height, in workspace units. * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.positionRect_ = function(x, y, width, height) { +Blockly.blockRendering.MarkerSvg.prototype.positionRect_ = function( + x, y, width, height) { this.markerSvgRect_.setAttribute('x', x); this.markerSvgRect_.setAttribute('y', y); this.markerSvgRect_.setAttribute('width', width); @@ -434,7 +527,6 @@ Blockly.blockRendering.MarkerSvg.prototype.flipRtl_ = function(markerSvg) { /** * Hide the marker. - * @package */ Blockly.blockRendering.MarkerSvg.prototype.hide = function() { this.markerSvgLine_.style.display = 'none'; @@ -443,64 +535,6 @@ Blockly.blockRendering.MarkerSvg.prototype.hide = function() { this.markerBlock_.style.display = 'none'; }; -/** - * Update the marker. - * @param {Blockly.ASTNode} oldNode The previous node the marker was on or null. - * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for. - * @package - */ -Blockly.blockRendering.MarkerSvg.prototype.draw = function(oldNode, curNode) { - if (!curNode) { - this.hide(); - return; - } - - this.constants_ = this.workspace_.getRenderer().getConstants(); - - var defaultColour = this.isCursor() ? this.constants_.CURSOR_COLOUR : - this.constants_.MARKER_COLOUR; - this.colour_ = this.marker_.colour || defaultColour; - this.applyColour_(); - - this.showAtLocation_(curNode); - - this.firemarkerEvent_(oldNode, curNode); - - // Ensures the marker will be visible immediately after the move. - var animate = this.currentMarkerSvg.childNodes[0]; - if (animate !== undefined) { - animate.beginElement && animate.beginElement(); - } -}; - - -/** - * Update the marker's visible state based on the type of curNode.. - * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for. - * @protected - */ -Blockly.blockRendering.MarkerSvg.prototype.showAtLocation_ = function(curNode) { - if (curNode.getType() == Blockly.ASTNode.types.BLOCK) { - var block = /** @type {Blockly.BlockSvg} */ (curNode.getLocation()); - this.showWithBlockPrevOutput_(block); - } else if (curNode.getType() == Blockly.ASTNode.types.OUTPUT) { - var outputBlock = /** @type {Blockly.BlockSvg} */ (curNode.getLocation().getSourceBlock()); - this.showWithBlockPrevOutput_(outputBlock); - } else if (curNode.getLocation().type == Blockly.INPUT_VALUE) { - this.showWithInput_(curNode); - } else if (curNode.getLocation().type == Blockly.NEXT_STATEMENT) { - this.showWithNext_(curNode); - } else if (curNode.getType() == Blockly.ASTNode.types.PREVIOUS) { - var previousBlock = /** @type {Blockly.BlockSvg} */ (curNode.getLocation().getSourceBlock()); - this.showWithBlockPrevOutput_(previousBlock); - } else if (curNode.getType() == Blockly.ASTNode.types.FIELD) { - this.showWithField_(curNode); - } else if (curNode.getType() == Blockly.ASTNode.types.WORKSPACE) { - this.showWithCoordinates_(curNode); - } else if (curNode.getType() == Blockly.ASTNode.types.STACK) { - this.showWithStack_(curNode); - } -}; /** * Fire event for the marker or marker. @@ -508,7 +542,8 @@ Blockly.blockRendering.MarkerSvg.prototype.showAtLocation_ = function(curNode) { * @param {!Blockly.ASTNode} curNode The new node the marker is currently on. * @private */ -Blockly.blockRendering.MarkerSvg.prototype.firemarkerEvent_ = function(oldNode, curNode) { +Blockly.blockRendering.MarkerSvg.prototype.fireMarkerEvent_ = function( + oldNode, curNode) { var curBlock = curNode.getSourceBlock(); var eventType = this.isCursor() ? 'cursorMove' : 'markerMove'; var event = new Blockly.Events.Ui(curBlock, eventType, oldNode, curNode); @@ -555,7 +590,8 @@ Blockly.blockRendering.MarkerSvg.prototype.createDomInternal_ = function() { 'height': this.constants_.WS_CURSOR_HEIGHT }, this.svgGroup_); - // A horizontal line used to represent a workspace coordinate or next connection. + // A horizontal line used to represent a workspace coordinate or next + // connection. this.markerSvgLine_ = Blockly.utils.dom.createSvgElement('rect', { 'width': this.constants_.CURSOR_WS_WIDTH, @@ -609,9 +645,11 @@ Blockly.blockRendering.MarkerSvg.prototype.createDomInternal_ = function() { /** * Apply the marker's colour. + * @param {!Blockly.ASTNode} _curNode The node that we want to draw the marker + * for. * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.applyColour_ = function() { +Blockly.blockRendering.MarkerSvg.prototype.applyColour_ = function(_curNode) { this.markerSvgLine_.setAttribute('fill', this.colour_); this.markerSvgRect_.setAttribute('stroke', this.colour_); this.markerInput_.setAttribute('fill', this.colour_); @@ -627,7 +665,6 @@ Blockly.blockRendering.MarkerSvg.prototype.applyColour_ = function() { /** * Dispose of this marker. - * @package */ Blockly.blockRendering.MarkerSvg.prototype.dispose = function() { if (this.svgGroup_) { diff --git a/core/renderers/zelos/marker_svg.js b/core/renderers/zelos/marker_svg.js index 7c9bdd120..a118f76c4 100644 --- a/core/renderers/zelos/marker_svg.js +++ b/core/renderers/zelos/marker_svg.js @@ -32,9 +32,11 @@ Blockly.utils.object.inherits(Blockly.zelos.MarkerSvg, Blockly.blockRendering.MarkerSvg); /** - * @override + * Position and display the marker for an input or an output connection. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @private */ -Blockly.zelos.MarkerSvg.prototype.showWithInput_ = function(curNode) { +Blockly.zelos.MarkerSvg.prototype.showWithInputOutput_ = function(curNode) { var block = /** @type {!Blockly.BlockSvg} */ (curNode.getSourceBlock()); var connection = curNode.getLocation(); var offsetInBlock = connection.getOffsetInBlock(); @@ -44,6 +46,20 @@ Blockly.zelos.MarkerSvg.prototype.showWithInput_ = function(curNode) { this.showCurrent_(); }; +/** + * @override + */ +Blockly.zelos.MarkerSvg.prototype.showWithOutput_ = function(curNode) { + this.showWithInputOutput_(curNode); +}; + +/** + * @override + */ +Blockly.zelos.MarkerSvg.prototype.showWithInput_ = function(curNode) { + this.showWithInputOutput_(curNode); +}; + /** * Draw a rectangle around the block. * @param {!Blockly.ASTNode} curNode The current node of the marker. @@ -72,25 +88,6 @@ Blockly.zelos.MarkerSvg.prototype.positionCircle_ = function(x, y) { this.currentMarkerSvg = this.markerCircle_; }; -/** - * @override - */ -Blockly.zelos.MarkerSvg.prototype.showAtLocation_ = function(curNode) { - var handled = false; - if (curNode.getType() == Blockly.ASTNode.types.OUTPUT) { - // Inputs and outputs are drawn the same. - this.showWithInput_(curNode); - handled = true; - } else if (curNode.getType() == Blockly.ASTNode.types.BLOCK) { - this.showWithBlock_(curNode); - handled = true; - } - - if (!handled) { - Blockly.zelos.MarkerSvg.superClass_.showAtLocation_.call(this, curNode); - } -}; - /** * @override */ @@ -134,8 +131,8 @@ Blockly.zelos.MarkerSvg.prototype.createDomInternal_ = function() { /** * @override */ -Blockly.zelos.MarkerSvg.prototype.applyColour_ = function() { - Blockly.zelos.MarkerSvg.superClass_.applyColour_.call(this); +Blockly.zelos.MarkerSvg.prototype.applyColour_ = function(curNode) { + Blockly.zelos.MarkerSvg.superClass_.applyColour_.call(this, curNode); this.markerCircle_.setAttribute('fill', this.colour_); this.markerCircle_.setAttribute('stroke', this.colour_); diff --git a/tests/mocha/astnode_test.js b/tests/mocha/astnode_test.js index 2d0b111a7..1e9a69c71 100644 --- a/tests/mocha/astnode_test.js +++ b/tests/mocha/astnode_test.js @@ -169,112 +169,176 @@ suite('ASTNode', function() { }); suite('NavigationFunctions', function() { + setup(function() { + Blockly.defineBlocksWithJsonArray([{ + "type": "top_connection", + "message0": "", + "previousStatement": null, + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "start_block", + "message0": "", + "nextStatement": null, + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "fields_and_input", + "message0": "%1 hi %2 %3 %4", + "args0": [ + { + "type": "field_input", + "name": "NAME", + "text": "default" + }, + { + "type": "input_dummy" + }, + { + "type": "field_input", + "name": "NAME", + "text": "default" + }, + { + "type": "input_value", + "name": "NAME" + } + ], + "previousStatement": null, + "nextStatement": null, + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "two_fields", + "message0": "%1 hi", + "args0": [ + { + "type": "field_input", + "name": "NAME", + "text": "default" + } + ], + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "fields_and_input2", + "message0": "%1 %2 %3 hi %4 bye", + "args0": [ + { + "type": "input_value", + "name": "NAME" + }, + { + "type": "field_input", + "name": "NAME", + "text": "default" + }, + { + "type": "input_value", + "name": "NAME" + }, + { + "type": "input_statement", + "name": "NAME" + } + ], + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "dummy_input", + "message0": "Hello", + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "dummy_inputValue", + "message0": "Hello %1 %2", + "args0": [ + { + "type": "input_dummy" + }, + { + "type": "input_value", + "name": "NAME" + } + ], + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "output_next", + "message0": "", + "output": null, + "colour": 230, + "tooltip": "", + "helpUrl": "", + "nextStatement": null + }]); + + var noNextConnection = this.workspace.newBlock('top_connection'); + var fieldAndInputs = this.workspace.newBlock('fields_and_input'); + var twoFields = this.workspace.newBlock('two_fields'); + var fieldAndInputs2 = this.workspace.newBlock('fields_and_input2'); + var noPrevConnection = this.workspace.newBlock('start_block'); + this.blocks.noNextConnection = noNextConnection; + this.blocks.fieldAndInputs = fieldAndInputs; + this.blocks.twoFields = twoFields; + this.blocks.fieldAndInputs2 = fieldAndInputs2; + this.blocks.noPrevConnection = noPrevConnection; + + var dummyInput = this.workspace.newBlock('dummy_input'); + var dummyInputValue = this.workspace.newBlock('dummy_inputValue'); + var fieldWithOutput2 = this.workspace.newBlock('field_input'); + this.blocks.dummyInput = dummyInput; + this.blocks.dummyInputValue = dummyInputValue; + this.blocks.fieldWithOutput2 = fieldWithOutput2; + + var secondBlock = this.workspace.newBlock('input_statement'); + var outputNextBlock = this.workspace.newBlock('output_next'); + this.blocks.secondBlock = secondBlock; + this.blocks.outputNextBlock = outputNextBlock; + + + }); + teardown(function() { + delete this.blocks.noNextConnection; + delete this.blocks.fieldAndInputs; + delete this.blocks.twoFields; + delete this.blocks.fieldAndInputs2; + delete this.blocks.noPrevConnection; + delete this.blocks.dummyInput; + delete this.blocks.dummyInputValue; + delete this.blocks.fieldWithOutput2; + + + delete Blockly.Blocks['fields_and_input2']; + delete Blockly.Blocks['two_fields']; + delete Blockly.Blocks['fields_and_input']; + delete Blockly.Blocks['top_connection']; + delete Blockly.Blocks['start_block']; + delete Blockly.Blocks['dummy_input']; + delete Blockly.Blocks['dummy_inputValue']; + }); suite('Next', function() { setup(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "top_connection", - "message0": "", - "previousStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "fields_and_input", - "message0": "%1 hi %2 %3 %4", - "args0": [ - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_dummy" - }, - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_value", - "name": "NAME" - } - ], - "previousStatement": null, - "nextStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "two_fields", - "message0": "%1 hi", - "args0": [ - { - "type": "field_input", - "name": "NAME", - "text": "default" - } - ], - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "fields_and_input2", - "message0": "%1 %2 %3 hi %4 bye", - "args0": [ - { - "type": "input_value", - "name": "NAME" - }, - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_value", - "name": "NAME" - }, - { - "type": "input_statement", - "name": "NAME" - } - ], - "colour": 230, - "tooltip": "", - "helpUrl": "" - }]); - this.singleBlockWorkspace = new Blockly.Workspace(); - - var noNextConnection = this.workspace.newBlock('top_connection'); - var fieldAndInputs = this.workspace.newBlock('fields_and_input'); - var twoFields = this.workspace.newBlock('two_fields'); - var fieldAndInputs2 = this.workspace.newBlock('fields_and_input2'); var singleBlock = this.singleBlockWorkspace.newBlock('two_fields'); - - this.blocks.noNextConnection = noNextConnection; - this.blocks.fieldAndInputs = fieldAndInputs; - this.blocks.twoFields = twoFields; - this.blocks.fieldAndInputs2 = fieldAndInputs2; this.blocks.singleBlock = singleBlock; - - }); teardown(function() { - delete this.blocks.noNextConnection; - delete this.blocks.fieldAndInputs; - delete this.blocks.twoFields; - delete this.blocks.fieldAndInputs2; delete this.blocks.singleBlock; - - delete Blockly.Blocks['fields_and_input2']; - delete Blockly.Blocks['two_fields']; - delete Blockly.Blocks['fields_and_input']; - delete Blockly.Blocks['top_connection']; }); test('fromPreviousToBlock', function() { @@ -374,88 +438,6 @@ suite('ASTNode', function() { }); suite('Previous', function() { - setup(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "start_block", - "message0": "", - "nextStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "fields_and_input", - "message0": "%1 hi %2 %3 %4", - "args0": [ - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_dummy" - }, - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_value", - "name": "NAME" - } - ], - "previousStatement": null, - "nextStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "fields_and_input2", - "message0": "%1 %2 %3 hi %4 bye", - "args0": [ - { - "type": "input_value", - "name": "NAME" - }, - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_value", - "name": "NAME" - }, - { - "type": "input_statement", - "name": "NAME" - } - ], - "colour": 230, - "tooltip": "", - "helpUrl": "" - }]); - - var noPrevConnection = this.workspace.newBlock('start_block'); - var fieldsAndInputs = this.workspace.newBlock('fields_and_input'); - var fieldsAndInputs2 = this.workspace.newBlock('fields_and_input2'); - - this.blocks.noPrevConnection = noPrevConnection; - this.blocks.fieldsAndInputs = fieldsAndInputs; - this.blocks.fieldsAndInputs2 = fieldsAndInputs2; - }); - teardown(function() { - delete this.blocks.noPrevConnection; - delete this.blocks.fieldAndInputs; - delete this.blocks.fieldsAndInputs2; - - delete Blockly.Blocks['fields_and_input2']; - delete Blockly.Blocks['start_block']; - delete Blockly.Blocks['fields_and_input']; - }); - test('fromPreviousToNull', function() { var prevConnection = this.blocks.statementInput1.previousConnection; var node = Blockly.ASTNode.createConnectionNode(prevConnection); @@ -505,14 +487,14 @@ suite('ASTNode', function() { assertEquals(prevNode.getLocation(), input.fieldRow[1]); }); test('fromInputToNull', function() { - var input = this.blocks.fieldsAndInputs2.inputList[0]; + var input = this.blocks.fieldAndInputs2.inputList[0]; var node = Blockly.ASTNode.createInputNode(input); var prevNode = node.prev(); assertEquals(prevNode, null); }); test('fromInputToInput', function() { - var input = this.blocks.fieldsAndInputs2.inputList[2]; - var inputConnection = this.blocks.fieldsAndInputs2.inputList[1].connection; + var input = this.blocks.fieldAndInputs2.inputList[2]; + var inputConnection = this.blocks.fieldAndInputs2.inputList[1].connection; var node = Blockly.ASTNode.createInputNode(input); var prevNode = node.prev(); assertEquals(prevNode.getLocation(), inputConnection); @@ -530,15 +512,15 @@ suite('ASTNode', function() { assertEquals(prevNode, null); }); test('fromFieldToInput', function() { - var field = this.blocks.fieldsAndInputs2.inputList[1].fieldRow[0]; - var inputConnection = this.blocks.fieldsAndInputs2.inputList[0].connection; + var field = this.blocks.fieldAndInputs2.inputList[1].fieldRow[0]; + var inputConnection = this.blocks.fieldAndInputs2.inputList[0].connection; var node = Blockly.ASTNode.createFieldNode(field); var prevNode = node.prev(); assertEquals(prevNode.getLocation(), inputConnection); }); test('fromFieldToField', function() { - var field = this.blocks.fieldsAndInputs.inputList[1].fieldRow[0]; - var field2 = this.blocks.fieldsAndInputs.inputList[0].fieldRow[0]; + var field = this.blocks.fieldAndInputs.inputList[1].fieldRow[0]; + var field2 = this.blocks.fieldAndInputs.inputList[0].fieldRow[0]; var node = Blockly.ASTNode.createFieldNode(field); var prevNode = node.prev(); assertEquals(prevNode.getLocation(), field2); @@ -553,46 +535,10 @@ suite('ASTNode', function() { suite('In', function() { setup(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "dummy_input", - "message0": "Hello", - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "dummy_inputValue", - "message0": "Hello %1 %2", - "args0": [ - { - "type": "input_dummy" - }, - { - "type": "input_value", - "name": "NAME" - } - ], - "colour": 230, - "tooltip": "", - "helpUrl": "" - }]); - var dummyInput = this.workspace.newBlock('dummy_input'); - var dummyInputValue = this.workspace.newBlock('dummy_inputValue'); - var fieldWithOutput2 = this.workspace.newBlock('field_input'); - - this.blocks.dummyInput = dummyInput; - this.blocks.dummyInputValue = dummyInputValue; - this.blocks.fieldWithOutput2 = fieldWithOutput2; this.emptyWorkspace = new Blockly.Workspace(); }); teardown(function() { - delete this.blocks.dummyInput; - delete this.blocks.dummyInputValue; - delete this.blocks.fieldWithOutput2; delete this.emptyWorkspace; - - delete Blockly.Blocks['dummy_input']; - delete Blockly.Blocks['dummy_inputValue']; }); test('fromInputToOutput', function() { @@ -695,44 +641,11 @@ suite('ASTNode', function() { suite('Out', function() { setup(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "start_block", - "message0": "", - "nextStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "output_next", - "message0": "", - "output": null, - "colour": 230, - "tooltip": "", - "helpUrl": "", - "nextStatement": null - }]); - var noPrevConnection = this.workspace.newBlock('start_block'); - var secondBlock = this.workspace.newBlock('input_statement'); - var outputNextBlock = this.workspace.newBlock('output_next'); - var fieldWithOutput2 = this.workspace.newBlock('field_input'); - - noPrevConnection.nextConnection.connect(secondBlock.previousConnection); + var secondBlock = this.blocks.secondBlock; + var outputNextBlock = this.blocks.outputNextBlock; + this.blocks.noPrevConnection.nextConnection.connect(secondBlock.previousConnection); secondBlock.inputList[0].connection .connect(outputNextBlock.outputConnection); - this.blocks.noPrevConnection = noPrevConnection; - this.blocks.secondBlock = secondBlock; - this.blocks.outputNextBlock = outputNextBlock; - this.blocks.fieldWithOutput2 = fieldWithOutput2; - }); - teardown(function() { - delete this.blocks.noPrevConnection; - delete this.blocks.secondBlock; - delete this.blocks.outputNextBlock; - delete this.blocks.fieldWithOutput2; - - delete Blockly.Blocks['start_block']; - delete Blockly.Blocks['output_next']; }); test('fromInputToBlock', function() { @@ -896,6 +809,21 @@ suite('ASTNode', function() { assertEquals(node.getType(), Blockly.ASTNode.types.INPUT); assertTrue(node.isConnection()); }); + test('createTopNode-previous', function() { + var block = this.blocks.statementInput1; + var topNode = Blockly.ASTNode.createTopNode(block); + assertEquals(topNode.getLocation(), block.previousConnection); + }); + test('createTopNode-block', function() { + var block = this.blocks.noPrevConnection; + var topNode = Blockly.ASTNode.createTopNode(block); + assertEquals(topNode.getLocation(), block); + }); + test('createTopNode-output', function() { + var block = this.blocks.outputNextBlock; + var topNode = Blockly.ASTNode.createTopNode(block); + assertEquals(topNode.getLocation(), block.outputConnection); + }); }); }); }); From ab5f7d8a00358850473042d6e8580ea9d458c41e Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Wed, 15 Apr 2020 11:29:17 -0700 Subject: [PATCH 018/139] Converting event tests to mocha. (#3811) * Convert remaining jsunit tests for events to mocha. * Fix eslint. --- tests/jsunit/event_test.js | 355 ------------------------------------ tests/jsunit/index.html | 1 - tests/mocha/event_test.js | 256 +++++++++++++++++++++++++- tests/mocha/test_helpers.js | 1 + 4 files changed, 256 insertions(+), 357 deletions(-) delete mode 100644 tests/jsunit/event_test.js diff --git a/tests/jsunit/event_test.js b/tests/jsunit/event_test.js deleted file mode 100644 index 9a1b2a19a..000000000 --- a/tests/jsunit/event_test.js +++ /dev/null @@ -1,355 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - - /** - * @fileoverview Tests for Blockly.Events - * @author marisaleung@google.com (Marisa Leung) - */ -'use strict'; - -var mockControl_; -var workspace; - -function eventTest_setUp() { - workspace = new Blockly.Workspace(); -} - -function eventTest_setUpWithMockBlocks() { - eventTest_setUp(); - // TODO: Replace with defineGetVarBlock(); - Blockly.defineBlocksWithJsonArray([{ - 'type': 'field_variable_test_block', - 'message0': '%1', - 'args0': [ - { - 'type': 'field_variable', - 'name': 'VAR', - 'variable': 'item' - } - ], - }, - { - 'type': 'simple_test_block', - 'message0': 'simple test block' - }]); -} - -function eventTest_tearDown() { - delete Blockly.Blocks['field_variable_test_block']; - delete Blockly.Blocks['simple_test_block']; - if (mockControl_) { - mockControl_.restore(); - } - workspace.dispose(); -} - -function eventTest_tearDownWithMockBlocks() { - eventTest_tearDown(); - delete Blockly.Blocks.field_variable_test_block; -} - -// Test util -function createSimpleTestBlock(workspace) { - // Disable events while constructing the block: this is a test of the - // Blockly.Event constructors, not the block constructor. - Blockly.Events.disable(); - var block = new Blockly.Block(workspace, 'simple_test_block'); - Blockly.Events.enable(); - return block; -} - -function test_events_filter() { - eventTest_setUpWithMockBlocks(); - try { - var block1 = workspace.newBlock('field_variable_test_block', '1'); - var events = [ - new Blockly.Events.BlockCreate(block1), - new Blockly.Events.BlockMove(block1), - new Blockly.Events.BlockChange(block1, 'field', 'VAR', 'id1', 'id2'), - new Blockly.Events.Ui(block1, 'click') - ]; - var filteredEvents = Blockly.Events.filter(events, true); - assertEquals(4, filteredEvents.length); // no event should have been removed. - // test that the order hasn't changed - assertTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); - assertTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); - assertTrue(filteredEvents[2] instanceof Blockly.Events.BlockChange); - assertTrue(filteredEvents[3] instanceof Blockly.Events.Ui); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_events_filterForward() { - eventTest_setUpWithMockBlocks(); - try { - var block1 = workspace.newBlock('field_variable_test_block', '1'); - var events = [ - new Blockly.Events.BlockCreate(block1), - ]; - helper_addMoveEvent(events, block1, 1, 1); - helper_addMoveEvent(events, block1, 2, 2); - helper_addMoveEvent(events, block1, 3, 3); - var filteredEvents = Blockly.Events.filter(events, true); - assertEquals(2, filteredEvents.length); // duplicate moves should have been removed. - // test that the order hasn't changed - assertTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); - assertTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); - assertEquals(3, filteredEvents[1].newCoordinate.x); - assertEquals(3, filteredEvents[1].newCoordinate.y); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_events_filterBackward() { - eventTest_setUpWithMockBlocks(); - try { - var block1 = workspace.newBlock('field_variable_test_block', '1'); - var events = [ - new Blockly.Events.BlockCreate(block1), - ]; - helper_addMoveEvent(events, block1, 1, 1); - helper_addMoveEvent(events, block1, 2, 2); - helper_addMoveEvent(events, block1, 3, 3); - var filteredEvents = Blockly.Events.filter(events, false); - assertEquals(2, filteredEvents.length); // duplicate event should have been removed. - // test that the order hasn't changed - assertTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); - assertTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); - assertEquals(1, filteredEvents[1].newCoordinate.x); - assertEquals(1, filteredEvents[1].newCoordinate.y); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} - -function test_events_filterDifferentBlocks() { - eventTest_setUpWithMockBlocks(); - var block1 = workspace.newBlock('field_variable_test_block', '1'); - var block2 = workspace.newBlock('field_variable_test_block', '2'); - var events = [ - new Blockly.Events.BlockCreate(block1), - new Blockly.Events.BlockMove(block1), - new Blockly.Events.BlockCreate(block2), - new Blockly.Events.BlockMove(block2) - ]; - var filteredEvents = Blockly.Events.filter(events, true); - assertEquals(4, filteredEvents.length); // no event should have been removed. - eventTest_tearDownWithMockBlocks(); -} - -function test_events_mergeMove() { - eventTest_setUpWithMockBlocks(); - var block1 = workspace.newBlock('field_variable_test_block', '1'); - var events = []; - helper_addMoveEvent(events, block1, 0, 0); - helper_addMoveEvent(events, block1, 1, 1); - var filteredEvents = Blockly.Events.filter(events, true); - assertEquals(1, filteredEvents.length); // second move event merged into first - assertEquals(1, filteredEvents[0].newCoordinate.x); - assertEquals(1, filteredEvents[0].newCoordinate.y); - eventTest_tearDownWithMockBlocks(); -} - -function test_events_mergeChange() { - eventTest_setUpWithMockBlocks(); - var block1 = workspace.newBlock('field_variable_test_block', '1'); - var events = [ - new Blockly.Events.Change(block1, 'field', 'VAR', 'item', 'item1'), - new Blockly.Events.Change(block1, 'field', 'VAR', 'item1', 'item2') - ]; - var filteredEvents = Blockly.Events.filter(events, true); - assertEquals(1, filteredEvents.length); // second change event merged into first - assertEquals('item', filteredEvents[0].oldValue); - assertEquals('item2', filteredEvents[0].newValue); - eventTest_tearDownWithMockBlocks(); -} - -function test_events_mergeUi() { - eventTest_setUpWithMockBlocks(); - var block1 = workspace.newBlock('field_variable_test_block', '1'); - var block2 = workspace.newBlock('field_variable_test_block', '2'); - var block3 = workspace.newBlock('field_variable_test_block', '3'); - var events = [ - new Blockly.Events.Ui(block1, 'commentOpen', 'false', 'true'), - new Blockly.Events.Ui(block1, 'click', 'false', 'true'), - new Blockly.Events.Ui(block2, 'mutatorOpen', 'false', 'true'), - new Blockly.Events.Ui(block2, 'click', 'false', 'true'), - new Blockly.Events.Ui(block3, 'warningOpen', 'false', 'true'), - new Blockly.Events.Ui(block3, 'click', 'false', 'true') - ]; - var filteredEvents = Blockly.Events.filter(events, true); - assertEquals(3, filteredEvents.length); // click event merged into corresponding *Open event - assertEquals('commentOpen', filteredEvents[0].element); - assertEquals('mutatorOpen', filteredEvents[1].element); - assertEquals('warningOpen', filteredEvents[2].element); - eventTest_tearDownWithMockBlocks(); -} - -/** - * Tests that events that collide on a (event, block, workspace) tuple - * but cannot be merged do not get dropped during filtering. - */ -function test_events_stackclick() { - eventTest_setUpWithMockBlocks(); - var block = workspace.newBlock('field_variable_test_block', '1'); - var events = [ - new Blockly.Events.Ui(block, 'click', undefined, undefined), - new Blockly.Events.Ui(block, 'stackclick', undefined, undefined) - ]; - var filteredEvents = Blockly.Events.filter(events, true); - // click and stackclick should both exist - assertEquals(2, filteredEvents.length); - assertEquals('click', filteredEvents[0].element); - assertEquals('stackclick', filteredEvents[1].element); - eventTest_tearDownWithMockBlocks(); -} - -/** - * Mutator composition could result in move events for blocks - * connected to the mutated block that were null operations. This - * leads to events in the undo/redo queue that do nothing, requiring - * an extra undo/redo to proceed to the next event. This test ensures - * that two move events that do get merged (disconnecting and - * reconnecting a block in response to a mutator change) are filtered - * from the queue. - */ -function test_events_filteraftermerge() { - eventTest_setUpWithMockBlocks(); - var block = workspace.newBlock('field_variable_test_block', '1'); - block.setParent(null); - var events = []; - helper_addMoveEventParent(events, block, null); - helper_addMoveEventParent(events, block, null); - var filteredEvents = Blockly.Events.filter(events, true); - // The two events should be merged, but because nothing has changed - // they will be filtered out. - assertEquals(0, filteredEvents.length); - eventTest_tearDownWithMockBlocks(); -} - -/** - * Helper function to simulate block move events. - * - * @param {!Array.} events a queue of events. - * @param {!Blockly.Block} block the block to be moved - * @param {number} newX new X coordinate of the block - * @param {number} newY new Y coordinate of the block - */ -function helper_addMoveEvent(events, block, newX, newY) { - events.push(new Blockly.Events.BlockMove(block)); - block.xy_ = new Blockly.utils.Coordinate(newX, newY); - events[events.length-1].recordNew(); -} - -function helper_addMoveEventParent(events, block, parent) { - events.push(new Blockly.Events.BlockMove(block)); - block.setParent(parent); - events[events.length-1].recordNew(); -} - -function test_events_newblock_newvar() { - eventTest_setUpWithMockBlocks(); - - Blockly.Events.fire = temporary_fireEvent; - temporary_fireEvent.firedEvents_ = []; - // Expect three calls to genUid: one to set the block's ID, one for the event - // group's id, and one for the variable's ID. - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '2', '3']); - try { - var block = workspace.newBlock('field_variable_test_block'); - - var firedEvents = workspace.undoStack_; - // Expect two events: varCreate and block create. - assertEquals(2, firedEvents.length); - - var event0 = firedEvents[0]; - var event1 = firedEvents[1]; - assertEquals('var_create', event0.type); - assertEquals('create', event1.type); - - // Expect the events to have the same group ID. - assertEquals(event0.group, event1.group); - - // Expect the group ID to be the result of the second call to genUid. - assertEquals('2', event0.group); - - // Expect the workspace to have a variable with ID '3'. - assertNotNull(workspace.getVariableById('3')); - assertEquals('3', event0.varId); - } finally { - eventTest_tearDownWithMockBlocks(); - Blockly.Events.fire = savedFireFunc; - } -} - -// The sequence of events should be the same whether the block was created from -// XML or directly. -function test_events_newblock_newvar_xml() { - eventTest_setUpWithMockBlocks(); - - Blockly.Events.fire = temporary_fireEvent; - temporary_fireEvent.firedEvents_ = []; - try { - var dom = Blockly.Xml.textToDom( - '' + - ' ' + - ' name1' + - ' ' + - ''); - Blockly.Xml.domToWorkspace(dom, workspace); - - var firedEvents = workspace.undoStack_; - // Expect two events: varCreate and block create. - assertEquals(2, firedEvents.length); - - var event0 = firedEvents[0]; - var event1 = firedEvents[1]; - assertEquals('var_create', event0.type); - assertEquals('create', event1.type); - - // Expect the events to have the same group ID. - assertEquals(event0.group, event1.group); - - // Expect the workspace to have a variable with ID 'id1'. - assertNotNull(workspace.getVariableById('id1')); - assertEquals('id1', event0.varId); - } finally { - eventTest_tearDownWithMockBlocks(); - Blockly.Events.fire = savedFireFunc; - } -} - -function test_events_filter_nomerge_move() { - // Move events should only merge if they refer to the same block and are - // consecutive. - // See github.com/google/blockly/pull/1892 for a worked example showing - // how merging non-consecutive events can fail when replacing a shadow - // block. - eventTest_setUpWithMockBlocks(); - try { - var block1 = createSimpleTestBlock(workspace); - var block2 = createSimpleTestBlock(workspace); - - var events = []; - helper_addMoveEvent(events, block1, 1, 1); - helper_addMoveEvent(events, block2, 1, 1); - events.push(new Blockly.Events.BlockDelete(block2)); - helper_addMoveEvent(events, block1, 2, 2); - - var filteredEvents = Blockly.Events.filter(events, true); - // Nothing should have merged. - assertEquals(4, filteredEvents.length); - // test that the order hasn't changed - assertTrue(filteredEvents[0] instanceof Blockly.Events.BlockMove); - assertTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); - assertTrue(filteredEvents[2] instanceof Blockly.Events.BlockDelete); - assertTrue(filteredEvents[3] instanceof Blockly.Events.BlockMove); - } finally { - eventTest_tearDownWithMockBlocks(); - } -} diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index cf10ff987..221ff2618 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -17,7 +17,6 @@ - diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index 86af27f48..69a33fb2b 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -60,7 +60,7 @@ suite('Events', function() { function createSimpleTestBlock(workspace, opt_prototypeName) { // Disable events while constructing the block: this is a test of the - // Blockly.Event constructors, not the block constructor. + // Blockly.Event constructors, not the block constructor.s Blockly.Events.disable(); var block = new Blockly.Block( workspace, opt_prototypeName || 'simple_test_block'); @@ -375,4 +375,258 @@ suite('Events', function() { }); }); }); + + suite('Filters', function() { + + function addMoveEvent(events, block, newX, newY) { + events.push(new Blockly.Events.BlockMove(block)); + block.xy_ = new Blockly.utils.Coordinate(newX, newY); + events[events.length - 1].recordNew(); + } + + function addMoveEventParent(events, block, parent) { + events.push(new Blockly.Events.BlockMove(block)); + block.setParent(parent); + events[events.length - 1].recordNew(); + } + + test('No removed, order unchanged', function() { + var block = this.workspace.newBlock('field_variable_test_block', '1'); + var events = [ + new Blockly.Events.BlockCreate(block), + new Blockly.Events.BlockMove(block), + new Blockly.Events.BlockChange(block, 'field', 'VAR', 'id1', 'id2'), + new Blockly.Events.Ui(block, 'click', undefined, undefined) + ]; + var filteredEvents = Blockly.Events.filter(events, true); + assertEquals(4, filteredEvents.length); // no event should have been removed. + // test that the order hasn't changed + assertTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); + assertTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); + assertTrue(filteredEvents[2] instanceof Blockly.Events.BlockChange); + assertTrue(filteredEvents[3] instanceof Blockly.Events.Ui); + }); + + test('Different blocks no removed', function() { + var block1 = this.workspace.newBlock('field_variable_test_block', '1'); + var block2 = this.workspace.newBlock('field_variable_test_block', '2'); + var events = [ + new Blockly.Events.BlockCreate(block1), + new Blockly.Events.BlockMove(block1), + new Blockly.Events.BlockCreate(block2), + new Blockly.Events.BlockMove(block2) + ]; + var filteredEvents = Blockly.Events.filter(events, true); + assertEquals(4, filteredEvents.length); // no event should have been removed. + }); + + test('Forward', function() { + var block = this.workspace.newBlock('field_variable_test_block', '1'); + var events = [ new Blockly.Events.BlockCreate(block) ]; + addMoveEvent(events, block, 1, 1); + addMoveEvent(events, block, 2, 2); + addMoveEvent(events, block, 3, 3); + var filteredEvents = Blockly.Events.filter(events, true); + assertEquals(2, filteredEvents.length); // duplicate moves should have been removed. + // test that the order hasn't changed + assertTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); + assertTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); + assertEquals(3, filteredEvents[1].newCoordinate.x); + assertEquals(3, filteredEvents[1].newCoordinate.y); + }); + + test('Backward', function() { + var block = this.workspace.newBlock('field_variable_test_block', '1'); + var events = [ new Blockly.Events.BlockCreate(block) ]; + addMoveEvent(events, block, 1, 1); + addMoveEvent(events, block, 2, 2); + addMoveEvent(events, block, 3, 3); + var filteredEvents = Blockly.Events.filter(events, false); + assertEquals(2, filteredEvents.length); // duplicate event should have been removed. + // test that the order hasn't changed + assertTrue(filteredEvents[0] instanceof Blockly.Events.BlockCreate); + assertTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); + assertEquals(1, filteredEvents[1].newCoordinate.x); + assertEquals(1, filteredEvents[1].newCoordinate.y); + }); + + test('Merge move events', function() { + var block = this.workspace.newBlock('field_variable_test_block', '1'); + var events = []; + addMoveEvent(events, block, 0, 0); + addMoveEvent(events, block, 1, 1); + var filteredEvents = Blockly.Events.filter(events, true); + assertEquals(1, filteredEvents.length); // second move event merged into first + assertEquals(1, filteredEvents[0].newCoordinate.x); + assertEquals(1, filteredEvents[0].newCoordinate.y); + }); + + test('Merge change events', function() { + var block1 = this.workspace.newBlock('field_variable_test_block', '1'); + var events = [ + new Blockly.Events.Change(block1, 'field', 'VAR', 'item', 'item1'), + new Blockly.Events.Change(block1, 'field', 'VAR', 'item1', 'item2') + ]; + var filteredEvents = Blockly.Events.filter(events, true); + assertEquals(1, filteredEvents.length); // second change event merged into first + assertEquals('item', filteredEvents[0].oldValue); + assertEquals('item2', filteredEvents[0].newValue); + }); + + test('Merge ui events', function() { + var block1 = this.workspace.newBlock('field_variable_test_block', '1'); + var block2 = this.workspace.newBlock('field_variable_test_block', '2'); + var block3 = this.workspace.newBlock('field_variable_test_block', '3'); + var events = [ + new Blockly.Events.Ui(block1, 'commentOpen', 'false', 'true'), + new Blockly.Events.Ui(block1, 'click', 'false', 'true'), + new Blockly.Events.Ui(block2, 'mutatorOpen', 'false', 'true'), + new Blockly.Events.Ui(block2, 'click', 'false', 'true'), + new Blockly.Events.Ui(block3, 'warningOpen', 'false', 'true'), + new Blockly.Events.Ui(block3, 'click', 'false', 'true') + ]; + var filteredEvents = Blockly.Events.filter(events, true); + assertEquals(3, filteredEvents.length); // click event merged into corresponding *Open event + assertEquals('commentOpen', filteredEvents[0].element); + assertEquals('mutatorOpen', filteredEvents[1].element); + assertEquals('warningOpen', filteredEvents[2].element); + }); + + test('Colliding events not dropped', function() { + // Tests that events that collide on a (event, block, workspace) tuple + // but cannot be merged do not get dropped during filtering. + var block = this.workspace.newBlock('field_variable_test_block', '1'); + var events = [ + new Blockly.Events.Ui(block, 'click', undefined, undefined), + new Blockly.Events.Ui(block, 'stackclick', undefined, undefined) + ]; + var filteredEvents = Blockly.Events.filter(events, true); + // click and stackclick should both exist + assertEquals(2, filteredEvents.length); + assertEquals('click', filteredEvents[0].element); + assertEquals('stackclick', filteredEvents[1].element); + }); + + test('Merging null operations dropped', function() { + // Mutator composition could result in move events for blocks + // connected to the mutated block that were null operations. This + // leads to events in the undo/redo queue that do nothing, requiring + // an extra undo/redo to proceed to the next event. This test ensures + // that two move events that do get merged (disconnecting and + // reconnecting a block in response to a mutator change) are filtered + // from the queue. + var block = this.workspace.newBlock('field_variable_test_block', '1'); + block.setParent(null); + var events = []; + addMoveEventParent(events, block, null); + addMoveEventParent(events, block, null); + var filteredEvents = Blockly.Events.filter(events, true); + // The two events should be merged, but because nothing has changed + // they will be filtered out. + assertEquals(0, filteredEvents.length); + }); + + test('Move events different blocks not merged', function() { + // Move events should only merge if they refer to the same block and are + // consecutive. + // See github.com/google/blockly/pull/1892 for a worked example showing + // how merging non-consecutive events can fail when replacing a shadow + // block. + var block1 = createSimpleTestBlock(this.workspace); + var block2 = createSimpleTestBlock(this.workspace); + + var events = []; + addMoveEvent(events, block1, 1, 1); + addMoveEvent(events, block2, 1, 1); + events.push(new Blockly.Events.BlockDelete(block2)); + addMoveEvent(events, block1, 2, 2); + + var filteredEvents = Blockly.Events.filter(events, true); + // Nothing should have merged. + assertEquals(4, filteredEvents.length); + // test that the order hasn't changed + assertTrue(filteredEvents[0] instanceof Blockly.Events.BlockMove); + assertTrue(filteredEvents[1] instanceof Blockly.Events.BlockMove); + assertTrue(filteredEvents[2] instanceof Blockly.Events.BlockDelete); + assertTrue(filteredEvents[3] instanceof Blockly.Events.BlockMove); + }); + }); + + suite('Firing', function() { + function temporary_fireEvent(event) { + if (!Blockly.Events.isEnabled()) { + return; + } + Blockly.Events.FIRE_QUEUE_.push(event); + Blockly.Events.fireNow_(); + } + + setup(function() { + this.savedFireFunc_ = Blockly.Events.fire; + Blockly.Events.fire = temporary_fireEvent; + temporary_fireEvent.firedEvents_ = []; + }); + + teardown(function() { + Blockly.Events.fire = this.savedFireFunc_; + sinon.restore(); + }); + + test('New block new var', function() { + // Expect three calls to genUid: one to set the block's ID, one for the event + // group's id, and one for the variable's ID. + var stub = sinon.stub(Blockly.utils, "genUid"); + stub.onCall(0).returns('1'); + stub.onCall(1).returns('2'); + stub.onCall(2).returns('3'); + var _ = this.workspace.newBlock('field_variable_test_block'); + + var firedEvents = this.workspace.undoStack_; + // Expect two events: varCreate and block create. + assertEquals(2, firedEvents.length); + + var event0 = firedEvents[0]; + var event1 = firedEvents[1]; + assertEquals('var_create', event0.type); + assertEquals('create', event1.type); + + // Expect the events to have the same group ID. + assertEquals(event0.group, event1.group); + + // Expect the group ID to be the result of the second call to genUid. + assertEquals('2', event0.group); + + // Expect the workspace to have a variable with ID '3'. + assertNotNull(this.workspace.getVariableById('3')); + assertEquals('3', event0.varId); + }); + + test('New block new var xml', function() { + // The sequence of events should be the same whether the block was created from + // XML or directly. + var dom = Blockly.Xml.textToDom( + '' + + ' ' + + ' name1' + + ' ' + + ''); + Blockly.Xml.domToWorkspace(dom, this.workspace); + + var firedEvents = this.workspace.undoStack_; + // Expect two events: varCreate and block create. + assertEquals(2, firedEvents.length); + + var event0 = firedEvents[0]; + var event1 = firedEvents[1]; + assertEquals('var_create', event0.type); + assertEquals('create', event1.type); + + // Expect the events to have the same group ID. + assertEquals(event0.group, event1.group); + + // Expect the workspace to have a variable with ID 'id1'. + assertNotNull(this.workspace.getVariableById('id1')); + assertEquals('id1', event0.varId); + }); + }); }); diff --git a/tests/mocha/test_helpers.js b/tests/mocha/test_helpers.js index 15ddc3f88..61aae9475 100644 --- a/tests/mocha/test_helpers.js +++ b/tests/mocha/test_helpers.js @@ -191,3 +191,4 @@ function createTestBlock() { } }; } + From a4a390ba6d29323079ecff981697c9d0659798a9 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 15 Apr 2020 15:46:42 -0700 Subject: [PATCH 019/139] Add user agent types so they appear in dts (#3825) --- core/utils/useragent.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/core/utils/useragent.js b/core/utils/useragent.js index 401a49afb..84d036d57 100644 --- a/core/utils/useragent.js +++ b/core/utils/useragent.js @@ -20,6 +20,45 @@ goog.provide('Blockly.utils.userAgent'); goog.require('Blockly.utils.global'); +/** @const {boolean} */ +Blockly.utils.userAgent.IE; + +/** @const {boolean} */ +Blockly.utils.userAgent.EDGE; + +/** @const {boolean} */ +Blockly.utils.userAgent.JAVA_FX; + +/** @const {boolean} */ +Blockly.utils.userAgent.CHROME; + +/** @const {boolean} */ +Blockly.utils.userAgent.WEBKIT; + +/** @const {boolean} */ +Blockly.utils.userAgent.GECKO; + +/** @const {boolean} */ +Blockly.utils.userAgent.ANDROID; + +/** @const {boolean} */ +Blockly.utils.userAgent.IPAD; + +/** @const {boolean} */ +Blockly.utils.userAgent.IPOD; + +/** @const {boolean} */ +Blockly.utils.userAgent.IPHONE; + +/** @const {boolean} */ +Blockly.utils.userAgent.MAC; + +/** @const {boolean} */ +Blockly.utils.userAgent.TABLET; + +/** @const {boolean} */ +Blockly.utils.userAgent.MOBILE; + (function(raw) { Blockly.utils.userAgent.raw = raw; var rawUpper = Blockly.utils.userAgent.raw.toUpperCase(); From 493c89869eac8bbe437dd58c80fd321e30ac435b Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 15 Apr 2020 15:54:36 -0700 Subject: [PATCH 020/139] Rename dom Node enum (#3824) * Rename Node enum to NodeType to avoid conflict with type Node --- core/components/component.js | 3 ++- core/utils/dom.js | 12 ++++++------ core/xml.js | 11 ++++++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/core/components/component.js b/core/components/component.js index 2a19d5734..24bc79403 100644 --- a/core/components/component.js +++ b/core/components/component.js @@ -476,7 +476,8 @@ Blockly.Component.prototype.addChildAt = function(child, index, opt_render) { child.element_.parentNode && // Under some circumstances, IE8 implicitly creates a Document Fragment // for detached nodes, so ensure the parent is an Element as it should be. - child.element_.parentNode.nodeType == Blockly.utils.dom.Node.ELEMENT_NODE) { + child.element_.parentNode.nodeType == + Blockly.utils.dom.NodeType.ELEMENT_NODE) { // We don't touch the DOM, but if the parent is in the document, and the // child element is in the document but not marked as such, then we call // enterDocument on the child. diff --git a/core/utils/dom.js b/core/utils/dom.js index c68f98778..202889c05 100644 --- a/core/utils/dom.js +++ b/core/utils/dom.js @@ -44,7 +44,7 @@ Blockly.utils.dom.XLINK_NS = 'http://www.w3.org/1999/xlink'; * https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType * @enum {number} */ -Blockly.utils.dom.Node = { +Blockly.utils.dom.NodeType = { ELEMENT_NODE: 1, TEXT_NODE: 3, COMMENT_NODE: 8, @@ -76,10 +76,10 @@ Blockly.utils.dom.canvasContext_ = null; * Helper method for creating SVG elements. * @param {string} name Element's tag name. * @param {!Object} attrs Dictionary of attribute names and values. - * @param {Element} parent Optional parent on which to append the element. + * @param {Element=} opt_parent Optional parent on which to append the element. * @return {!SVGElement} Newly created SVG element. */ -Blockly.utils.dom.createSvgElement = function(name, attrs, parent) { +Blockly.utils.dom.createSvgElement = function(name, attrs, opt_parent) { var e = /** @type {!SVGElement} */ (document.createElementNS(Blockly.utils.dom.SVG_NS, name)); for (var key in attrs) { @@ -91,8 +91,8 @@ Blockly.utils.dom.createSvgElement = function(name, attrs, parent) { if (document.body.runtimeStyle) { // Indicates presence of IE-only attr. e.runtimeStyle = e.currentStyle = e.style; } - if (parent) { - parent.appendChild(e); + if (opt_parent) { + opt_parent.appendChild(e); } return e; }; @@ -192,7 +192,7 @@ Blockly.utils.dom.insertAfter = function(newNode, refNode) { */ Blockly.utils.dom.containsNode = function(parent, descendant) { return !!(parent.compareDocumentPosition(descendant) & - Blockly.utils.dom.Node.DOCUMENT_POSITION_CONTAINED_BY); + Blockly.utils.dom.NodeType.DOCUMENT_POSITION_CONTAINED_BY); }; /** diff --git a/core/xml.js b/core/xml.js index e5d7cd6e3..0120ed279 100644 --- a/core/xml.js +++ b/core/xml.js @@ -253,7 +253,7 @@ Blockly.Xml.cloneShadow_ = function(shadow, opt_noId) { while (node && !node.nextSibling) { textNode = node; node = node.parentNode; - if (textNode.nodeType == Blockly.utils.dom.Node.TEXT_NODE && + if (textNode.nodeType == Blockly.utils.dom.NodeType.TEXT_NODE && textNode.data.trim() == '' && node.firstChild != textNode) { // Prune whitespace after a tag. Blockly.utils.dom.removeNode(textNode); @@ -262,7 +262,8 @@ Blockly.Xml.cloneShadow_ = function(shadow, opt_noId) { if (node) { textNode = node; node = node.nextSibling; - if (textNode.nodeType == Blockly.utils.dom.Node.TEXT_NODE && textNode.data.trim() == '') { + if (textNode.nodeType == Blockly.utils.dom.NodeType.TEXT_NODE && + textNode.data.trim() == '') { // Prune whitespace before a tag. Blockly.utils.dom.removeNode(textNode); } @@ -583,7 +584,7 @@ Blockly.Xml.domToBlock = function(xmlBlock, workspace) { */ Blockly.Xml.domToVariables = function(xmlVariables, workspace) { for (var i = 0, xmlChild; (xmlChild = xmlVariables.childNodes[i]); i++) { - if (xmlChild.nodeType != Blockly.utils.dom.Node.ELEMENT_NODE) { + if (xmlChild.nodeType != Blockly.utils.dom.NodeType.ELEMENT_NODE) { continue; // Skip text nodes. } var type = xmlChild.getAttribute('type'); @@ -613,7 +614,7 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) { var blockChild = null; for (var i = 0, xmlChild; (xmlChild = xmlBlock.childNodes[i]); i++) { - if (xmlChild.nodeType == Blockly.utils.dom.Node.TEXT_NODE) { + if (xmlChild.nodeType == Blockly.utils.dom.NodeType.TEXT_NODE) { // Ignore any text at the level. It's all whitespace anyway. continue; } @@ -623,7 +624,7 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) { var childBlockElement = null; var childShadowElement = null; for (var j = 0, grandchild; (grandchild = xmlChild.childNodes[j]); j++) { - if (grandchild.nodeType == Blockly.utils.dom.Node.ELEMENT_NODE) { + if (grandchild.nodeType == Blockly.utils.dom.NodeType.ELEMENT_NODE) { if (grandchild.nodeName.toLowerCase() == 'block') { childBlockElement = /** @type {!Element} */ (grandchild); } else if (grandchild.nodeName.toLowerCase() == 'shadow') { From d61f3c6f38b41c285dda574199a9800d12d5190f Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Wed, 15 Apr 2020 15:55:49 -0700 Subject: [PATCH 021/139] Converting extensions_test to mocha. (#3820) * Converting extensions_test to mocha. * Add spacing between test cases. * Fix cleanup for block type. * Add cleanup for event state. --- tests/jsunit/extensions_test.js | 643 -------------------------------- tests/jsunit/index.html | 2 +- tests/mocha/extensions_test.js | 511 +++++++++++++++++++++++++ tests/mocha/index.html | 1 + tests/mocha/xml_test.js | 3 + 5 files changed, 516 insertions(+), 644 deletions(-) delete mode 100644 tests/jsunit/extensions_test.js create mode 100644 tests/mocha/extensions_test.js diff --git a/tests/jsunit/extensions_test.js b/tests/jsunit/extensions_test.js deleted file mode 100644 index 43bb66deb..000000000 --- a/tests/jsunit/extensions_test.js +++ /dev/null @@ -1,643 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - - /** - * @fileoverview Tests for Blockly.Extensions - * @author Anm@anm.me (Andrew n marshall) - */ -'use strict'; - -function test_extension() { - var workspace = new Blockly.Workspace(); - var block; - try { - assertUndefined(Blockly.Extensions.ALL_['extensions_test']); - - var numCallsToBefore = 0; - var numCallsToAfter = 0; - - // Extension defined before the block type is defined. - Blockly.Extensions.register('extensions_test_before', function () { - numCallsToBefore++; - this.extendedWithBefore = true; - }); - - Blockly.defineBlocksWithJsonArray([{ - "type": "extension_test_block", - "message0": "extension_test_block", - "extensions": ["extensions_test_before", "extensions_test_after"] - }]); - - // Extension defined after the block type (but before instantiation). - Blockly.Extensions.register('extensions_test_after', function () { - numCallsToAfter++; - this.extendedWithAfter = true; - }); - - assert(typeof Blockly.Extensions.ALL_['extensions_test_before'] == 'function'); - assert(typeof Blockly.Extensions.ALL_['extensions_test_after'] == 'function'); - assertEquals(0, numCallsToBefore); - assertEquals(0, numCallsToAfter); - - block = new Blockly.Block(workspace, 'extension_test_block'); - - assertEquals(1, numCallsToBefore); - assertEquals(1, numCallsToAfter); - assert(block.extendedWithBefore); - assert(block.extendedWithAfter); - } finally { - block && block.dispose(); - workspace.dispose(); - - delete Blockly.Extensions.ALL_['extensions_test_before']; - delete Blockly.Extensions.ALL_['extensions_test_after']; - delete Blockly.Blocks['extension_test_block']; - } -} - -function test_extension_missing() { - var workspace = new Blockly.Workspace(); - var block; - var exceptionWasThrown = false; - try { - assertUndefined(Blockly.Extensions.ALL_['missing_extension']); - Blockly.defineBlocksWithJsonArray([{ - "type": "missing_extension_block", - "message0": "missing_extension_block", - "extensions": ["missing_extension"] - }]); - - block = new Blockly.Block(workspace, 'missing_extension_block'); - } catch (e) { - // Expected. - exceptionWasThrown = true; - } finally { - block && block.dispose(); - workspace.dispose(); - delete Blockly.Blocks['missing_extension_block']; - } - assert(exceptionWasThrown); -} - -function test_extension_not_a_function() { - var exceptionWasThrown = false; - try { - assertUndefined(Blockly.Extensions.ALL_['extension_just_a_string']); - Blockly.Extensions.register('extension_just_a_string', 'extension_just_a_string'); - } catch (e) { - // Expected. - exceptionWasThrown = true; - } finally { - delete Blockly.Extensions.ALL_['extension_just_a_string']; - } - assert(exceptionWasThrown); - - var exceptionWasThrown = false; - try { - assertUndefined(Blockly.Extensions.ALL_['extension_is_null']); - Blockly.Extensions.register('extension_is_null', null); - } catch (e) { - // Expected. - exceptionWasThrown = true; - } finally { - delete Blockly.Extensions.ALL_['extension_is_null']; - } - assert(exceptionWasThrown); - - var exceptionWasThrown = false; - try { - assertUndefined(Blockly.Extensions.ALL_['extension_is_undefined']); - Blockly.Extensions.register('extension_is_undefined'); - } catch (e) { - // Expected. - exceptionWasThrown = true; - } finally { - delete Blockly.Extensions.ALL_['extension_is_undefined']; - } - assert(exceptionWasThrown); -} - -function test_parent_tooltip_when_inline() { - var defaultTooltip = "defaultTooltip"; - var parentTooltip = "parentTooltip"; - - var workspace = new Blockly.Workspace(); - var block; - try { - Blockly.defineBlocksWithJsonArray([ - { - "type": "test_parent_tooltip_when_inline", - "message0": "test_parent_tooltip_when_inline", - "output": true, - "tooltip": defaultTooltip, - "extensions": ["parent_tooltip_when_inline"] - }, - { - "type": "test_parent", - "message0": "%1", - "args0": [ - { - "type": "input_value", - "name": "INPUT" - } - ], - "tooltip": parentTooltip - } - ]); - - block = new Blockly.Block(workspace, 'test_parent_tooltip_when_inline'); - - // Tooltip is dynamic after extension initialization. - assert(typeof block.tooltip == 'function'); - assertEquals(block.tooltip(), defaultTooltip); - - // Tooltip is normal before connected to parent. - var parent = new Blockly.Block(workspace, 'test_parent'); - assertEquals(parent.tooltip, parentTooltip); - assertFalse(!!parent.inputsInline); - - // Tooltip is normal when parent is not inline. - parent.getInput('INPUT').connection.connect(block.outputConnection); - assertEquals(block.getParent(), parent); - assertEquals(block.tooltip(), defaultTooltip); - - // Tooltip is parent's when parent is inline. - parent.setInputsInline(true); - assertEquals(block.tooltip(), parentTooltip); - - // Tooltip revert when disconnected. - parent.getInput('INPUT').connection.disconnect(); - assert(!block.getParent()); - assertEquals(block.tooltip(), defaultTooltip); - } finally { - block && block.dispose(); - workspace.dispose(); - - delete Blockly.Blocks['test_parent_tooltip_when_inline']; - delete Blockly.Blocks['test_parent']; - } -} - -function test_mixin_extension() { - var TEST_MIXIN = { - field: 'FIELD', - method: function() { - console.log('TEXT_MIXIN method()'); - } - }; - - var workspace = new Blockly.Workspace(); - var block; - try { - assertUndefined(Blockly.Extensions.ALL_['mixin_test']); - - // Extension defined before the block type is defined. - Blockly.Extensions.registerMixin('mixin_test', TEST_MIXIN); - assert(typeof Blockly.Extensions.ALL_['mixin_test'] == 'function'); - - Blockly.defineBlocksWithJsonArray([{ - "type": "test_block_mixin", - "message0": "test_block_mixin", - "extensions": ["mixin_test"] - }]); - - block = new Blockly.Block(workspace, 'test_block_mixin'); - - assertEquals(TEST_MIXIN.field, block.field); - assertEquals(TEST_MIXIN.method, block.method); - } finally { - block && block.dispose(); - workspace.dispose(); - - delete Blockly.Extensions.ALL_['mixin_test']; - delete Blockly.Blocks['test_block_mixin']; - } -} - -function test_bad_mixin_overwrites_local_value() { - var TEST_MIXIN_BAD_INPUTLIST = { - inputList: 'bad inputList' // Defined in constructor - }; - - var workspace = new Blockly.Workspace(); - var block; - try { - assertUndefined(Blockly.Extensions.ALL_['mixin_bad_inputList']); - - // Extension defined before the block type is defined. - Blockly.Extensions.registerMixin('mixin_bad_inputList', TEST_MIXIN_BAD_INPUTLIST); - assert(typeof Blockly.Extensions.ALL_['mixin_bad_inputList'] == 'function'); - - Blockly.defineBlocksWithJsonArray([{ - "type": "test_block_bad_inputList", - "message0": "test_block_bad_inputList", - "extensions": ["mixin_bad_inputList"] - }]); - - try { - block = new Blockly.Block(workspace, 'test_block_bad_inputList'); - } catch (e) { - // Expected Error - assert(e.message.indexOf('inputList') >= 0); // Reference the conflict - return; - } - fail('Expected error when constructing block'); - } finally { - block && block.dispose(); - workspace.dispose(); - - delete Blockly.Extensions.ALL_['mixin_bad_inputList']; - delete Blockly.Blocks['test_block_bad_inputList']; - } -} - -function test_bad_mixin_overwrites_prototype() { - var TEST_MIXIN_BAD_COLOUR = { - colour_: 'bad colour_' // Defined on prototype - }; - - var workspace = new Blockly.Workspace(); - var block; - try { - assertUndefined(Blockly.Extensions.ALL_['mixin_bad_colour_']); - - // Extension defined before the block type is defined. - Blockly.Extensions.registerMixin('mixin_bad_colour_', TEST_MIXIN_BAD_COLOUR); - assert(typeof Blockly.Extensions.ALL_['mixin_bad_colour_'] == 'function'); - - Blockly.defineBlocksWithJsonArray([{ - "type": "test_block_bad_colour", - "message0": "test_block_bad_colour", - "extensions": ["mixin_bad_colour_"] - }]); - - try { - block = new Blockly.Block(workspace, 'test_block_bad_colour'); - } catch (e) { - // Expected Error - assert(e.message.indexOf('colour_') >= 0); // Reference the conflict - return; - } - fail('Expected error when constructing block'); - } finally { - block && block.dispose(); - workspace.dispose(); - - delete Blockly.Extensions.ALL_['mixin_bad_colour_']; - delete Blockly.Blocks['test_block_bad_colour']; - } -} - -function test_mutator_mixin() { - var workspace = new Blockly.Workspace(); - var block; - - try { - Blockly.defineBlocksWithJsonArray([{ - "type": "mutator_test_block", - "message0": "mutator_test_block", - "mutator": "mutator_test" - }]); - - // Events code calls mutationToDom and expects it to give back a meaningful - // value. - Blockly.Events.disable(); - Blockly.Extensions.registerMutator('mutator_test', - { - domToMutation: function() { - return 'domToMutationFn'; - }, - mutationToDom: function() { - return 'mutationToDomFn'; - }, - compose: function() { - return 'composeFn'; - }, - decompose: function() { - return 'decomposeFn'; - } - }); - - block = new Blockly.Block(workspace, 'mutator_test_block'); - - // Make sure all of the functions were installed correctly. - assertEquals(block.domToMutation(), 'domToMutationFn'); - assertEquals(block.mutationToDom(), 'mutationToDomFn'); - assertEquals(block.compose(), 'composeFn'); - assertEquals(block.decompose(), 'decomposeFn'); - } finally { - if (block) { - block.dispose(); - } - workspace.dispose(); - Blockly.Events.enable(); - delete Blockly.Extensions.ALL_['mutator_test']; - } -} - -function test_mutator_mixin_no_dialog() { - var workspace = new Blockly.Workspace(); - var block; - - try { - Blockly.defineBlocksWithJsonArray([{ - "type": "mutator_test_block", - "message0": "mutator_test_block", - "mutator": "mutator_test" - }]); - - // Events code calls mutationToDom and expects it to give back a meaningful - // value. - Blockly.Events.disable(); - assertUndefined(Blockly.Extensions.ALL_['mutator_test']); - Blockly.Extensions.registerMutator('mutator_test', - { - domToMutation: function() { - return 'domToMutationFn'; - }, - mutationToDom: function() { - return 'mutationToDomFn'; - } - }); - - block = new Blockly.Block(workspace, 'mutator_test_block'); - - // Make sure all of the functions were installed correctly. - assertEquals(block.domToMutation(), 'domToMutationFn'); - assertEquals(block.mutationToDom(), 'mutationToDomFn'); - assertFalse(block.hasOwnProperty('compose')); - assertFalse(block.hasOwnProperty('decompose')); - } finally { - if (block) { - block.dispose(); - } - workspace.dispose(); - Blockly.Events.enable(); - delete Blockly.Extensions.ALL_['mutator_test']; - } -} - -// Explicitly check all four things that could be missing. -function test_mutator_mixin_no_decompose_fails() { - var exceptionWasThrown = false; - try { - Blockly.Extensions.registerMutator('mutator_test', - { - domToMutation: function() { - return 'domToMutationFn'; - }, - mutationToDom: function() { - return 'mutationToDomFn'; - }, - compose: function() { - return 'composeFn'; - } - }); - } catch (e) { - // Expected. - exceptionWasThrown = true; - } finally { - delete Blockly.Extensions.ALL_['mutator_test']; - } - assertTrue(exceptionWasThrown); -} - -function test_mutator_mixin_no_compose_fails() { - var exceptionWasThrown = false; - try { - Blockly.Extensions.registerMutator('mutator_test', - { - domToMutation: function() { - return 'domToMutationFn'; - }, - mutationToDom: function() { - return 'mutationToDomFn'; - }, - decompose: function() { - return 'decomposeFn'; - } - }); - } catch (e) { - // Expected. - exceptionWasThrown = true; - } finally { - delete Blockly.Extensions.ALL_['mutator_test']; - } - assertTrue(exceptionWasThrown); -} - -function test_mutator_mixin_no_domToMutation_fails() { - var exceptionWasThrown = false; - try { - Blockly.Extensions.registerMutator('mutator_test', - { - mutationToDom: function() { - return 'mutationToDomFn'; - }, - compose: function() { - return 'composeFn'; - }, - decompose: function() { - return 'decomposeFn'; - } - }); - } catch (e) { - // Expected. - exceptionWasThrown = true; - } finally { - delete Blockly.Extensions.ALL_['mutator_test']; - } - assertTrue(exceptionWasThrown); -} - -function test_mutator_mixin_no_mutationToDom_fails() { - var exceptionWasThrown = false; - try { - Blockly.Extensions.registerMutator('mutator_test', - { - domToMutation: function() { - return 'domToMutationFn'; - }, - compose: function() { - return 'composeFn'; - }, - decompose: function() { - return 'decomposeFn'; - } - }); - } catch (e) { - // Expected. - exceptionWasThrown = true; - } finally { - delete Blockly.Extensions.ALL_['mutator_test']; - } - assertTrue(exceptionWasThrown); -} - -function test_use_mutator_as_extension_fails() { - var workspace = new Blockly.Workspace(); - var block; - var exceptionWasThrown = false; - - try { - Blockly.defineBlocksWithJsonArray([{ - "type": "mutator_test_block", - "message0": "mutator_test_block", - "extensions": ["mutator_test"] - }]); - - Blockly.Events.disable(); - assertUndefined(Blockly.Extensions.ALL_['mutator_test']); - Blockly.Extensions.registerMutator('mutator_test', - { - domToMutation: function() { - return 'domToMutationFn'; - }, - mutationToDom: function() { - return 'mutationToDomFn'; - } - }); - - // Events code calls mutationToDom and expects it to give back a meaningful - // value. - block = new Blockly.Block(workspace, 'mutator_test_block'); - } catch (e) { - // Expected - exceptionWasThrown = true; - // Should have failed on apply, not on register. - assertNotNull(Blockly.Extensions.ALL_['mutator_test']); - } finally { - if (block) { - block.dispose(); - } - workspace.dispose(); - Blockly.Events.enable(); - delete Blockly.Extensions.ALL_['mutator_test']; - } - assertTrue(exceptionWasThrown); -} - -function test_use_mutator_mixin_as_extension_fails() { - var workspace = new Blockly.Workspace(); - var block; - var exceptionWasThrown = false; - - try { - Blockly.defineBlocksWithJsonArray([{ - "type": "mutator_test_block", - "message0": "mutator_test_block", - "extensions": ["mutator_test"] - }]); - - // Events code calls mutationToDom and expects it to give back a meaningful - // value. - Blockly.Events.disable(); - assertUndefined(Blockly.Extensions.ALL_['mutator_test']); - Blockly.Extensions.registerMixin('mutator_test', - { - domToMutation: function() { - return 'domToMutationFn'; - }, - mutationToDom: function() { - return 'mutationToDomFn'; - } - }); - - block = new Blockly.Block(workspace, 'mutator_test_block'); - } catch (e) { - // Expected - exceptionWasThrown = true; - // Should have failed on apply, not on register. - assertNotNull(Blockly.Extensions.ALL_['mutator_test']); - } finally { - if (block) { - block.dispose(); - } - workspace.dispose(); - Blockly.Events.enable(); - delete Blockly.Extensions.ALL_['mutator_test']; - } - assertTrue(exceptionWasThrown); -} - -function test_use_extension_as_mutator_fails() { - var workspace = new Blockly.Workspace(); - var block; - var exceptionWasThrown = false; - - try { - Blockly.defineBlocksWithJsonArray([{ - "type": "mutator_test_block", - "message0": "mutator_test_block", - "mutator": ["extensions_test"] - }]); - - // Events code calls mutationToDom and expects it to give back a meaningful - // value. - Blockly.Events.disable(); - assertUndefined(Blockly.Extensions.ALL_['extensions_test']); - Blockly.Extensions.register('extensions_test', function() { - return 'extensions_test_fn'; - }); - - block = new Blockly.Block(workspace, 'mutator_test_block'); - } catch (e) { - // Expected - exceptionWasThrown = true; - // Should have failed on apply, not on register. - assertNotNull(Blockly.Extensions.ALL_['extensions_test']); - } finally { - if (block) { - block.dispose(); - } - workspace.dispose(); - Blockly.Events.enable(); - delete Blockly.Extensions.ALL_['extensions_test']; - } - assertTrue(exceptionWasThrown); -} - -function test_mutator_mixin_plus_function() { - var workspace = new Blockly.Workspace(); - var block; - var fnWasCalled = false; - - try { - Blockly.defineBlocksWithJsonArray([{ - "type": "mutator_test_block", - "message0": "mutator_test_block", - "mutator": ["extensions_test"] - }]); - - Blockly.Events.disable(); - assertUndefined(Blockly.Extensions.ALL_['extensions_test']); - Blockly.Extensions.registerMutator('extensions_test', - { - domToMutation: function() { - return 'domToMutationFn'; - }, - mutationToDom: function() { - return 'mutationToDomFn'; - } - }, - function() { - fnWasCalled = true; - } - ); - - // Events code calls mutationToDom and expects it to give back a meaningful - // value. - block = new Blockly.Block(workspace, 'mutator_test_block'); - } finally { - if (block) { - block.dispose(); - } - workspace.dispose(); - Blockly.Events.enable(); - delete Blockly.Extensions.ALL_['extensions_test']; - } - assertTrue(fnWasCalled); -} diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index 221ff2618..f7634f8cd 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -17,7 +17,7 @@ - + diff --git a/tests/mocha/extensions_test.js b/tests/mocha/extensions_test.js new file mode 100644 index 000000000..fcabd8e30 --- /dev/null +++ b/tests/mocha/extensions_test.js @@ -0,0 +1,511 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +suite('Extensions', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + this.blockTypesCleanup_ = []; + this.extensionsCleanup_ = []; + }); + teardown(function() { + var i; + for (i = 0; i < this.blockTypesCleanup_.length; i++) { + var blockType = this.blockTypesCleanup_[i]; + delete Blockly.Blocks[blockType]; + } + for (i = 0; i < this.extensionsCleanup_.length; i++) { + var extension = this.extensionsCleanup_[i]; + delete Blockly.Extensions.ALL_[extension]; + } + this.workspace.dispose(); + // Clear Blockly.Event state. + Blockly.Events.setGroup(false); + Blockly.Events.disabled_ = 0; + sinon.restore(); + }); + + test('Definition before and after block type', function() { + this.extensionsCleanup_.push('extensions_test_before'); + this.extensionsCleanup_.push('extensions_test_after'); + this.blockTypesCleanup_.push('extension_test_block'); + + assertUndefined(Blockly.Extensions.ALL_['extensions_test_before']); + var beforeCallback = sinon.spy(); + // Extension defined before the block type is defined. + Blockly.Extensions.register('extensions_test_before', beforeCallback); + + Blockly.defineBlocksWithJsonArray([{ + "type": "extension_test_block", + "message0": "extension_test_block", + "extensions": ["extensions_test_before", "extensions_test_after"] + }]); + + assertUndefined(Blockly.Extensions.ALL_['extensions_test_after']); + var afterCallback = sinon.spy(); + // Extension defined after the block type (but before instantiation). + Blockly.Extensions.register('extensions_test_after', afterCallback); + + assert(typeof Blockly.Extensions.ALL_['extensions_test_before'] == 'function'); + assert(typeof Blockly.Extensions.ALL_['extensions_test_after'] == 'function'); + sinon.assert.notCalled(beforeCallback); + sinon.assert.notCalled(afterCallback); + + var block = new Blockly.Block(this.workspace, 'extension_test_block'); + + sinon.assert.calledOnce(beforeCallback); + sinon.assert.calledOnce(afterCallback); + sinon.assert.calledOn(beforeCallback, block); + sinon.assert.calledOn(afterCallback, block); + }); + + test('Parent tooltip when inline', function() { + this.blockTypesCleanup_.push('test_parent_tooltip_when_inline'); + this.blockTypesCleanup_.push('test_parent'); + + var defaultTooltip = "defaultTooltip"; + var parentTooltip = "parentTooltip"; + Blockly.defineBlocksWithJsonArray([ + { + "type": "test_parent_tooltip_when_inline", + "message0": "test_parent_tooltip_when_inline", + "output": true, + "tooltip": defaultTooltip, + "extensions": ["parent_tooltip_when_inline"] + }, + { + "type": "test_parent", + "message0": "%1", + "args0": [ + { + "type": "input_value", + "name": "INPUT" + } + ], + "tooltip": parentTooltip + } + ]); + + var block = + new Blockly.Block(this.workspace, 'test_parent_tooltip_when_inline'); + + // Tooltip is dynamic after extension initialization. + assert(typeof block.tooltip == 'function'); + assertEquals(block.tooltip(), defaultTooltip); + + // Tooltip is normal before connected to parent. + var parent = new Blockly.Block(this.workspace, 'test_parent'); + assertEquals(parent.tooltip, parentTooltip); + assertFalse(!!parent.inputsInline); + + // Tooltip is normal when parent is not inline. + parent.getInput('INPUT').connection.connect(block.outputConnection); + assertEquals(block.getParent(), parent); + assertEquals(block.tooltip(), defaultTooltip); + + // Tooltip is parent's when parent is inline. + parent.setInputsInline(true); + assertEquals(block.tooltip(), parentTooltip); + + // Tooltip revert when disconnected. + parent.getInput('INPUT').connection.disconnect(); + assert(!block.getParent()); + assertEquals(block.tooltip(), defaultTooltip); + }); + + suite('Mixin', function() { + test('Basic', function() { + this.extensionsCleanup_.push('mixin_test'); + this.blockTypesCleanup_.push('test_block_mixin'); + + var testMixin = { + field: 'FIELD', + method: function() { + console.log('TEXT_MIXIN method()'); + } + }; + + assertUndefined(Blockly.Extensions.ALL_['mixin_test']); + // Extension defined before the block type is defined. + Blockly.Extensions.registerMixin('mixin_test', testMixin); + + assert(typeof Blockly.Extensions.ALL_['mixin_test'] == 'function'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "test_block_mixin", + "message0": "test_block_mixin", + "extensions": ["mixin_test"] + }]); + + var block = new Blockly.Block(this.workspace, 'test_block_mixin'); + + assertEquals(testMixin.field, block.field); + assertEquals(testMixin.method, block.method); + }); + + suite('Mutator', function() { + test('Basic', function() { + this.extensionsCleanup_.push('mutator_test'); + this.blockTypesCleanup_.push('mutator_test_block'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "mutator_test_block", + "message0": "mutator_test_block", + "mutator": "mutator_test" + }]); + + // Events code calls mutationToDom and expects it to give back a meaningful + // value. + Blockly.Events.disable(); + Blockly.Extensions.registerMutator('mutator_test', + { + domToMutation: function() { + return 'domToMutationFn'; + }, + mutationToDom: function() { + return 'mutationToDomFn'; + }, + compose: function() { + return 'composeFn'; + }, + decompose: function() { + return 'decomposeFn'; + } + }); + + var block = new Blockly.Block(this.workspace, 'mutator_test_block'); + + // Make sure all of the functions were installed correctly. + assertEquals(block.domToMutation(), 'domToMutationFn'); + assertEquals(block.mutationToDom(), 'mutationToDomFn'); + assertEquals(block.compose(), 'composeFn'); + assertEquals(block.decompose(), 'decomposeFn'); + }); + + test('With helper function', function() { + this.extensionsCleanup_.push('extensions_test'); + this.blockTypesCleanup_.push('mutator_test_block'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "mutator_test_block", + "message0": "mutator_test_block", + "mutator": ["extensions_test"] + }]); + + // Events code calls mutationToDom and expects it to give back a + // meaningful value. + Blockly.Events.disable(); + assertUndefined(Blockly.Extensions.ALL_['extensions_test']); + var helperFunctionSpy = sinon.spy(); + Blockly.Extensions.registerMutator('extensions_test', + { + domToMutation: function() { + return 'domToMutationFn'; + }, + mutationToDom: function() { + return 'mutationToDomFn'; + } + }, + helperFunctionSpy + ); + + var _ = new Blockly.Block(this.workspace, 'mutator_test_block'); + + sinon.assert.calledOnce(helperFunctionSpy); + }); + + test('No dialog', function() { + this.extensionsCleanup_.push('mutator_test'); + this.blockTypesCleanup_.push('mutator_test_block'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "mutator_test_block", + "message0": "mutator_test_block", + "mutator": "mutator_test" + }]); + + // Events code calls mutationToDom and expects it to give back a + // meaningful value. + Blockly.Events.disable(); + assertUndefined(Blockly.Extensions.ALL_['mutator_test']); + Blockly.Extensions.registerMutator('mutator_test', + { + domToMutation: function() { + return 'domToMutationFn'; + }, + mutationToDom: function() { + return 'mutationToDomFn'; + } + }); + + var block = new Blockly.Block(this.workspace, 'mutator_test_block'); + + // Make sure all of the functions were installed correctly. + assertEquals(block.domToMutation(), 'domToMutationFn'); + assertEquals(block.mutationToDom(), 'mutationToDomFn'); + assertFalse(block.hasOwnProperty('compose')); + assertFalse(block.hasOwnProperty('decompose')); + }); + }); + }); + + suite('Error cases', function() { + test('Missing extension', function() { + this.blockTypesCleanup_.push('missing_extension_block'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "missing_extension_block", + "message0": "missing_extension_block", + "extensions": ["missing_extension"] + }]); + + assertUndefined(Blockly.Extensions.ALL_['missing_extension']); + var workspace = this.workspace; + chai.assert.throws(function() { + var _ = new Blockly.Block(workspace, 'missing_extension_block'); + }); + }); + + test('Mixin overwrites local value', function() { + this.extensionsCleanup_.push('mixin_bad_inputList'); + this.blockTypesCleanup_.push('test_block_bad_inputList'); + + var TEST_MIXIN_BAD_INPUTLIST = { + inputList: 'bad inputList' // Defined in constructor + }; + + assertUndefined(Blockly.Extensions.ALL_['mixin_bad_inputList']); + // Extension defined before the block type is defined. + Blockly.Extensions.registerMixin('mixin_bad_inputList', TEST_MIXIN_BAD_INPUTLIST); + assert(typeof Blockly.Extensions.ALL_['mixin_bad_inputList'] == 'function'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "test_block_bad_inputList", + "message0": "test_block_bad_inputList", + "extensions": ["mixin_bad_inputList"] + }]); + + var workspace = this.workspace; + chai.assert.throws(function() { + var _ = new Blockly.Block(workspace, 'test_block_bad_inputList'); + }, /inputList/); + }); + + test('Mixin overwrites prototype', function() { + this.extensionsCleanup_.push('mixin_bad_colour_'); + this.blockTypesCleanup_.push('test_block_bad_colour'); + + var TEST_MIXIN_BAD_COLOUR = { + colour_: 'bad colour_' // Defined on prototype + }; + + assertUndefined(Blockly.Extensions.ALL_['mixin_bad_colour_']); + // Extension defined before the block type is defined. + Blockly.Extensions.registerMixin('mixin_bad_colour_', TEST_MIXIN_BAD_COLOUR); + assert(typeof Blockly.Extensions.ALL_['mixin_bad_colour_'] == 'function'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "test_block_bad_colour", + "message0": "test_block_bad_colour", + "extensions": ["mixin_bad_colour_"] + }]); + + var workspace = this.workspace; + chai.assert.throws(function() { + var _ = new Blockly.Block(workspace, 'test_block_bad_colour'); + }, /colour_/); + }); + + test('Use mutator as extension', function() { + this.extensionsCleanup_.push('mutator_test'); + this.blockTypesCleanup_.push('mutator_test_block'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "mutator_test_block", + "message0": "mutator_test_block", + "extensions": ["mutator_test"] + }]); + + // Events code calls mutationToDom and expects it to give back a + // meaningful value. + Blockly.Events.disable(); + assertUndefined(Blockly.Extensions.ALL_['mutator_test']); + Blockly.Extensions.registerMutator('mutator_test', + { + domToMutation: function() { + return 'domToMutationFn'; + }, + mutationToDom: function() { + return 'mutationToDomFn'; + } + }); + + var workspace = this.workspace; + chai.assert.throws(function() { + var _ = new Blockly.Block(workspace, 'mutator_test_block'); + }); + // Should have failed on apply, not on register. + assertNotNull(Blockly.Extensions.ALL_['mutator_test']); + }); + + test('Use mutator mixin as extension', function() { + this.extensionsCleanup_.push('mutator_test'); + this.blockTypesCleanup_.push('mutator_test_block'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "mutator_test_block", + "message0": "mutator_test_block", + "extensions": ["mutator_test"] + }]); + + // Events code calls mutationToDom and expects it to give back a + // meaningful value. + Blockly.Events.disable(); + assertUndefined(Blockly.Extensions.ALL_['mutator_test']); + Blockly.Extensions.registerMixin('mutator_test', + { + domToMutation: function() { + return 'domToMutationFn'; + }, + mutationToDom: function() { + return 'mutationToDomFn'; + } + }); + + var workspace = this.workspace; + chai.assert.throws(function() { + var _ = new Blockly.Block(workspace, 'mutator_test_block'); + }); + // Should have failed on apply, not on register. + assertNotNull(Blockly.Extensions.ALL_['mutator_test']); + }); + + test('Use extension as mutator', function() { + this.extensionsCleanup_.push('extensions_test'); + this.blockTypesCleanup_.push('mutator_test_block'); + + Blockly.defineBlocksWithJsonArray([{ + "type": "mutator_test_block", + "message0": "mutator_test_block", + "mutator": ["extensions_test"] + }]); + + // Events code calls mutationToDom and expects it to give back a + // meaningful value. + Blockly.Events.disable(); + assertUndefined(Blockly.Extensions.ALL_['extensions_test']); + Blockly.Extensions.register('extensions_test', function() { + return 'extensions_test_fn'; + }); + + var workspace = this.workspace; + chai.assert.throws(function() { + var _ = new Blockly.Block(workspace, 'mutator_test_block'); + }); + // Should have failed on apply, not on register. + assertNotNull(Blockly.Extensions.ALL_['extensions_test']); + }); + + suite('register', function() { + test('Just a string', function() { + this.extensionsCleanup_.push('extension_just_a_string'); + assertUndefined(Blockly.Extensions.ALL_['extension_just_a_string']); + chai.assert.throws(function() { + Blockly.Extensions.register('extension_just_a_string', null); + }); + }); + + test('Null', function() { + this.extensionsCleanup_.push('extension_is_null'); + assertUndefined(Blockly.Extensions.ALL_['extension_is_null']); + chai.assert.throws(function() { + Blockly.Extensions.register('extension_is_null', null); + }); + }); + + test('Undefined', function() { + this.extensionsCleanup_.push('extension_is_undefined'); + assertUndefined(Blockly.Extensions.ALL_['extension_is_undefined']); + chai.assert.throws(function() { + Blockly.Extensions.register('extension_is_undefined', null); + }); + }); + }); + + suite('registerMutator', function() { + test('No domToMutation', function() { + this.extensionsCleanup_.push('mutator_test'); + chai.assert.throws(function() { + Blockly.Extensions.registerMutator('mutator_test', + { + mutationToDom: function() { + return 'mutationToDomFn'; + }, + compose: function() { + return 'composeFn'; + }, + decompose: function() { + return 'decomposeFn'; + } + }); + }, /domToMutation/); + }); + + test('No mutationToDom', function() { + this.extensionsCleanup_.push('mutator_test'); + chai.assert.throws(function() { + Blockly.Extensions.registerMutator('mutator_test', + { + domToMutation: function() { + return 'domToMutationFn'; + }, + compose: function() { + return 'composeFn'; + }, + decompose: function() { + return 'decomposeFn'; + } + }); + }, /mutationToDom/); + }); + + test('Has decompose but no compose', function() { + this.extensionsCleanup_.push('mutator_test'); + chai.assert.throws(function() { + Blockly.Extensions.registerMutator('mutator_test', + { + domToMutation: function() { + return 'domToMutationFn'; + }, + mutationToDom: function() { + return 'mutationToDomFn'; + }, + decompose: function() { + return 'decomposeFn'; + } + }); + }, /compose/); + }); + + test('Has compose but no decompose', function() { + this.extensionsCleanup_.push('mutator_test'); + chai.assert.throws(function() { + Blockly.Extensions.registerMutator('mutator_test', + { + domToMutation: function() { + return 'domToMutationFn'; + }, + mutationToDom: function() { + return 'mutationToDomFn'; + }, + compose: function() { + return 'composeFn'; + } + }); + }, /decompose/); + }); + }); + }); +}); diff --git a/tests/mocha/index.html b/tests/mocha/index.html index ee645b79e..c156f3f28 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -33,6 +33,7 @@ + diff --git a/tests/mocha/xml_test.js b/tests/mocha/xml_test.js index 05635de73..bcf826a23 100644 --- a/tests/mocha/xml_test.js +++ b/tests/mocha/xml_test.js @@ -76,6 +76,9 @@ suite('XML', function() { delete Blockly.Blocks[this.blockTypes_[i]]; } this.blockTypes_.length = 0; + // Clear Blockly.Event state. + Blockly.Events.setGroup(false); + Blockly.Events.disabled_ = 0; sinon.restore(); }); suite('textToDom', function() { From 12c8a50a0f677e759bcf5fa7b271698891b72fba Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 15 Apr 2020 17:51:57 -0700 Subject: [PATCH 022/139] Update the options object to reflect its properties, update the public option interface to include keymap and other little things (#3826) --- core/options.js | 24 +++++++++++++++++++ typings/templates/blockly-interfaces.template | 6 +++++ 2 files changed, 30 insertions(+) diff --git a/core/options.js b/core/options.js index fd97f8d94..84fce92dc 100644 --- a/core/options.js +++ b/core/options.js @@ -106,31 +106,55 @@ Blockly.Options = function(options) { var renderer = options['renderer'] || 'geras'; + /** @type {boolean} */ this.RTL = rtl; + /** @type {boolean} */ this.oneBasedIndex = oneBasedIndex; + /** @type {boolean} */ this.collapse = hasCollapse; + /** @type {boolean} */ this.comments = hasComments; + /** @type {boolean} */ this.disable = hasDisable; + /** @type {boolean} */ this.readOnly = readOnly; + /** @type {number} */ this.maxBlocks = options['maxBlocks'] || Infinity; + /** @type {?Object.} */ this.maxInstances = options['maxInstances']; + /** @type {string} */ this.pathToMedia = pathToMedia; + /** @type {boolean} */ this.hasCategories = hasCategories; + /** @type {!Object} */ this.moveOptions = Blockly.Options.parseMoveOptions(options, hasCategories); /** @deprecated January 2019 */ this.hasScrollbars = this.moveOptions.scrollbars; + /** @type {boolean} */ this.hasTrashcan = hasTrashcan; + /** @type {number} */ this.maxTrashcanContents = maxTrashcanContents; + /** @type {boolean} */ this.hasSounds = hasSounds; + /** @type {boolean} */ this.hasCss = hasCss; + /** @type {boolean} */ this.horizontalLayout = horizontalLayout; + /** @type {Node} */ this.languageTree = languageTree; + /** @type {!Object} */ this.gridOptions = Blockly.Options.parseGridOptions_(options); + /** @type {!Object} */ this.zoomOptions = Blockly.Options.parseZoomOptions_(options); + /** @type {number} */ this.toolboxPosition = toolboxPosition; + /** @type {!Blockly.Theme} */ this.theme = Blockly.Options.parseThemeOptions_(options); + /** @type {!Object} */ this.keyMap = keyMap; + /** @type {string} */ this.renderer = renderer; + /** @type {?Object} */ this.rendererOverrides = options['rendererOverrides']; /** diff --git a/typings/templates/blockly-interfaces.template b/typings/templates/blockly-interfaces.template index 31fa80fbb..4afd7fe2c 100644 --- a/typings/templates/blockly-interfaces.template +++ b/typings/templates/blockly-interfaces.template @@ -5,6 +5,7 @@ declare module Blockly { toolbox?: HTMLElement | string; readOnly?: boolean; trashcan?: boolean; + maxInstances?: {[type: string]: number;}; maxTrashcanContents?: number; collapse?: boolean; comments?: boolean; @@ -35,14 +36,19 @@ declare module Blockly { maxScale?: number; minScale?: number; scaleSpeed?: number; + pinch?: boolean; }; renderer?: string; + keyMap?: {[type: string]: Blockly.Action;}; } interface BlocklyThemeOptions { + base?: string; blockStyles?: {[blocks: string]: Blockly.Theme.BlockStyle;}; categoryStyles?: {[category: string]: Blockly.Theme.CategoryStyle;}; componentStyles?: {[component: string]: any;}; + fontStyle?: Blockly.Theme.FontStyle; + startHats?: boolean; } interface Metrics { From 0230a4c192e9e9a0cd9399337cb170234997a21d Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 15 Apr 2020 19:46:11 -0700 Subject: [PATCH 023/139] Update IPathObject to include properties (#3822) * Update IPathObject to include properties * Fix ipathobject svgpath --- core/renderers/common/i_path_object.js | 32 ++++++++++++++++++++++++++ core/renderers/common/path_object.js | 2 +- core/renderers/geras/path_object.js | 2 +- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/core/renderers/common/i_path_object.js b/core/renderers/common/i_path_object.js index 82a58f513..8b18426cf 100644 --- a/core/renderers/common/i_path_object.js +++ b/core/renderers/common/i_path_object.js @@ -27,6 +27,38 @@ goog.requireType('Blockly.Theme'); */ Blockly.blockRendering.IPathObject = function(_root, _constants) {}; +/** + * The primary path of the block. + * @type {!SVGElement} + */ +Blockly.blockRendering.IPathObject.prototype.svgPath; + +/** + * The renderer's constant provider. + * @type {!Blockly.blockRendering.ConstantProvider} + */ +Blockly.blockRendering.IPathObject.prototype.constants; + +/** + * The primary path of the block. + * @type {!Blockly.Theme.BlockStyle} + */ +Blockly.blockRendering.IPathObject.prototype.style; + +/** + * Holds the cursors svg element when the cursor is attached to the block. + * This is null if there is no cursor on the block. + * @type {SVGElement} + */ +Blockly.blockRendering.IPathObject.prototype.cursorSvg; + +/** + * Holds the markers svg element when the marker is attached to the block. + * This is null if there is no marker on the block. + * @type {SVGElement} + */ +Blockly.blockRendering.IPathObject.prototype.markerSvg; + /** * Set the path generated by the renderer onto the respective SVG element. * @param {string} pathString The path. diff --git a/core/renderers/common/path_object.js b/core/renderers/common/path_object.js index 73d1cc732..602f27448 100644 --- a/core/renderers/common/path_object.js +++ b/core/renderers/common/path_object.js @@ -43,7 +43,7 @@ Blockly.blockRendering.PathObject = function(root, style, constants) { /** * The primary path of the block. - * @type {SVGElement} + * @type {!SVGElement} * @package */ this.svgPath = Blockly.utils.dom.createSvgElement('path', diff --git a/core/renderers/geras/path_object.js b/core/renderers/geras/path_object.js index 76884c9bc..eed4775fe 100644 --- a/core/renderers/geras/path_object.js +++ b/core/renderers/geras/path_object.js @@ -54,7 +54,7 @@ Blockly.geras.PathObject = function(root, style, constants) { /** * The primary path of the block. - * @type {SVGElement} + * @type {!SVGElement} * @package */ this.svgPath = Blockly.utils.dom.createSvgElement('path', From 9e98df9949292ee114ab159289bc5cf58a4b7b45 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Thu, 16 Apr 2020 13:02:05 -0700 Subject: [PATCH 024/139] Fix collapsed blocks not updating when modified (#3806) * Stop recursive render calls * Fix visibility bugs. * Make toString ignore collapsed input. * Add automatic collapse rendering handling * Fix insertion markers with collapsed * Add tests * Fix build? * PR comments * Add missing jsdoc --- core/block.js | 38 +- core/block_svg.js | 144 ++++---- core/input.js | 10 +- core/insertion_marker_manager.js | 26 +- core/rendered_connection.js | 17 +- tests/mocha/block_test.js | 427 ++++++++++++++++++++++ tests/mocha/run_mocha_tests_in_browser.js | 2 +- 7 files changed, 560 insertions(+), 104 deletions(-) diff --git a/core/block.js b/core/block.js index 724e76777..6ea9dcc42 100644 --- a/core/block.js +++ b/core/block.js @@ -229,6 +229,17 @@ Blockly.Block = function(workspace, prototypeName, opt_id) { */ Blockly.Block.CommentModel; +/** + * The language-neutral id given to the collapsed input. + * @const {string} + */ +Blockly.Block.COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT'; +/** + * The language-neutral id given to the collapsed field. + * @const {string} + */ +Blockly.Block.COLLAPSED_FIELD_NAME = '_TEMP_COLLAPSED_FIELD'; + /** * Optional text data that round-trips between blocks and XML. * Has no effect. May be used by 3rd parties for meta information. @@ -1295,20 +1306,19 @@ Blockly.Block.prototype.setCollapsed = function(collapsed) { Blockly.Block.prototype.toString = function(opt_maxLength, opt_emptyToken) { var text = []; var emptyFieldPlaceholder = opt_emptyToken || '?'; - if (this.collapsed_) { - text.push(this.getInput('_TEMP_COLLAPSED_INPUT').fieldRow[0].getText()); - } else { - for (var i = 0, input; (input = this.inputList[i]); i++) { - for (var j = 0, field; (field = input.fieldRow[j]); j++) { - text.push(field.getText()); - } - if (input.connection) { - var child = input.connection.targetBlock(); - if (child) { - text.push(child.toString(undefined, opt_emptyToken)); - } else { - text.push(emptyFieldPlaceholder); - } + for (var i = 0, input; (input = this.inputList[i]); i++) { + if (input.name == Blockly.Block.COLLAPSED_INPUT_NAME) { + continue; + } + for (var j = 0, field; (field = input.fieldRow[j]); j++) { + text.push(field.getText()); + } + if (input.connection) { + var child = input.connection.targetBlock(); + if (child) { + text.push(child.toString(undefined, opt_emptyToken)); + } else { + text.push(emptyFieldPlaceholder); } } } diff --git a/core/block_svg.js b/core/block_svg.js index bebf725b3..5938e597e 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -69,6 +69,14 @@ Blockly.BlockSvg = function(workspace, prototypeName, opt_id) { /** @type {boolean} */ this.rendered = false; + /** + * Is this block currently rendering? Used to stop recursive render calls + * from actually triggering a re-render. + * @type {boolean} + * @private + */ + this.renderIsInProgress_ = false; + /** @type {!Blockly.WorkspaceSvg} */ this.workspace = workspace; @@ -602,60 +610,51 @@ Blockly.BlockSvg.prototype.setCollapsed = function(collapsed) { if (this.collapsed_ == collapsed) { return; } - var renderList = []; - // Show/hide the inputs. - for (var i = 0, input; (input = this.inputList[i]); i++) { - renderList.push.apply(renderList, input.setVisible(!collapsed)); - } - - var COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT'; - if (collapsed) { - var icons = this.getIcons(); - for (var i = 0; i < icons.length; i++) { - icons[i].setVisible(false); - } - var text = this.toString(Blockly.COLLAPSE_CHARS); - this.appendDummyInput(COLLAPSED_INPUT_NAME).appendField(text).init(); - - // Add any warnings on enclosed blocks to this block. - var descendants = this.getDescendants(true); - var nextBlock = this.getNextBlock(); - if (nextBlock) { - var index = descendants.indexOf(nextBlock); - descendants.splice(index, descendants.length - index); - } - for (var i = 1, block; (block = descendants[i]); i++) { - if (block.warning) { - this.setWarningText(Blockly.Msg['COLLAPSED_WARNINGS_WARNING'], - Blockly.BlockSvg.COLLAPSED_WARNING_ID); - break; - } - } - } else { - this.removeInput(COLLAPSED_INPUT_NAME); - // Clear any warnings inherited from enclosed blocks. - if (this.warning) { - this.warning.setText('', Blockly.BlockSvg.COLLAPSED_WARNING_ID); - if (!Object.keys(this.warning.text_).length) { - this.setWarningText(null); - } - } - } Blockly.BlockSvg.superClass_.setCollapsed.call(this, collapsed); + if (!collapsed) { + this.updateCollapsed_(); + } else if (this.rendered) { + this.render(); + // Don't bump neighbours. Users like to store collapsed functions together + // and bumping makes them go out of alignment. + } +}; - if (!renderList.length) { - // No child blocks, just render this block. - renderList[0] = this; - } - if (this.rendered) { - for (var i = 0, block; (block = renderList[i]); i++) { - block.render(); +/** + * Makes sure that when the block is collapsed, it is rendered correctly + * for that state. + * @private + */ +Blockly.BlockSvg.prototype.updateCollapsed_ = function() { + var collapsed = this.isCollapsed(); + var collapsedInputName = Blockly.Block.COLLAPSED_INPUT_NAME; + var collapsedFieldName = Blockly.Block.COLLAPSED_FIELD_NAME; + + for (var i = 0, input; (input = this.inputList[i]); i++) { + if (input.name != collapsedInputName) { + input.setVisible(!collapsed); } - // Don't bump neighbours. - // Although bumping neighbours would make sense, users often collapse - // all their functions and store them next to each other. Expanding and - // bumping causes all their definitions to go out of alignment. } + + if (!collapsed) { + this.removeInput(collapsedInputName); + return; + } + + var icons = this.getIcons(); + for (var i = 0, icon; (icon = icons[i]); i++) { + icon.setVisible(false); + } + + var text = this.toString(Blockly.COLLAPSE_CHARS); + var field = this.getField(collapsedFieldName); + if (field) { + field.setValue(text); + return; + } + var input = this.getInput(collapsedInputName) || + this.appendDummyInput(collapsedInputName); + input.appendField(new Blockly.FieldLabel(text), collapsedFieldName); }; /** @@ -1647,31 +1646,40 @@ Blockly.BlockSvg.prototype.getRootBlock = function() { }; /** - * Render the block. * Lays out and reflows a block based on its contents and settings. * @param {boolean=} opt_bubble If false, just render this block. * If true, also render block's parent, grandparent, etc. Defaults to true. */ Blockly.BlockSvg.prototype.render = function(opt_bubble) { - Blockly.utils.dom.startTextWidthCache(); - this.rendered = true; - (/** @type {!Blockly.WorkspaceSvg} */ (this.workspace)) - .getRenderer().render(this); - // No matter how we rendered, connection locations should now be correct. - this.updateConnectionLocations_(); - if (opt_bubble !== false) { - // Render all blocks above this one (propagate a reflow). - var parentBlock = this.getParent(); - if (parentBlock) { - parentBlock.render(true); - } else { - // Top-most block. Fire an event to allow scrollbars to resize. - this.workspace.resizeContents(); - } + if (this.renderIsInProgress_) { + return; // Don't allow recursive renders. } - Blockly.utils.dom.stopTextWidthCache(); + this.renderIsInProgress_ = true; + try { + this.rendered = true; + Blockly.utils.dom.startTextWidthCache(); - this.updateMarkers_(); + if (this.isCollapsed()) { + this.updateCollapsed_(); + } + this.workspace.getRenderer().render(this); + this.updateConnectionLocations_(); + + if (opt_bubble !== false) { + var parentBlock = this.getParent(); + if (parentBlock) { + parentBlock.render(true); + } else { + // Top-most block. Fire an event to allow scrollbars to resize. + this.workspace.resizeContents(); + } + } + + Blockly.utils.dom.stopTextWidthCache(); + this.updateMarkers_(); + } finally { + this.renderIsInProgress_ = false; + } }; /** diff --git a/core/input.js b/core/input.js index 8e6bfb7b4..aeb60a9de 100644 --- a/core/input.js +++ b/core/input.js @@ -91,21 +91,23 @@ Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) { if (index < 0 || index > this.fieldRow.length) { throw Error('index ' + index + ' out of bounds.'); } - // Falsy field values don't generate a field, unless the field is an empty // string and named. if (!field && !(field == '' && opt_name)) { return index; } + // Generate a FieldLabel when given a plain text field. if (typeof field == 'string') { field = new Blockly.FieldLabel(/** @type {string} */ (field)); } + field.setSourceBlock(this.sourceBlock_); if (this.sourceBlock_.rendered) { field.init(); } field.name = opt_name; + field.setVisible(this.isVisible()); if (field.prefixField) { // Add any prefix. @@ -173,7 +175,6 @@ Blockly.Input.prototype.setVisible = function(visible) { } this.visible_ = visible; - var display = visible ? 'block' : 'none'; for (var y = 0, field; (field = this.fieldRow[y]); y++) { field.setVisible(visible); } @@ -186,10 +187,7 @@ Blockly.Input.prototype.setVisible = function(visible) { } var child = this.connection.targetBlock(); if (child) { - child.getSvgRoot().style.display = display; - if (!visible) { - child.rendered = false; - } + child.getSvgRoot().style.display = visible ? 'block' : 'none'; } } return renderList; diff --git a/core/insertion_marker_manager.js b/core/insertion_marker_manager.js index 49f264e72..bb85cc960 100644 --- a/core/insertion_marker_manager.js +++ b/core/insertion_marker_manager.js @@ -253,23 +253,25 @@ Blockly.InsertionMarkerManager.prototype.createMarkerBlock_ = function(sourceBlo result.domToMutation(oldMutationDom); } } - result.setCollapsed(sourceBlock.isCollapsed()); - result.setInputsInline(sourceBlock.getInputsInline()); - // Copy visible field values from the other block. These values may impact - // the rendered size of the insertion marker. Note that we do not care - // about child blocks here. + // Copy field values from the other block. These values may impact the + // rendered size of the insertion marker. Note that we do not care about + // child blocks here. for (var i = 0; i < sourceBlock.inputList.length; i++) { var sourceInput = sourceBlock.inputList[i]; - if (sourceInput.isVisible()) { - var resultInput = result.inputList[i]; - for (var j = 0; j < sourceInput.fieldRow.length; j++) { - var sourceField = sourceInput.fieldRow[j]; - var resultField = resultInput.fieldRow[j]; - resultField.setValue(sourceField.getValue()); - } + if (sourceInput.name == Blockly.Block.COLLAPSED_INPUT_NAME) { + continue; // Ignore the collapsed input. + } + var resultInput = result.inputList[i]; + for (var j = 0; j < sourceInput.fieldRow.length; j++) { + var sourceField = sourceInput.fieldRow[j]; + var resultField = resultInput.fieldRow[j]; + resultField.setValue(sourceField.getValue()); } } + result.setCollapsed(sourceBlock.isCollapsed()); + result.setInputsInline(sourceBlock.getInputsInline()); + result.initSvg(); result.getSvgRoot().setAttribute('visibility', 'hidden'); } finally { diff --git a/core/rendered_connection.js b/core/rendered_connection.js index d6eab4827..fa6c45643 100644 --- a/core/rendered_connection.js +++ b/core/rendered_connection.js @@ -454,6 +454,8 @@ Blockly.RenderedConnection.prototype.disconnectInternal_ = function(parentBlock, if (childBlock.rendered) { childBlock.updateDisabled(); childBlock.render(); + // Reset visibility, since the child is now a top block. + childBlock.getSvgRoot().style.display = 'block'; } }; @@ -504,14 +506,16 @@ Blockly.RenderedConnection.prototype.connect_ = function(childConnection) { var parentConnection = this; var parentBlock = parentConnection.getSourceBlock(); var childBlock = childConnection.getSourceBlock(); + var parentRendered = parentBlock.rendered; + var childRendered = childBlock.rendered; - if (parentBlock.rendered) { + if (parentRendered) { parentBlock.updateDisabled(); } - if (childBlock.rendered) { + if (childRendered) { childBlock.updateDisabled(); } - if (parentBlock.rendered && childBlock.rendered) { + if (parentRendered && childRendered) { if (parentConnection.type == Blockly.NEXT_STATEMENT || parentConnection.type == Blockly.PREVIOUS_STATEMENT) { // Child block may need to square off its corners if it is in a stack. @@ -523,6 +527,13 @@ Blockly.RenderedConnection.prototype.connect_ = function(childConnection) { parentBlock.render(); } } + + // The input the child block is connected to (if any). + var parentInput = parentBlock.getInputWithBlock(childBlock); + if (parentInput) { + var visible = parentInput.isVisible(); + childBlock.getSvgRoot().style.display = visible ? 'block' : 'none'; + } }; /** diff --git a/tests/mocha/block_test.js b/tests/mocha/block_test.js index dcdea6a61..f29b767db 100644 --- a/tests/mocha/block_test.js +++ b/tests/mocha/block_test.js @@ -1209,7 +1209,434 @@ suite('Blocks', function() { }); }); }); + suite('Collapsing and Expanding', function() { + function assertCollapsed(block, opt_string) { + chai.assert.isTrue(block.isCollapsed()); + for (var i = 0, input; (input = block.inputList[i]); i++) { + if (input.name == Blockly.Block.COLLAPSED_INPUT_NAME) { + continue; + } + chai.assert.isFalse(input.isVisible()); + for (var j = 0, field; (field = input.fieldRow[j]); j++) { + chai.assert.isFalse(field.isVisible()); + } + } + var icons = block.getIcons(); + for (var i = 0, icon; (icon = icons[i]); i++) { + chai.assert.isFalse(icon.isVisible()); + } + var input = block.getInput(Blockly.Block.COLLAPSED_INPUT_NAME); + chai.assert.isNotNull(input); + chai.assert.isTrue(input.isVisible()); + var field = block.getField(Blockly.Block.COLLAPSED_FIELD_NAME); + chai.assert.isNotNull(field); + chai.assert.isTrue(field.isVisible()); + + if (opt_string) { + chai.assert.equal(field.getText(), opt_string); + } + } + function assertNotCollapsed(block) { + chai.assert.isFalse(block.isCollapsed()); + for (var i = 0, input; (input = block.inputList[i]); i++) { + chai.assert.isTrue(input.isVisible()); + for (var j = 0, field; (field = input.fieldRow[j]); j++) { + chai.assert.isTrue(field.isVisible()); + } + } + + var input = block.getInput(Blockly.Block.COLLAPSED_INPUT_NAME); + chai.assert.isNull(input); + var field = block.getField(Blockly.Block.COLLAPSED_FIELD_NAME); + chai.assert.isNull(field); + } + function isBlockHidden(block) { + var node = block.getSvgRoot(); + do { + var visible = node.style.display != 'none'; + if (!visible) { + return true; + } + node = node.parentNode; + } while (node != document); + return false; + } + + setup(function() { + Blockly.Events.disable(); + // We need a visible workspace. + this.workspace = Blockly.inject('blocklyDiv', {}); + Blockly.defineBlocksWithJsonArray([ + { + "type": "variable_block", + "message0": "%1", + "args0": [ + { + "type": "field_variable", + "name": "NAME", + "variable": "x" + } + ], + } + ]); + this.createBlock = function(type) { + var block = this.workspace.newBlock(type); + block.initSvg(); + block.render(); + return block; + }; + }); + teardown(function() { + Blockly.Events.enable(); + delete Blockly.Blocks['variable_block']; + }); + suite('Connecting and Disconnecting', function() { + test('Connect Block to Next', function() { + var blockA = this.createBlock('stack_block'); + var blockB = this.createBlock('stack_block'); + + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.nextConnection.connect(blockB.previousConnection); + assertNotCollapsed(blockB); + }); + test('Connect Block to Value Input', function() { + var blockA = this.createBlock('row_block'); + var blockB = this.createBlock('row_block'); + + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.getInput('INPUT').connection.connect(blockB.outputConnection); + chai.assert.isTrue(isBlockHidden(blockB)); + blockA.setCollapsed(false); + assertNotCollapsed(blockA); + chai.assert.isFalse(isBlockHidden(blockB)); + }); + test('Connect Block to Statement Input', function() { + var blockA = this.createBlock('statement_block'); + var blockB = this.createBlock('stack_block'); + + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.getInput('STATEMENT').connection + .connect(blockB.previousConnection); + chai.assert.isTrue(isBlockHidden(blockB)); + blockA.setCollapsed(false); + assertNotCollapsed(blockA); + chai.assert.isFalse(isBlockHidden(blockB)); + }); + test('Connect Block to Child of Collapsed - Input', function() { + var blockA = this.createBlock('row_block'); + var blockB = this.createBlock('row_block'); + var blockC = this.createBlock('row_block'); + + blockA.getInput('INPUT').connection.connect(blockB.outputConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + blockB.getInput('INPUT').connection.connect(blockC.outputConnection); + chai.assert.isTrue(isBlockHidden(blockC)); + + blockA.setCollapsed(false); + assertNotCollapsed(blockA); + chai.assert.isFalse(isBlockHidden(blockB)); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Connect Block to Child of Collapsed - Next', function() { + var blockA = this.createBlock('statement_block'); + var blockB = this.createBlock('stack_block'); + var blockC = this.createBlock('stack_block'); + + blockA.getInput('STATEMENT').connection + .connect(blockB.previousConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + blockB.nextConnection.connect(blockC.previousConnection); + chai.assert.isTrue(isBlockHidden(blockC)); + + blockA.setCollapsed(false); + assertNotCollapsed(blockA); + chai.assert.isFalse(isBlockHidden(blockB)); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Connect Block to Value Input Already Taken', function() { + var blockA = this.createBlock('row_block'); + var blockB = this.createBlock('row_block'); + var blockC = this.createBlock('row_block'); + + blockA.getInput('INPUT').connection.connect(blockB.outputConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + blockA.getInput('INPUT').connection.connect(blockC.outputConnection); + chai.assert.isTrue(isBlockHidden(blockC)); + // Still hidden after C is inserted between. + chai.assert.isTrue(isBlockHidden(blockB)); + + blockA.setCollapsed(false); + assertNotCollapsed(blockA); + chai.assert.isFalse(isBlockHidden(blockB)); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Connect Block to Statement Input Already Taken', function() { + var blockA = this.createBlock('statement_block'); + var blockB = this.createBlock('stack_block'); + var blockC = this.createBlock('stack_block'); + + blockA.getInput('STATEMENT').connection + .connect(blockB.previousConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + blockA.getInput('STATEMENT').connection + .connect(blockC.previousConnection); + chai.assert.isTrue(isBlockHidden(blockC)); + // Still hidden after C is inserted between. + chai.assert.isTrue(isBlockHidden(blockB)); + + blockA.setCollapsed(false); + assertNotCollapsed(blockA); + chai.assert.isFalse(isBlockHidden(blockB)); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Connect Block with Child - Input', function() { + var blockA = this.createBlock('row_block'); + var blockB = this.createBlock('row_block'); + var blockC = this.createBlock('row_block'); + + blockB.getInput('INPUT').connection.connect(blockC.outputConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.getInput('INPUT').connection.connect(blockB.outputConnection); + chai.assert.isTrue(isBlockHidden(blockC)); + chai.assert.isTrue(isBlockHidden(blockB)); + + blockA.setCollapsed(false); + assertNotCollapsed(blockA); + chai.assert.isFalse(isBlockHidden(blockB)); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Connect Block with Child - Statement', function() { + var blockA = this.createBlock('statement_block'); + var blockB = this.createBlock('stack_block'); + var blockC = this.createBlock('stack_block'); + + blockB.nextConnection.connect(blockC.previousConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.getInput('STATEMENT').connection + .connect(blockB.previousConnection); + chai.assert.isTrue(isBlockHidden(blockC)); + chai.assert.isTrue(isBlockHidden(blockB)); + + blockA.setCollapsed(false); + assertNotCollapsed(blockA); + chai.assert.isFalse(isBlockHidden(blockB)); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Disconnect Block from Value Input', function() { + var blockA = this.createBlock('row_block'); + var blockB = this.createBlock('row_block'); + + blockA.getInput('INPUT').connection.connect(blockB.outputConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + blockB.outputConnection.disconnect(); + chai.assert.isFalse(isBlockHidden(blockB)); + }); + test('Disconnect Block from Statement Input', function() { + var blockA = this.createBlock('statement_block'); + var blockB = this.createBlock('stack_block'); + + blockA.getInput('STATEMENT').connection + .connect(blockB.previousConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + blockB.previousConnection.disconnect(); + chai.assert.isFalse(isBlockHidden(blockB)); + }); + test('Disconnect Block from Child of Collapsed - Input', function() { + var blockA = this.createBlock('row_block'); + var blockB = this.createBlock('row_block'); + var blockC = this.createBlock('row_block'); + + blockA.getInput('INPUT').connection.connect(blockB.outputConnection); + blockB.getInput('INPUT').connection.connect(blockC.outputConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + chai.assert.isTrue(isBlockHidden(blockC)); + + blockC.outputConnection.disconnect(); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Disconnect Block from Child of Collapsed - Next', function() { + var blockA = this.createBlock('statement_block'); + var blockB = this.createBlock('stack_block'); + var blockC = this.createBlock('stack_block'); + + blockA.getInput('STATEMENT').connection + .connect(blockB.previousConnection); + blockB.nextConnection.connect(blockC.previousConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + chai.assert.isTrue(isBlockHidden(blockC)); + + blockC.previousConnection.disconnect(); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Disconnect Block with Child - Input', function() { + var blockA = this.createBlock('row_block'); + var blockB = this.createBlock('row_block'); + var blockC = this.createBlock('row_block'); + + blockB.getInput('INPUT').connection.connect(blockC.outputConnection); + blockA.getInput('INPUT').connection.connect(blockB.outputConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockB)); + chai.assert.isTrue(isBlockHidden(blockC)); + + blockB.outputConnection.disconnect(); + chai.assert.isFalse(isBlockHidden(blockB)); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + test('Disconnect Block with Child - Statement', function() { + var blockA = this.createBlock('statement_block'); + var blockB = this.createBlock('stack_block'); + var blockC = this.createBlock('stack_block'); + + blockB.nextConnection.connect(blockC.previousConnection); + blockA.getInput('STATEMENT').connection + .connect(blockB.previousConnection); + blockA.setCollapsed(true); + assertCollapsed(blockA); + chai.assert.isTrue(isBlockHidden(blockC)); + chai.assert.isTrue(isBlockHidden(blockB)); + + blockB.previousConnection.disconnect(); + chai.assert.isFalse(isBlockHidden(blockB)); + chai.assert.isFalse(isBlockHidden(blockC)); + }); + }); + suite('Adding and Removing Block Parts', function() { + test('Add Previous Connection', function() { + var blockA = this.createBlock('empty_block'); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.setPreviousStatement(true); + assertCollapsed(blockA); + chai.assert.isNotNull(blockA.previousConnection); + }); + test('Add Next Connection', function() { + var blockA = this.createBlock('empty_block'); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.setNextStatement(true); + assertCollapsed(blockA); + chai.assert.isNotNull(blockA.nextConnection); + }); + test('Add Input', function() { + var blockA = this.createBlock('empty_block'); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.appendDummyInput('NAME'); + assertCollapsed(blockA); + chai.assert.isNotNull(blockA.getInput('NAME')); + }); + test('Add Field', function() { + var blockA = this.createBlock('empty_block'); + var input = blockA.appendDummyInput('NAME'); + blockA.setCollapsed(true); + assertCollapsed(blockA); + input.appendField(new Blockly.FieldLabel('test'), 'FIELD'); + assertCollapsed(blockA); + var field = blockA.getField('FIELD'); + chai.assert.isNotNull(field); + chai.assert.equal('test', field.getText()); + }); + test('Add Icon', function() { + var blockA = this.createBlock('empty_block'); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.setCommentText('test'); + assertCollapsed(blockA); + }); + test('Remove Previous Connection', function() { + var blockA = this.createBlock('empty_block'); + blockA.setPreviousStatement(true); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.setPreviousStatement(false); + assertCollapsed(blockA); + chai.assert.isNull(blockA.previousConnection); + }); + test('Remove Next Connection', function() { + var blockA = this.createBlock('empty_block'); + blockA.setNextStatement(true); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.setNextStatement(false); + assertCollapsed(blockA); + chai.assert.isNull(blockA.nextConnection); + }); + test('Remove Input', function() { + var blockA = this.createBlock('empty_block'); + blockA.appendDummyInput('NAME'); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.removeInput('NAME'); + assertCollapsed(blockA); + chai.assert.isNull(blockA.getInput('NAME')); + }); + test('Remove Field', function() { + var blockA = this.createBlock('empty_block'); + var input = blockA.appendDummyInput('NAME'); + input.appendField(new Blockly.FieldLabel('test'), 'FIELD'); + blockA.setCollapsed(true); + assertCollapsed(blockA); + input.removeField('FIELD'); + assertCollapsed(blockA); + var field = blockA.getField('FIELD'); + chai.assert.isNull(field); + }); + test('Remove Icon', function() { + var blockA = this.createBlock('empty_block'); + blockA.setCommentText('test'); + blockA.setCollapsed(true); + assertCollapsed(blockA); + blockA.setCommentText(null); + assertCollapsed(blockA); + }); + }); + suite('Renaming Vars', function() { + test('Simple Rename', function() { + var blockA = this.createBlock('variable_block'); + + blockA.setCollapsed(true); + assertCollapsed(blockA, 'x'); + + var variable = this.workspace.getVariable('x', ''); + this.workspace.renameVariableById(variable.getId(), 'y'); + assertCollapsed(blockA, 'y'); + }); + test('Coalesce, Different Case', function() { + var blockA = this.createBlock('variable_block'); + + blockA.setCollapsed(true); + assertCollapsed(blockA, 'x'); + + var variable = this.workspace.createVariable('y'); + this.workspace.renameVariableById(variable.getId(), 'X'); + assertCollapsed(blockA, 'X'); + }); + }); + }); suite('Style', function() { suite('Headless', function() { setup(function() { diff --git a/tests/mocha/run_mocha_tests_in_browser.js b/tests/mocha/run_mocha_tests_in_browser.js index ed0c82943..768e8a7d7 100644 --- a/tests/mocha/run_mocha_tests_in_browser.js +++ b/tests/mocha/run_mocha_tests_in_browser.js @@ -40,7 +40,7 @@ async function runMochaTestsInBrowser() { var elem = await browser.$('#failureCount'); var text = await elem.getAttribute('tests_failed'); return text != 'unset'; - }, 7000); + }, 9000); const elem = await browser.$('#failureCount'); const numOfFailure = await elem.getAttribute('tests_failed'); From 9c400f2bf021f5d56af9cc0c81e15051c6e58f2c Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Thu, 16 Apr 2020 14:18:12 -0700 Subject: [PATCH 025/139] Converting variable tests to mocha. (#3828) --- tests/jsunit/index.html | 1 - tests/jsunit/variables_test.js | 136 ------------------------------- tests/mocha/index.html | 1 + tests/mocha/variables_test.js | 142 +++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 137 deletions(-) delete mode 100644 tests/jsunit/variables_test.js create mode 100644 tests/mocha/variables_test.js diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index f7634f8cd..15a0b5156 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -19,7 +19,6 @@ - diff --git a/tests/jsunit/variables_test.js b/tests/jsunit/variables_test.js deleted file mode 100644 index 7041f3174..000000000 --- a/tests/jsunit/variables_test.js +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Tests for variable utility functions in Blockly - * @author fenichel@google.com (Rachel Fenichel) - */ -'use strict'; - -function variablesTest_setUp() { - defineGetVarBlock(); - var workspace = new Blockly.Workspace(); - workspace.createVariable('foo', 'type1', '1'); - workspace.createVariable('bar', 'type1', '2'); - workspace.createVariable('baz', 'type1', '3'); - return workspace; -} - -function variablesTest_tearDown(workspace) { - undefineGetVarBlock(); - workspace.dispose(); -} - -function buildVariablesTest(testImpl) { - return function() { - var workspace = variablesTest_setUp(); - try { - testImpl(workspace); - } finally { - variablesTest_tearDown(workspace); - } - }; -} - -var test_allUsedVarModels = buildVariablesTest( - function(workspace) { - createMockVarBlock(workspace, '1'); - createMockVarBlock(workspace, '2'); - createMockVarBlock(workspace, '3'); - - var result = Blockly.Variables.allUsedVarModels(workspace); - assertEquals('Expected three variables in the list of used variables', - 3, result.length); - } -); - -var test_allUsedVarModels_someUnused = buildVariablesTest( - function(workspace) { - createMockVarBlock(workspace, '2'); - - var result = Blockly.Variables.allUsedVarModels(workspace); - assertEquals('Expected one variable in the list of used variables', - 1, result.length); - assertEquals('Expected variable with ID 2 in the list of used variables', - '2', result[0].getId()); - } -); - -var test_allUsedVarModels_varUsedTwice = buildVariablesTest( - function(workspace) { - createMockVarBlock(workspace, '2'); - createMockVarBlock(workspace, '2'); - - var result = Blockly.Variables.allUsedVarModels(workspace); - // Using the same variable multiple times should not change the number of - // elements in the list. - assertEquals('Expected one variable in the list of used variables', - 1, result.length); - assertEquals('Expected variable with ID 2 in the list of used variables', - '2', result[0].getId()); - } -); - -var test_allUsedVarModels_allUnused = buildVariablesTest( - function(workspace) { - var result = Blockly.Variables.allUsedVarModels(workspace); - assertEquals('Expected no variables in the list of used variables', - 0, result.length); - } -); - -var test_getVariable_byId = buildVariablesTest( - function(workspace) { - var var_1 = workspace.createVariable('name1', 'type1', 'id1'); - var var_2 = workspace.createVariable('name2', 'type1', 'id2'); - var var_3 = workspace.createVariable('name3', 'type2', 'id3'); - var result_1 = Blockly.Variables.getVariable(workspace, 'id1'); - var result_2 = Blockly.Variables.getVariable(workspace, 'id2'); - var result_3 = Blockly.Variables.getVariable(workspace, 'id3'); - - assertEquals(var_1, result_1); - assertEquals(var_2, result_2); - assertEquals(var_3, result_3); - } -); - -var test_getVariable_byNameAndType = buildVariablesTest( - function(workspace) { - var var_1 = workspace.createVariable('name1', 'type1', 'id1'); - var var_2 = workspace.createVariable('name2', 'type1', 'id2'); - var var_3 = workspace.createVariable('name3', 'type2', 'id3'); - var result_1 = - Blockly.Variables.getVariable(workspace, null, 'name1', 'type1'); - var result_2 = - Blockly.Variables.getVariable(workspace, null, 'name2', 'type1'); - var result_3 = - Blockly.Variables.getVariable(workspace, null, 'name3', 'type2'); - - // Searching by name + type is correct. - assertEquals(var_1, result_1); - assertEquals(var_2, result_2); - assertEquals(var_3, result_3); - } -); - -var test_getVariable_byIdThenName = buildVariablesTest( - function(workspace) { - var var_1 = workspace.createVariable('name1', 'type1', 'id1'); - var var_2 = workspace.createVariable('name2', 'type1', 'id2'); - var var_3 = workspace.createVariable('name3', 'type2', 'id3'); - var result_1 = - Blockly.Variables.getVariable(workspace, 'badId', 'name1', 'type1'); - var result_2 = - Blockly.Variables.getVariable(workspace, 'badId', 'name2', 'type1'); - var result_3 = - Blockly.Variables.getVariable(workspace, 'badId', 'name3', 'type2'); - - // Searching by ID failed, but falling back onto name + type is correct. - assertEquals(var_1, result_1); - assertEquals(var_2, result_2); - assertEquals(var_3, result_3); - } -); diff --git a/tests/mocha/index.html b/tests/mocha/index.html index c156f3f28..70d7ab502 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -59,6 +59,7 @@ + diff --git a/tests/mocha/variables_test.js b/tests/mocha/variables_test.js new file mode 100644 index 000000000..7e0efbdb9 --- /dev/null +++ b/tests/mocha/variables_test.js @@ -0,0 +1,142 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +suite('Variables', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + Blockly.defineBlocksWithJsonArray([{ + "type": "get_var_block", + "message0": "%1", + "args0": [ + { + "type": "field_variable", + "name": "VAR", + "variableTypes": ["", "type1", "type2"] + } + ] + }]); + this.workspace.createVariable('foo', 'type1', '1'); + this.workspace.createVariable('bar', 'type1', '2'); + this.workspace.createVariable('baz', 'type1', '3'); + }); + + teardown(function() { + delete Blockly.Blocks['get_var_block']; + this.workspace.dispose(); + + // Clear Blockly.Event state. + Blockly.Events.setGroup(false); + Blockly.Events.disabled_ = 0; + sinon.restore(); + }); + + /** + * Create a test get_var_block. + * Will fail if get_var_block isn't defined. + * @param {!Blockly.Workspace} workspace The workspace on which to create the + * block. + * @param {!string} variable_id The id of the variable to reference. + * @return {!Blockly.Block} The created block. + */ + function createTestVarBlock(workspace, variable_id) { + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue(variable_id); + Blockly.Events.enable(); + return block; + } + + suite('allUsedVarModels', function() { + test('All used', function() { + createTestVarBlock(this.workspace, '1'); + createTestVarBlock(this.workspace, '2'); + createTestVarBlock(this.workspace, '3'); + + var result = Blockly.Variables.allUsedVarModels(this.workspace); + assertEquals('Expected three variables in the list of used variables', + 3, result.length); + }); + + test('Some unused', function() { + createTestVarBlock(this.workspace, '2'); + + var result = Blockly.Variables.allUsedVarModels(this.workspace); + assertEquals('Expected one variable in the list of used variables', + 1, result.length); + assertEquals('Expected variable with ID 2 in the list of used variables', + '2', result[0].getId()); + }); + + test('Var used twice', function() { + createTestVarBlock(this.workspace, '2'); + createTestVarBlock(this.workspace, '2'); + + var result = Blockly.Variables.allUsedVarModels(this.workspace); + // Using the same variable multiple times should not change the number of + // elements in the list. + assertEquals('Expected one variable in the list of used variables', + 1, result.length); + assertEquals('Expected variable with ID 2 in the list of used variables', + '2', result[0].getId()); + }); + + test('All unused', function() { + var result = Blockly.Variables.allUsedVarModels(this.workspace); + assertEquals('Expected no variables in the list of used variables', + 0, result.length); + }); + }); + + suite('getVariable', function() { + test('By id', function() { + var var1 = this.workspace.createVariable('name1', 'type1', 'id1'); + var var2 = this.workspace.createVariable('name2', 'type1', 'id2'); + var var3 = this.workspace.createVariable('name3', 'type2', 'id3'); + var result1 = Blockly.Variables.getVariable(this.workspace, 'id1'); + var result2 = Blockly.Variables.getVariable(this.workspace, 'id2'); + var result3 = Blockly.Variables.getVariable(this.workspace, 'id3'); + + assertEquals(var1, result1); + assertEquals(var2, result2); + assertEquals(var3, result3); + }); + + test('By name and type', function() { + var var1 = this.workspace.createVariable('name1', 'type1', 'id1'); + var var2 = this.workspace.createVariable('name2', 'type1', 'id2'); + var var3 = this.workspace.createVariable('name3', 'type2', 'id3'); + var result1 = + Blockly.Variables.getVariable(this.workspace, null, 'name1', 'type1'); + var result2 = + Blockly.Variables.getVariable(this.workspace, null, 'name2', 'type1'); + var result3 = + Blockly.Variables.getVariable(this.workspace, null, 'name3', 'type2'); + + // Searching by name + type is correct. + assertEquals(var1, result1); + assertEquals(var2, result2); + assertEquals(var3, result3); + }); + + test('Bad id with name and type fallback', function() { + var var1 = this.workspace.createVariable('name1', 'type1', 'id1'); + var var2 = this.workspace.createVariable('name2', 'type1', 'id2'); + var var3 = this.workspace.createVariable('name3', 'type2', 'id3'); + var result1 = + Blockly.Variables.getVariable(this.workspace, 'badId', 'name1', 'type1'); + var result2 = + Blockly.Variables.getVariable(this.workspace, 'badId', 'name2', 'type1'); + var result3 = + Blockly.Variables.getVariable(this.workspace, 'badId', 'name3', 'type2'); + + // Searching by ID failed, but falling back onto name + type is correct. + assertEquals(var1, result1); + assertEquals(var2, result2); + assertEquals(var3, result3); + }); + }); +}); From e838027629e78b509672f92944cbcd8baef4a692 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Thu, 16 Apr 2020 17:39:38 -0700 Subject: [PATCH 026/139] Convert variable model tests to mocha. (#3829) * Convert variable model tests to mocha. * Delete old jsunit test. * Updating to use chai syntax. --- tests/jsunit/index.html | 1 - tests/jsunit/variable_model_test.js | 77 ----------------------------- tests/mocha/index.html | 1 + tests/mocha/variable_model_test.js | 58 ++++++++++++++++++++++ 4 files changed, 59 insertions(+), 78 deletions(-) delete mode 100644 tests/jsunit/variable_model_test.js create mode 100644 tests/mocha/variable_model_test.js diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index 15a0b5156..3e633001e 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -20,7 +20,6 @@ - diff --git a/tests/jsunit/variable_model_test.js b/tests/jsunit/variable_model_test.js deleted file mode 100644 index 58e32c9b6..000000000 --- a/tests/jsunit/variable_model_test.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Tests for variable model. - * @author marisaleung@google.com (Marisa Leung) - */ -'use strict'; - -var variable; -var workspace; - -function variableModelTest_setUp() { - workspace = new Blockly.Workspace(); -} - -function variableModelTest_tearDown() { - workspace.dispose(); - variable = null; -} - -/** - * These tests check the constructor of the variable model. - */ -function testInit_Trivial() { - variableModelTest_setUp(); - variable = new Blockly.VariableModel(workspace, 'test', 'test_type', - 'test_id'); - assertEquals('test', variable.name); - assertEquals('test_type', variable.type); - assertEquals('test_id', variable.id_); - variableModelTest_tearDown(); -} - -function testInit_NullType() { - variableModelTest_setUp(); - variable = new Blockly.VariableModel(workspace, 'test', null, 'test_id'); - assertEquals('', variable.type); - variableModelTest_tearDown(); -} - -function testInit_UndefinedType() { - variableModelTest_setUp(); - variable = new Blockly.VariableModel(workspace, 'test', undefined, 'test_id'); - assertEquals('', variable.type); - variableModelTest_tearDown(); -} - -function testInit_NullId() { - variableModelTest_setUp(); - variable = new Blockly.VariableModel(workspace, 'test', 'test_type', null); - assertEquals('test', variable.name); - assertEquals('test_type', variable.type); - assertNotNull(variable.id_); - variableModelTest_tearDown(); -} - -function testInit_UndefinedId() { - variableModelTest_setUp(); - variable = new Blockly.VariableModel(workspace, 'test', 'test_type', undefined); - assertEquals('test', variable.name); - assertEquals('test_type', variable.type); - assertNotNull(variable.id_); - variableModelTest_tearDown(); -} - -function testInit_OnlyNameProvided() { - variableModelTest_setUp(); - variable = new Blockly.VariableModel(workspace, 'test'); - assertEquals('test', variable.name); - assertEquals('', variable.type); - assertNotNull(variable.id_); - variableModelTest_tearDown(); -} diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 70d7ab502..e0bede811 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -60,6 +60,7 @@ + diff --git a/tests/mocha/variable_model_test.js b/tests/mocha/variable_model_test.js new file mode 100644 index 000000000..fb47818b9 --- /dev/null +++ b/tests/mocha/variable_model_test.js @@ -0,0 +1,58 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +suite('Variable Model', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + }); + + teardown(function() { + this.workspace.dispose(); + }); + + test('Trivial', function() { + var variable = new Blockly.VariableModel( + this.workspace, 'test', 'test_type', 'test_id'); + chai.assert.equal(variable.name, 'test'); + chai.assert.equal(variable.type, 'test_type'); + chai.assert.equal(variable.id_, 'test_id'); + }); + + test('Null type', function() { + var variable = new Blockly.VariableModel( + this.workspace, 'test', null, 'test_id'); + chai.assert.equal(variable.type, ''); + }); + + test('Undefined type', function() { + var variable = new Blockly.VariableModel( + this.workspace, 'test', undefined, 'test_id'); + chai.assert.equal(variable.type, ''); + }); + + test('Null id', function() { + var variable = new Blockly.VariableModel( + this.workspace, 'test', 'test_type', null); + chai.assert.equal(variable.name, 'test'); + chai.assert.equal(variable.type, 'test_type'); + chai.assert.exists(variable.id_); + }); + + test('Undefined id', function() { + var variable = new Blockly.VariableModel( + this.workspace, 'test', 'test_type', undefined); + chai.assert.equal(variable.name, 'test'); + chai.assert.equal(variable.type, 'test_type'); + chai.assert.exists(variable.id_); + }); + + test('Only name provided', function() { + var variable = new Blockly.VariableModel(this.workspace, 'test'); + chai.assert.equal(variable.name, 'test'); + chai.assert.equal(variable.type, ''); + chai.assert.exists(variable.id_); + }); +}); From a74cd0898c0f99343873593657423f0b439de897 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Thu, 16 Apr 2020 17:47:17 -0700 Subject: [PATCH 027/139] Converting variable map tests to mocha. (#3827) * Converting variable map tests to mocha. * Removing TODO updating chai syntax. --- tests/jsunit/index.html | 1 - tests/jsunit/variable_map_test.js | 284 ------------------------------ tests/mocha/.eslintrc.json | 1 + tests/mocha/event_test.js | 23 +-- tests/mocha/index.html | 3 +- tests/mocha/test_helpers.js | 19 +- tests/mocha/variable_map_test.js | 250 ++++++++++++++++++++++++++ 7 files changed, 274 insertions(+), 307 deletions(-) delete mode 100644 tests/jsunit/variable_map_test.js create mode 100644 tests/mocha/variable_map_test.js diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index 3e633001e..06c81a014 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -19,7 +19,6 @@ - diff --git a/tests/jsunit/variable_map_test.js b/tests/jsunit/variable_map_test.js deleted file mode 100644 index 8f5b2f6ff..000000000 --- a/tests/jsunit/variable_map_test.js +++ /dev/null @@ -1,284 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - - /** - * @fileoverview Tests for variable map. - * @author marisaleung@google.com (Marisa Leung) - */ -'use strict'; - -var variable_map; -var mockControl_; -var workspace; - -function variableMapTest_setUp() { - workspace = new Blockly.Workspace(); - variable_map = new Blockly.VariableMap(workspace); -} - -function variableMapTest_tearDown() { - workspace.dispose(); - if (mockControl_) { - mockControl_.restore(); - } - variable_map = null; -} - -function test_getVariable_ByNameAndType() { - variableMapTest_setUp(); - var var_1 = variable_map.createVariable('name1', 'type1', 'id1'); - var var_2 = variable_map.createVariable('name2', 'type1', 'id2'); - var var_3 = variable_map.createVariable('name3', 'type2', 'id3'); - var result_1 = variable_map.getVariable('name1', 'type1'); - var result_2 = variable_map.getVariable('name2', 'type1'); - var result_3 = variable_map.getVariable('name3', 'type2'); - - // Searching by name + type is correct. - assertEquals(var_1, result_1); - assertEquals(var_2, result_2); - assertEquals(var_3, result_3); - - // Searching only by name defaults to the '' type. - assertNull(variable_map.getVariable('name1')); - assertNull(variable_map.getVariable('name2')); - assertNull(variable_map.getVariable('name3')); - variableMapTest_tearDown(); -} - -function test_getVariable_NotFound() { - variableMapTest_setUp(); - var result = variable_map.getVariable('name1'); - assertNull(result); - variableMapTest_tearDown(); -} - -function test_getVariableById_Trivial() { - variableMapTest_setUp(); - var var_1 = variable_map.createVariable('name1', 'type1', 'id1'); - var var_2 = variable_map.createVariable('name2', 'type1', 'id2'); - var var_3 = variable_map.createVariable('name3', 'type2', 'id3'); - var result_1 = variable_map.getVariableById('id1'); - var result_2 = variable_map.getVariableById('id2'); - var result_3 = variable_map.getVariableById('id3'); - - assertEquals(var_1, result_1); - assertEquals(var_2, result_2); - assertEquals(var_3, result_3); - variableMapTest_tearDown(); -} - -function test_getVariableById_NotFound() { - variableMapTest_setUp(); - var result = variable_map.getVariableById('id1'); - assertNull(result); - variableMapTest_tearDown(); -} - -function test_createVariableTrivial() { - variableMapTest_setUp(); - variable_map.createVariable('name1', 'type1', 'id1'); - checkVariableValues(variable_map, 'name1', 'type1', 'id1'); - variableMapTest_tearDown(); -} - -function test_createVariableAlreadyExists() { - // Expect that when the variable already exists, the variableMap_ is unchanged. - variableMapTest_setUp(); - variable_map.createVariable('name1', 'type1', 'id1'); - - // Assert there is only one variable in the variable_map. - var keys = Object.keys(variable_map.variableMap_); - assertEquals(1, keys.length); - var varMapLength = variable_map.variableMap_[keys[0]].length; - assertEquals(1, varMapLength); - - variable_map.createVariable('name1', 'type1'); - checkVariableValues(variable_map, 'name1', 'type1', 'id1'); - // Check that the size of the variableMap_ did not change. - keys = Object.keys(variable_map.variableMap_); - assertEquals(1, keys.length); - varMapLength = variable_map.variableMap_[keys[0]].length; - assertEquals(1, varMapLength); - variableMapTest_tearDown(); -} - -function test_createVariableNameAlreadyExists() { - // Expect that when a variable with the same name but a different type already - // exists, the new variable is created. - variableMapTest_setUp(); - variable_map.createVariable('name1', 'type1', 'id1'); - - // Assert there is only one variable in the variable_map. - var keys = Object.keys(variable_map.variableMap_); - assertEquals(1, keys.length); - var varMapLength = variable_map.variableMap_[keys[0]].length; - assertEquals(1, varMapLength); - - variable_map.createVariable('name1', 'type2', 'id2'); - checkVariableValues(variable_map, 'name1', 'type1', 'id1'); - checkVariableValues(variable_map, 'name1', 'type2', 'id2'); - // Check that the size of the variableMap_ did change. - keys = Object.keys(variable_map.variableMap_); - assertEquals(2, keys.length); - variableMapTest_tearDown(); -} -function test_createVariableNullAndUndefinedType() { - variableMapTest_setUp(); - variable_map.createVariable('name1', null, 'id1'); - variable_map.createVariable('name2', undefined, 'id2'); - - checkVariableValues(variable_map, 'name1', '', 'id1'); - checkVariableValues(variable_map, 'name2', '', 'id2'); - variableMapTest_tearDown(); -} - -function test_createVariableNullId() { - variableMapTest_setUp(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '2']); - try { - variable_map.createVariable('name1', 'type1', null); - checkVariableValues(variable_map, 'name1', 'type1', '1'); - } finally { - variableMapTest_tearDown(); - } -} - -function test_createVariableUndefinedId() { - variableMapTest_setUp(); - mockControl_ = setUpMockMethod(Blockly.utils, 'genUid', null, ['1', '2']); - try { - variable_map.createVariable('name1', 'type1', undefined); - checkVariableValues(variable_map, 'name1', 'type1', '1'); - } finally { - variableMapTest_tearDown(); - } -} - -function test_createVariableIdAlreadyExists() { - variableMapTest_setUp(); - variable_map.createVariable('name1', 'type1', 'id1'); - try { - variable_map.createVariable('name2', 'type2', 'id1'); - fail(); - } catch (e) { - // expected - } - variableMapTest_tearDown(); -} - -function test_createVariableMismatchedIdAndType() { - variableMapTest_setUp(); - variable_map.createVariable('name1', 'type1', 'id1'); - try { - variable_map.createVariable('name1', 'type2', 'id1'); - fail(); - } catch (e) { - // expected - } - try { - variable_map.createVariable('name1', 'type1', 'id2'); - fail(); - } catch (e) { - // expected - } - variableMapTest_tearDown(); -} - -function test_createVariableTwoSameTypes() { - variableMapTest_setUp(); - variable_map.createVariable('name1', 'type1', 'id1'); - variable_map.createVariable('name2', 'type1', 'id2'); - - checkVariableValues(variable_map, 'name1', 'type1', 'id1'); - checkVariableValues(variable_map, 'name2', 'type1', 'id2'); - variableMapTest_tearDown(); -} - -function test_getVariablesOfType_Trivial() { - variableMapTest_setUp(); - var var_1 = variable_map.createVariable('name1', 'type1', 'id1'); - var var_2 = variable_map.createVariable('name2', 'type1', 'id2'); - variable_map.createVariable('name3', 'type2', 'id3'); - variable_map.createVariable('name4', 'type3', 'id4'); - var result_array_1 = variable_map.getVariablesOfType('type1'); - var result_array_2 = variable_map.getVariablesOfType('type5'); - isEqualArrays([var_1, var_2], result_array_1); - isEqualArrays([], result_array_2); - variableMapTest_tearDown(); -} - -function test_getVariablesOfType_Null() { - variableMapTest_setUp(); - var var_1 = variable_map.createVariable('name1', '', 'id1'); - var var_2 = variable_map.createVariable('name2', '', 'id2'); - var var_3 = variable_map.createVariable('name3', '', 'id3'); - variable_map.createVariable('name4', 'type1', 'id4'); - var result_array = variable_map.getVariablesOfType(null); - isEqualArrays([var_1, var_2, var_3], result_array); - variableMapTest_tearDown(); -} - -function test_getVariablesOfType_EmptyString() { - variableMapTest_setUp(); - var var_1 = variable_map.createVariable('name1', null, 'id1'); - var var_2 = variable_map.createVariable('name2', null, 'id2'); - var result_array = variable_map.getVariablesOfType(''); - isEqualArrays([var_1, var_2], result_array); - variableMapTest_tearDown(); -} - -function test_getVariablesOfType_Deleted() { - variableMapTest_setUp(); - var variable = variable_map.createVariable('name1', null, 'id1'); - variable_map.deleteVariable(variable); - var result_array = variable_map.getVariablesOfType(''); - isEqualArrays([], result_array); - variableMapTest_tearDown(); -} - -function test_getVariablesOfType_DoesNotExist() { - variableMapTest_setUp(); - var result_array = variable_map.getVariablesOfType('type1'); - isEqualArrays([], result_array); - variableMapTest_tearDown(); -} - -function test_getVariableTypes_Trivial() { - variableMapTest_setUp(); - variable_map.createVariable('name1', 'type1', 'id1'); - variable_map.createVariable('name2', 'type1', 'id2'); - variable_map.createVariable('name3', 'type2', 'id3'); - variable_map.createVariable('name4', 'type3', 'id4'); - var result_array = variable_map.getVariableTypes(); - // The empty string is always an option. - isEqualArrays(['type1', 'type2', 'type3', ''], result_array); - variableMapTest_tearDown(); -} - -function test_getVariableTypes_None() { - variableMapTest_setUp(); - // The empty string is always an option. - var result_array = variable_map.getVariableTypes(); - isEqualArrays([''], result_array); - variableMapTest_tearDown(); -} - -function test_getAllVariables_Trivial() { - variableMapTest_setUp(); - var var_1 = variable_map.createVariable('name1', 'type1', 'id1'); - var var_2 = variable_map.createVariable('name2', 'type1', 'id2'); - var var_3 = variable_map.createVariable('name3', 'type2', 'id3'); - var result_array = variable_map.getAllVariables(); - isEqualArrays([var_1, var_2, var_3], result_array); - variableMapTest_tearDown(); -} - -function test_getAllVariables_None() { - variableMapTest_setUp(); - var result_array = variable_map.getAllVariables(); - isEqualArrays([], result_array); - variableMapTest_tearDown(); -} diff --git a/tests/mocha/.eslintrc.json b/tests/mocha/.eslintrc.json index c6ae36484..f057f88e2 100644 --- a/tests/mocha/.eslintrc.json +++ b/tests/mocha/.eslintrc.json @@ -17,6 +17,7 @@ "assertUndefined": true, "assertNotUndefined": true, "assertNotNullNorUndefined": true, + "assertVariableValues": true, "defineStackBlock": true, "defineRowBlock": true, "defineStatementBlock": true, diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index 69a33fb2b..8304d6a34 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -228,21 +228,6 @@ suite('Events', function() { this.variable = this.workspace.createVariable('name1', 'type1', 'id1'); }); - /** - * Check if a variable with the given values exists. - * @param {Blockly.Workspace|Blockly.VariableMap} container The workspace or - * variableMap the checked variable belongs to. - * @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. - */ - function checkVariableValues(container, name, type, id) { - var variable = container.getVariableById(id); - assertNotUndefined(variable); - assertEquals(name, variable.name); - assertEquals(type, variable.type); - assertEquals(id, variable.getId()); - } suite('Constructors', function() { test('Var base', function() { var event = new Blockly.Events.VarBase(this.variable); @@ -334,7 +319,7 @@ suite('Events', function() { var x = this.workspace.getVariableById('id2'); assertNull(x); event.run(true); - checkVariableValues(this.workspace, 'name2', 'type2', 'id2'); + assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); }); test('Var delete', function() { @@ -348,7 +333,7 @@ suite('Events', function() { var event = new Blockly.Events.VarRename(this.variable, 'name2'); event.run(true); assertNull(this.workspace.getVariable('name1')); - checkVariableValues(this.workspace, 'name2', 'type1', 'id1'); + assertVariableValues(this.workspace, 'name2', 'type1', 'id1'); }); }); suite('Run Backward', function() { @@ -364,14 +349,14 @@ suite('Events', function() { var event = Blockly.Events.fromJson(json, this.workspace); assertNull(this.workspace.getVariableById('id2')); event.run(false); - checkVariableValues(this.workspace, 'name2', 'type2', 'id2'); + assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); }); test('Var rename', function() { var event = new Blockly.Events.VarRename(this.variable, 'name2'); event.run(false); assertNull(this.workspace.getVariable('name2')); - checkVariableValues(this.workspace, 'name1', 'type1', 'id1'); + assertVariableValues(this.workspace, 'name1', 'type1', 'id1'); }); }); }); diff --git a/tests/mocha/index.html b/tests/mocha/index.html index e0bede811..004ca414d 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -59,8 +59,9 @@ - + + diff --git a/tests/mocha/test_helpers.js b/tests/mocha/test_helpers.js index 61aae9475..86748490c 100644 --- a/tests/mocha/test_helpers.js +++ b/tests/mocha/test_helpers.js @@ -6,7 +6,7 @@ /* exported assertEquals, assertNotEquals, assertArrayEquals, assertTrue, assertFalse, assertNull, assertNotNull, assertNotNullNorUndefined, assert, - isEqualArrays, assertUndefined, assertNotUndefined, + isEqualArrays, assertUndefined, assertNotUndefined, assertVariableValues, defineRowBlock, defineStackBlock, defineStatementBlock, createTestBlock */ function _argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) { return args.length == expectedNumberOfNonCommentArgs + 1; @@ -141,6 +141,22 @@ function assertArrayEquals() { isEqualArrays(var1, var2); } +/** + * Check if a variable with the given values exists. + * @param {Blockly.Workspace|Blockly.VariableMap} container The workspace or + * variableMap the checked variable belongs to. + * @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. + */ +function assertVariableValues(container, name, type, id) { + var variable = container.getVariableById(id); + assertNotNull(variable); + assertEquals(name, variable.name); + assertEquals(type, variable.type); + assertEquals(id, variable.getId()); +} + function defineStackBlock() { Blockly.defineBlocksWithJsonArray([{ "type": "stack_block", @@ -191,4 +207,3 @@ function createTestBlock() { } }; } - diff --git a/tests/mocha/variable_map_test.js b/tests/mocha/variable_map_test.js new file mode 100644 index 000000000..91101f79a --- /dev/null +++ b/tests/mocha/variable_map_test.js @@ -0,0 +1,250 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +suite('Variable Map', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + this.variableMap = new Blockly.VariableMap(this.workspace); + }); + + teardown(function() { + this.workspace.dispose(); + sinon.restore(); + }); + + suite('createVariable', function() { + test('Trivial', function() { + this.variableMap.createVariable('name1', 'type1', 'id1'); + assertVariableValues(this.variableMap, 'name1', 'type1', 'id1'); + }); + + test('Already exists', function() { + // Expect that when the variable already exists, the variableMap_ is unchanged. + this.variableMap.createVariable('name1', 'type1', 'id1'); + + // Assert there is only one variable in the this.variableMap. + var keys = Object.keys(this.variableMap.variableMap_); + chai.assert.equal(keys.length, 1); + var varMapLength = this.variableMap.variableMap_[keys[0]].length; + chai.assert.equal(varMapLength, 1); + + this.variableMap.createVariable('name1', 'type1'); + assertVariableValues(this.variableMap, 'name1', 'type1', 'id1'); + // Check that the size of the variableMap_ did not change. + keys = Object.keys(this.variableMap.variableMap_); + chai.assert.equal(keys.length, 1); + varMapLength = this.variableMap.variableMap_[keys[0]].length; + chai.assert.equal(varMapLength, 1); + }); + + test('Name already exists', function() { + // Expect that when a variable with the same name but a different type already + // exists, the new variable is created. + this.variableMap.createVariable('name1', 'type1', 'id1'); + + // Assert there is only one variable in the this.variableMap. + var keys = Object.keys(this.variableMap.variableMap_); + chai.assert.equal(keys.length, 1); + var varMapLength = this.variableMap.variableMap_[keys[0]].length; + chai.assert.equal(varMapLength, 1); + + this.variableMap.createVariable('name1', 'type2', 'id2'); + assertVariableValues(this.variableMap, 'name1', 'type1', 'id1'); + assertVariableValues(this.variableMap, 'name1', 'type2', 'id2'); + // Check that the size of the variableMap_ did change. + keys = Object.keys(this.variableMap.variableMap_); + chai.assert.equal(keys.length, 2); + }); + + test('Null type', function() { + this.variableMap.createVariable('name1', null, 'id1'); + assertVariableValues(this.variableMap, 'name1', '', 'id1'); + }); + + test('Undefined type', function() { + this.variableMap.createVariable('name2', undefined, 'id2'); + assertVariableValues(this.variableMap, 'name2', '', 'id2'); + }); + + test('Null id', function() { + sinon.stub(Blockly.utils, "genUid").returns('1'); + this.variableMap.createVariable('name1', 'type1', null); + assertVariableValues(this.variableMap, 'name1', 'type1', '1'); + }); + + test('Undefined id', function() { + sinon.stub(Blockly.utils, "genUid").returns('1'); + this.variableMap.createVariable('name1', 'type1', undefined); + assertVariableValues(this.variableMap, 'name1', 'type1', '1'); + }); + + test('Two variables same type', function() { + this.variableMap.createVariable('name1', 'type1', 'id1'); + this.variableMap.createVariable('name2', 'type1', 'id2'); + + assertVariableValues(this.variableMap, 'name1', 'type1', 'id1'); + assertVariableValues(this.variableMap, 'name2', 'type1', 'id2'); + }); + + test('Two variables same name', function() { + this.variableMap.createVariable('name1', 'type1', 'id1'); + this.variableMap.createVariable('name1', 'type2', 'id2'); + + assertVariableValues(this.variableMap, 'name1', 'type1', 'id1'); + assertVariableValues(this.variableMap, 'name1', 'type2', 'id2'); + }); + + suite('Error cases', function() { + test('Id already exists', function() { + this.variableMap.createVariable('name1', 'type1', 'id1'); + var variableMap = this.variableMap; + chai.assert.throws(function() { + variableMap.createVariable('name2', 'type2', 'id1'); + }, /"id1".*in use/); + assertVariableValues(this.variableMap, 'name1', 'type1', 'id1'); + }); + + test('Mismatched id', function() { + this.variableMap.createVariable('name1', 'type1', 'id1'); + var variableMap = this.variableMap; + chai.assert.throws(function() { + variableMap.createVariable('name1', 'type1', 'id2'); + }, /"name1".*in use/); + assertVariableValues(this.variableMap, 'name1', 'type1', 'id1'); + }); + + test('Mismatched type', function() { + this.variableMap.createVariable('name1', 'type1', 'id1'); + var variableMap = this.variableMap; + chai.assert.throws(function() { + variableMap.createVariable('name1', 'type2', 'id1'); + }); + assertVariableValues(this.variableMap, 'name1', 'type1', 'id1'); + chai.assert.isNull(this.variableMap.getVariableById('id2')); + }); + }); + }); + + suite('getVariable', function() { + test('By name and type', function() { + var var1 = this.variableMap.createVariable('name1', 'type1', 'id1'); + var var2 = this.variableMap.createVariable('name2', 'type1', 'id2'); + var var3 = this.variableMap.createVariable('name3', 'type2', 'id3'); + var result1 = this.variableMap.getVariable('name1', 'type1'); + var result2 = this.variableMap.getVariable('name2', 'type1'); + var result3 = this.variableMap.getVariable('name3', 'type2'); + + // Searching by name + type is correct. + chai.assert.equal(result1, var1); + chai.assert.equal(result2, var2); + chai.assert.equal(result3, var3); + + // Searching only by name defaults to the '' type. + chai.assert.isNull(this.variableMap.getVariable('name1')); + chai.assert.isNull(this.variableMap.getVariable('name2')); + chai.assert.isNull(this.variableMap.getVariable('name3')); + }); + + test('Not found', function() { + var result = this.variableMap.getVariable('name1'); + chai.assert.isNull(result); + }); + }); + + suite('getVariableById', function() { + test('Trivial', function() { + var var1 = this.variableMap.createVariable('name1', 'type1', 'id1'); + var var2 = this.variableMap.createVariable('name2', 'type1', 'id2'); + var var3 = this.variableMap.createVariable('name3', 'type2', 'id3'); + var result1 = this.variableMap.getVariableById('id1'); + var result2 = this.variableMap.getVariableById('id2'); + var result3 = this.variableMap.getVariableById('id3'); + + chai.assert.equal(result1, var1); + chai.assert.equal(result2, var2); + chai.assert.equal(result3, var3); + }); + + test('Not found', function() { + var result = this.variableMap.getVariableById('id1'); + chai.assert.isNull(result); + }); + }); + + suite('getVariableTypes', function() { + test('Trivial', function() { + this.variableMap.createVariable('name1', 'type1', 'id1'); + this.variableMap.createVariable('name2', 'type1', 'id2'); + this.variableMap.createVariable('name3', 'type2', 'id3'); + this.variableMap.createVariable('name4', 'type3', 'id4'); + var resultArray = this.variableMap.getVariableTypes(); + // The empty string is always an option. + assertArrayEquals(resultArray, ['type1', 'type2', 'type3', '']); + }); + + test('None', function() { + // The empty string is always an option. + var resultArray = this.variableMap.getVariableTypes(); + assertArrayEquals(resultArray, ['']); + }); + }); + + suite('getVariablesOfType', function() { + test('Trivial', function() { + var var1 = this.variableMap.createVariable('name1', 'type1', 'id1'); + var var2 = this.variableMap.createVariable('name2', 'type1', 'id2'); + this.variableMap.createVariable('name3', 'type2', 'id3'); + this.variableMap.createVariable('name4', 'type3', 'id4'); + var resultArray1 = this.variableMap.getVariablesOfType('type1'); + var resultArray2 = this.variableMap.getVariablesOfType('type5'); + assertArrayEquals(resultArray1, [var1, var2]); + assertArrayEquals(resultArray2, []); + }); + + test('Null', function() { + var var1 = this.variableMap.createVariable('name1', '', 'id1'); + var var2 = this.variableMap.createVariable('name2', '', 'id2'); + var var3 = this.variableMap.createVariable('name3', '', 'id3'); + this.variableMap.createVariable('name4', 'type1', 'id4'); + var resultArray = this.variableMap.getVariablesOfType(null); + assertArrayEquals(resultArray, [var1, var2, var3]); + }); + + test('Empty string', function() { + var var1 = this.variableMap.createVariable('name1', null, 'id1'); + var var2 = this.variableMap.createVariable('name2', null, 'id2'); + var resultArray = this.variableMap.getVariablesOfType(''); + assertArrayEquals(resultArray, [var1, var2]); + }); + + test('Deleted', function() { + var variable = this.variableMap.createVariable('name1', null, 'id1'); + this.variableMap.deleteVariable(variable); + var resultArray = this.variableMap.getVariablesOfType(''); + assertArrayEquals(resultArray, []); + }); + + test('Does not exist', function() { + var resultArray = this.variableMap.getVariablesOfType('type1'); + assertArrayEquals(resultArray, []); + }); + }); + + suite('getAllVariables', function() { + test('Trivial', function() { + var var1 = this.variableMap.createVariable('name1', 'type1', 'id1'); + var var2 = this.variableMap.createVariable('name2', 'type1', 'id2'); + var var3 = this.variableMap.createVariable('name3', 'type2', 'id3'); + var resultArray = this.variableMap.getAllVariables(); + assertArrayEquals(resultArray, [var1, var2, var3]); + }); + + test('None', function() { + var resultArray = this.variableMap.getAllVariables(); + assertArrayEquals(resultArray, []); + }); + }); +}); From 4b2038383193e2107e168743a81b5b0d5946526f Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Thu, 16 Apr 2020 18:22:32 -0700 Subject: [PATCH 028/139] Add Selectable interface (#3823) * Add I Selectable interface --- core/block_svg.js | 22 +++++++++++++++++ core/blockly.js | 28 +++++++--------------- core/interfaces/i_copyable.js | 41 ++++++++++++++++++++++++++++++++ core/interfaces/i_deletable.js | 24 +++++++++++++++++++ core/interfaces/i_movable.js | 24 +++++++++++++++++++ core/interfaces/i_selectable.js | 42 +++++++++++++++++++++++++++++++++ core/workspace_comment_svg.js | 15 ++++++++++++ scripts/gulpfiles/typings.js | 1 + 8 files changed, 177 insertions(+), 20 deletions(-) create mode 100644 core/interfaces/i_copyable.js create mode 100644 core/interfaces/i_deletable.js create mode 100644 core/interfaces/i_movable.js create mode 100644 core/interfaces/i_selectable.js diff --git a/core/block_svg.js b/core/block_svg.js index 5938e597e..83af1db30 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -32,6 +32,7 @@ goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.object'); goog.require('Blockly.utils.Rect'); +goog.requireType('Blockly.ICopyable'); /** * Class for a block's SVG representation. @@ -42,6 +43,7 @@ goog.require('Blockly.utils.Rect'); * @param {string=} opt_id Optional ID. Use this ID if provided, otherwise * create a new ID. * @extends {Blockly.Block} + * @implements {Blockly.ICopyable} * @constructor */ Blockly.BlockSvg = function(workspace, prototypeName, opt_id) { @@ -991,6 +993,26 @@ Blockly.BlockSvg.prototype.dispose = function(healStack, animate) { Blockly.utils.dom.stopTextWidthCache(); }; +/** + * Encode a block for copying. + * @return {!Blockly.ICopyable.CopyData} Copy metadata. + * @package + */ +Blockly.BlockSvg.prototype.toCopyData = function() { + var xml = Blockly.Xml.blockToDom(this, true); + // Copy only the selected block and internal blocks. + Blockly.Xml.deleteNext(xml); + // Encode start position in XML. + var xy = this.getRelativeToSurfaceXY(); + xml.setAttribute('x', this.RTL ? -xy.x : xy.x); + xml.setAttribute('y', xy.y); + return { + xml: xml, + source: this.workspace, + typeCounts: Blockly.utils.getBlockTypeCounts(this, true) + }; +}; + /** * Change the colour of a block. * @package diff --git a/core/blockly.js b/core/blockly.js index 209c22e96..ceeae2ae8 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -51,7 +51,7 @@ Blockly.mainWorkspace = null; /** * Currently selected block. - * @type {Blockly.Block} + * @type {?Blockly.ICopyable} */ Blockly.selected = null; @@ -264,32 +264,20 @@ Blockly.onKeyDown = function(e) { /** * Copy a block or workspace comment onto the local clipboard. - * @param {!Blockly.Block | !Blockly.WorkspaceComment} toCopy Block or - * Workspace Comment to be copied. + * @param {!Blockly.ICopyable} toCopy Block or Workspace Comment to be copied. * @private */ Blockly.copy_ = function(toCopy) { - if (toCopy.isComment) { - var xml = toCopy.toXmlWithXY(); - } else { - var xml = Blockly.Xml.blockToDom(toCopy, true); - // Copy only the selected block and internal blocks. - Blockly.Xml.deleteNext(xml); - // Encode start position in XML. - var xy = toCopy.getRelativeToSurfaceXY(); - xml.setAttribute('x', toCopy.RTL ? -xy.x : xy.x); - xml.setAttribute('y', xy.y); - } - Blockly.clipboardXml_ = xml; - Blockly.clipboardSource_ = toCopy.workspace; - Blockly.clipboardTypeCounts_ = toCopy.isComment ? null : - Blockly.utils.getBlockTypeCounts(toCopy, true); + var data = toCopy.toCopyData(); + Blockly.clipboardXml_ = data.xml; + Blockly.clipboardSource_ = data.source; + Blockly.clipboardTypeCounts_ = data.typeCounts; }; /** * Duplicate this block and its children, or a workspace comment. - * @param {!Blockly.Block | !Blockly.WorkspaceComment} toDuplicate Block or - * Workspace Comment to be copied. + * @param {!Blockly.ICopyable} toDuplicate Block or Workspace Comment to be + * copied. * @package */ Blockly.duplicate = function(toDuplicate) { diff --git a/core/interfaces/i_copyable.js b/core/interfaces/i_copyable.js new file mode 100644 index 000000000..807911ef9 --- /dev/null +++ b/core/interfaces/i_copyable.js @@ -0,0 +1,41 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for an object that is copyable. + * @author samelh@google.com (Sam El-Husseini) + */ + +'use strict'; + +goog.provide('Blockly.ICopyable'); + +goog.require('Blockly.ISelectable'); + +goog.requireType('Blockly.WorkspaceSvg'); + + +/** + * @extends {Blockly.ISelectable} + * @interface + */ +Blockly.ICopyable = function() {}; + +/** + * Encode for copying. + * @return {!Blockly.ICopyable.CopyData} Copy metadata. + */ +Blockly.ICopyable.prototype.toCopyData; + +/** + * Copy Metadata. + * @typedef {{ + * xml:!Element, + * source:Blockly.WorkspaceSvg, + * typeCounts:?Object + * }} + */ +Blockly.ICopyable.CopyData; diff --git a/core/interfaces/i_deletable.js b/core/interfaces/i_deletable.js new file mode 100644 index 000000000..ee3058666 --- /dev/null +++ b/core/interfaces/i_deletable.js @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for an object that is deletable. + * @author samelh@google.com (Sam El-Husseini) + */ + +'use strict'; + +goog.provide('Blockly.IDeletable'); + + +/** @interface */ +Blockly.IDeletable = function() {}; + +/** + * Get whether this object is deletable or not. + * @return {boolean} True if deletable. + */ +Blockly.IDeletable.prototype.isDeletable; diff --git a/core/interfaces/i_movable.js b/core/interfaces/i_movable.js new file mode 100644 index 000000000..f183cd196 --- /dev/null +++ b/core/interfaces/i_movable.js @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for an object that is movable. + * @author samelh@google.com (Sam El-Husseini) + */ + +'use strict'; + +goog.provide('Blockly.IMovable'); + + +/** @interface */ +Blockly.IMovable = function() {}; + +/** + * Get whether this is movable or not. + * @return {boolean} True if movable. + */ +Blockly.IMovable.prototype.isMovable; diff --git a/core/interfaces/i_selectable.js b/core/interfaces/i_selectable.js new file mode 100644 index 000000000..8db8a63f5 --- /dev/null +++ b/core/interfaces/i_selectable.js @@ -0,0 +1,42 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for an object that is selectable. + * @author samelh@google.com (Sam El-Husseini) + */ + +'use strict'; + +goog.provide('Blockly.ISelectable'); + +goog.require('Blockly.IDeletable'); +goog.require('Blockly.IMovable'); + + +/** + * @extends {Blockly.IDeletable} + * @extends {Blockly.IMovable} + * @interface + */ +Blockly.ISelectable = function() {}; + +/** + * @type {string} + */ +Blockly.ISelectable.prototype.id; + +/** + * Select this. Highlight it visually. + * @return {void} + */ +Blockly.ISelectable.prototype.select; + +/** + * Unselect this. Unhighlight it visually. + * @return {void} + */ +Blockly.ISelectable.prototype.unselect; diff --git a/core/workspace_comment_svg.js b/core/workspace_comment_svg.js index f4b97a136..5301018cf 100644 --- a/core/workspace_comment_svg.js +++ b/core/workspace_comment_svg.js @@ -25,6 +25,7 @@ goog.require('Blockly.utils.object'); goog.require('Blockly.utils.Rect'); goog.require('Blockly.WorkspaceComment'); +goog.requireType('Blockly.ICopyable'); /** * Class for a workspace comment's SVG representation. @@ -35,6 +36,7 @@ goog.require('Blockly.WorkspaceComment'); * @param {string=} opt_id Optional ID. Use this ID if provided, otherwise * create a new ID. * @extends {Blockly.WorkspaceComment} + * @implements {Blockly.ICopyable} * @constructor */ Blockly.WorkspaceCommentSvg = function(workspace, content, height, width, @@ -612,6 +614,19 @@ Blockly.WorkspaceCommentSvg.prototype.toXmlWithXY = function(opt_noId) { return element; }; +/** + * Encode a comment for copying. + * @return {!Blockly.ICopyable.CopyData} Copy metadata. + * @package + */ +Blockly.WorkspaceCommentSvg.prototype.toCopyData = function() { + return { + xml: this.toXmlWithXY(), + source: this.workspace, + typeCounts: null + }; +}; + /** * CSS for workspace comment. See css.js for use. */ diff --git a/scripts/gulpfiles/typings.js b/scripts/gulpfiles/typings.js index 81dbe7ea6..0822dea3b 100644 --- a/scripts/gulpfiles/typings.js +++ b/scripts/gulpfiles/typings.js @@ -33,6 +33,7 @@ function typings() { "core/renderers/common", "core/renderers/measurables", "core/theme", + "core/interfaces", "core/utils", "msg/" ]; From 13093933b3d44be1fa585dd06303b4dc5de7d375 Mon Sep 17 00:00:00 2001 From: mmathrani <60405811+mmathrani@users.noreply.github.com> Date: Fri, 17 Apr 2020 08:19:28 -0700 Subject: [PATCH 029/139] Update the alert for demo storage. (#3830) --- demos/storage/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/storage/index.html b/demos/storage/index.html index 41462e295..38877a092 100644 --- a/demos/storage/index.html +++ b/demos/storage/index.html @@ -32,7 +32,7 @@ + diff --git a/tests/mocha/workspace_test.js b/tests/mocha/workspace_test.js new file mode 100644 index 000000000..42359bbfd --- /dev/null +++ b/tests/mocha/workspace_test.js @@ -0,0 +1,357 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +suite('Workspace', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + Blockly.defineBlocksWithJsonArray([{ + "type": "get_var_block", + "message0": "%1", + "args0": [ + { + "type": "field_variable", + "name": "VAR", + "variableTypes": ["", "type1", "type2"] + } + ] + }]); + }); + + teardown(function() { + delete Blockly.Blocks['get_var_block']; + this.workspace.dispose(); + }); + + suite('getTopBlocks(ordered=true)', function() { + test('Empty workspace', function() { + chai.assert.equal(this.workspace.getTopBlocks(true).length, 0); + }); + + test('Flat workspace one block', function() { + this.workspace.newBlock(''); + chai.assert.equal(this.workspace.getTopBlocks(true).length, 1); + }); + + test('Flat workspace one block after dispose', function() { + var blockA = this.workspace.newBlock(''); + this.workspace.newBlock(''); + blockA.dispose(); + chai.assert.equal(this.workspace.getTopBlocks(true).length, 1); + }); + + test('Flat workspace two blocks', function() { + this.workspace.newBlock(''); + this.workspace.newBlock(''); + chai.assert.equal(this.workspace.getTopBlocks(true).length, 2); + }); + + test('Clear', function() { + this.workspace.clear(); + chai.assert.equal(this.workspace.getTopBlocks(true).length, 0, + 'Clear empty workspace'); + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.clear(); + chai.assert.equal(this.workspace.getTopBlocks(true).length, 0); + }); + }); + + suite('getTopBlocks(ordered=false)', function() { + test('Empty workspace', function() { + chai.assert.equal(this.workspace.getTopBlocks(false).length, 0); + }); + + test('Flat workspace one block', function() { + this.workspace.newBlock(''); + chai.assert.equal(this.workspace.getTopBlocks(false).length, 1); + }); + + test('Flat workspace one block after dispose', function() { + var blockA = this.workspace.newBlock(''); + this.workspace.newBlock(''); + blockA.dispose(); + chai.assert.equal(this.workspace.getTopBlocks(false).length, 1); + }); + + test('Flat workspace two blocks', function() { + this.workspace.newBlock(''); + this.workspace.newBlock(''); + chai.assert.equal(this.workspace.getTopBlocks(false).length, 2); + }); + + test('Clear empty workspace', function() { + this.workspace.clear(); + chai.assert.equal(this.workspace.getTopBlocks(false).length, 0); + }); + + test('Clear non-empty workspace', function() { + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.clear(); + chai.assert.equal(this.workspace.getTopBlocks(false).length, 0); + }); + }); + + suite('getAllBlocks', function() { + test('Empty workspace', function() { + chai.assert.equal(this.workspace.getAllBlocks(true).length, 0); + }); + + test('Flat workspace one block', function() { + this.workspace.newBlock(''); + chai.assert.equal(this.workspace.getAllBlocks(true).length, 1); + }); + + test('Flat workspace one block after dispose', function() { + var blockA = this.workspace.newBlock(''); + this.workspace.newBlock(''); + blockA.dispose(); + chai.assert.equal(this.workspace.getAllBlocks(true).length, 1); + }); + + test('Flat workspace two blocks', function() { + this.workspace.newBlock(''); + this.workspace.newBlock(''); + chai.assert.equal(this.workspace.getAllBlocks(true).length, 2); + }); + + test('Clear', function() { + this.workspace.clear(); + chai.assert.equal(this.workspace.getAllBlocks(true).length, 0, + 'Clear empty workspace'); + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.clear(); + chai.assert.equal(this.workspace.getAllBlocks(true).length, 0); + }); + }); + + suite('remainingCapacity', function() { + setup(function() { + this.workspace.newBlock(''); + this.workspace.newBlock(''); + }); + + test('No block limit', function() { + chai.assert.equal(this.workspace.remainingCapacity(), Infinity); + }); + + test('Under block limit', function() { + this.workspace.options.maxBlocks = 3; + chai.assert.equal(this.workspace.remainingCapacity(), 1); + this.workspace.options.maxBlocks = 4; + chai.assert.equal(this.workspace.remainingCapacity(), 2); + }); + + test('At block limit', function() { + this.workspace.options.maxBlocks = 2; + chai.assert.equal(this.workspace.remainingCapacity(), 0); + }); + + test('At block limit of 0 after clear', function() { + this.workspace.options.maxBlocks = 0; + this.workspace.clear(); + chai.assert.equal(this.workspace.remainingCapacity(), 0); + }); + + test('Over block limit', function() { + this.workspace.options.maxBlocks = 1; + chai.assert.equal(this.workspace.remainingCapacity(), -1); + }); + + test('Over block limit of 0', function() { + this.workspace.options.maxBlocks = 0; + chai.assert.equal(this.workspace.remainingCapacity(), -2); + }); + }); + + suite('remainingCapacityOfType', function() { + setup(function() { + this.workspace.newBlock('get_var_block'); + this.workspace.newBlock('get_var_block'); + this.workspace.options.maxInstances = {}; + }); + + test('No instance limit', function() { + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + Infinity); + }); + + test('Under instance limit', function() { + this.workspace.options.maxInstances['get_var_block'] = 3; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + 1, 'With maxInstances limit 3'); + this.workspace.options.maxInstances['get_var_block'] = 4; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + 2, 'With maxInstances limit 4'); + }); + + test('Under instance limit with multiple block types', function() { + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.options.maxInstances['get_var_block'] = 3; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + 1, 'With maxInstances limit 3'); + this.workspace.options.maxInstances['get_var_block'] = 4; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + 2, 'With maxInstances limit 4'); + }); + + test('At instance limit', function() { + this.workspace.options.maxInstances['get_var_block'] = 2; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + 0, 'With maxInstances limit 2'); + }); + + test.skip('At instance limit of 0 after clear', function() { + // TODO(3837): Un-skip test after resolving. + this.workspace.clear(); + this.workspace.options.maxInstances['get_var_block'] = 0; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + 0); + }); + + test('At instance limit with multiple block types', function() { + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.options.maxInstances['get_var_block'] = 2; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + 0, 'With maxInstances limit 2'); + }); + + test.skip('At instance limit of 0 with multiple block types', function() { + // TODO(3837): Un-skip test after resolving. + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.options.maxInstances['get_var_block'] = 0; + this.workspace.clear(); + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + 0); + }); + + test('Over instance limit', function() { + this.workspace.options.maxInstances['get_var_block'] = 1; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + -1,'With maxInstances limit 1'); + }); + + test.skip('Over instance limit of 0', function() { + // TODO(3837): Un-skip test after resolving. + this.workspace.options.maxInstances['get_var_block'] = 0; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + -2,'With maxInstances limit 0'); + }); + + test('Over instance limit with multiple block types', function() { + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.options.maxInstances['get_var_block'] = 1; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + -1,'With maxInstances limit 1'); + }); + + test.skip('Over instance limit of 0 with multiple block types', function() { + // TODO(3837): Un-skip test after resolving. + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.newBlock(''); + this.workspace.options.maxInstances['get_var_block'] = 0; + chai.assert.equal(this.workspace.remainingCapacityOfType('get_var_block'), + -2,'With maxInstances limit 0'); + }); + + suite.skip('Max blocks and max instance interaction', function() { + // TODO(3836): Un-skip test suite after resolving. + test('Under block limit and no instance limit', function() { + this.workspace.options.maxBlocks = 3; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), 1); + }); + + test('At block limit and no instance limit', function() { + this.workspace.options.maxBlocks = 2; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), 0); + }); + + test.skip('Over block limit of 0 and no instance limit', function() { + // TODO(3837|3836): Un-skip test after resolving both. + this.workspace.options.maxBlocks = 0; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), -2); + }); + + test('Over block limit but under instance limit', function() { + this.workspace.options.maxBlocks = 1; + this.workspace.options.maxInstances['get_var_block'] = 3; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), + -2, + 'With maxBlocks limit 1 and maxInstances limit 3'); + }); + + test.skip('Over block limit of 0 but under instance limit', function() { + // TODO(3837|3836): Un-skip test after resolving both. + this.workspace.options.maxBlocks = 0; + this.workspace.options.maxInstances['get_var_block'] = 3; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), + -2, + 'With maxBlocks limit 0 and maxInstances limit 3'); + }); + + test('Over block limit but at instance limit', function() { + this.workspace.options.maxBlocks = 1; + this.workspace.options.maxInstances['get_var_block'] = 2; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), + -2, + 'With maxBlocks limit 1 and maxInstances limit 2'); + }); + + test('Over block limit and over instance limit', function() { + this.workspace.options.maxBlocks = 1; + this.workspace.options.maxInstances['get_var_block'] = 1; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), + -1, + 'With maxBlocks limit 1 and maxInstances limit 1'); + }); + + test.skip('Over block limit of 0 and over instance limit', function() { + // TODO(3837|3836): Un-skip test after resolving both. + this.workspace.options.maxBlocks = 0; + this.workspace.options.maxInstances['get_var_block'] = 1; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), + -2, + 'With maxBlocks limit 0 and maxInstances limit 1'); + }); + + test('Over block limit and over instance limit of 0', function() { + this.workspace.options.maxBlocks = 1; + this.workspace.options.maxInstances['get_var_block'] = 0; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'), + -1, + 'With maxBlocks limit 1 and maxInstances limit 0'); + }); + + test.skip('Over block limit of 0 and over instance limit of 0', function() { + // TODO(3837|3836): Un-skip test after resolving both. + this.workspace.options.maxBlocks = 0; + this.workspace.options.maxInstances['get_var_block'] = 0; + chai.assert.equal( + this.workspace.remainingCapacityOfType('get_var_block'),-1); + }); + }); + }); + +}); From 781dbd974d2e709144f7ee03c7c9c6e6752dc87c Mon Sep 17 00:00:00 2001 From: Maribeth Bottorff Date: Fri, 17 Apr 2020 17:47:58 -0700 Subject: [PATCH 033/139] Make block.removeInput return a boolean. (#3832) Make block.removeInput return a boolean. --- core/block.js | 7 +++++-- core/block_svg.js | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/core/block.js b/core/block.js index 6ea9dcc42..1bbd06dbe 100644 --- a/core/block.js +++ b/core/block.js @@ -1727,6 +1727,7 @@ Blockly.Block.prototype.moveNumberedInputBefore = function( * Remove an input from this block. * @param {string} name The name of the input. * @param {boolean=} opt_quiet True to prevent error if input is not present. + * @return {boolean} True if operation succeeds, false if input is not present and opt_quiet is true * @throws {Error} if the input is not present and opt_quiet is not true. */ Blockly.Block.prototype.removeInput = function(name, opt_quiet) { @@ -1737,10 +1738,12 @@ Blockly.Block.prototype.removeInput = function(name, opt_quiet) { } input.dispose(); this.inputList.splice(i, 1); - return; + return true; } } - if (!opt_quiet) { + if (opt_quiet) { + return false; + } else { throw Error('Input not found: ' + name); } }; diff --git a/core/block_svg.js b/core/block_svg.js index 83af1db30..f359aeda3 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -1390,17 +1390,20 @@ Blockly.BlockSvg.prototype.setInputsInline = function(newBoolean) { * Remove an input from this block. * @param {string} name The name of the input. * @param {boolean=} opt_quiet True to prevent error if input is not present. + * @return {boolean} True if operation succeeds, false if input is not present and opt_quiet is true * @throws {Error} if the input is not present and * opt_quiet is not true. */ Blockly.BlockSvg.prototype.removeInput = function(name, opt_quiet) { - Blockly.BlockSvg.superClass_.removeInput.call(this, name, opt_quiet); + var removed = Blockly.BlockSvg.superClass_.removeInput.call(this, name, opt_quiet); if (this.rendered) { this.render(); // Removing an input will cause the block to change shape. this.bumpNeighbours(); } + + return removed; }; /** From 7c3fbad360ea0e8747b6affb3dc1f2390638734a Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 20 Apr 2020 16:50:02 +0200 Subject: [PATCH 034/139] Localisation updates from https://translatewiki.net. --- msg/json/he.json | 1 + msg/json/kab.json | 96 +++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/msg/json/he.json b/msg/json/he.json index 5f7e8077d..38b0c96a2 100644 --- a/msg/json/he.json +++ b/msg/json/he.json @@ -100,6 +100,7 @@ "IOS_ERROR": "שגיאה", "IOS_PROCEDURES_INPUTS": "קלטים", "IOS_PROCEDURES_ADD_INPUT": "+ הוספת קלט", + "IOS_PROCEDURES_ALLOW_STATEMENTS": "לאפשר פעולות", "IOS_PROCEDURES_DUPLICATE_INPUTS_ERROR": "לפונקציה יש קלטים כפולים.", "IOS_VARIABLES_ADD_VARIABLE": "+ הוספת משתנה", "IOS_VARIABLES_ADD_BUTTON": "הוספה", diff --git a/msg/json/kab.json b/msg/json/kab.json index 5736bd468..bd6442011 100644 --- a/msg/json/kab.json +++ b/msg/json/kab.json @@ -77,8 +77,8 @@ "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Zgel ayen i d-yeqqimen di tneddict-a, sakin kemmel allus d-itteddun.", "CONTROLS_FLOW_STATEMENTS_WARNING": "Ɣur-k: Iḥder-a yessefk ad yettwaseqdec di tneddict.", "CONTROLS_IF_TOOLTIP_1": "mayella azal d idetti, ihi selkem kra n tinaḍin.", - "CONTROLS_IF_TOOLTIP_2": "Ma yella zal d idetti, selkem iḥder amezwaru. Neɣ ma ulac, selkem iḥder wis sin.", - "CONTROLS_IF_TOOLTIP_3": "Ma yella azal amezwaru d idetti, selkem iḥder amezwaru. Neɣ ma azal wis sin d ucciḍ, selkem iḥ€der wis sin.", + "CONTROLS_IF_TOOLTIP_2": "Mayella azal d idetti, selkem iḥder amezwaru. Neɣ ma ulac, selkem iḥder wis sin.", + "CONTROLS_IF_TOOLTIP_3": "Mayella azal amezwaru d idetti, selkem iḥder amezwaru. Neɣ ma azal wis sin d ucciḍ, selkem iḥder wis sin.", "CONTROLS_IF_TOOLTIP_4": "Mayella azal amezwaru d idetti, selkem iḥder amezwaru. Neɣ, mayella azal wis sin d idetti, selkem iḥder wis sin. Mayella ula d yiwen seg-sen ur yelli d idetti, selkem iḥder aneggaru.", "CONTROLS_IF_MSG_IF": "ma", "CONTROLS_IF_MSG_ELSEIF": "neɣ ma", @@ -165,7 +165,7 @@ "MATH_ROUND_OPERATOR_ROUNDUP": "Saẓ d asawen", "MATH_ROUND_OPERATOR_ROUNDDOWN": "Saẓ d akesser", "MATH_ONLIST_OPERATOR_SUM": "Timernit n tebdart", - "MATH_ONLIST_TOOLTIP_SUM": "Ad d-yerr timernit n imḍanen meṛṛa deg tebdart.", + "MATH_ONLIST_TOOLTIP_SUM": "Ad d-yerr timernit n yimḍanen meṛṛa deg tebdart.", "MATH_ONLIST_OPERATOR_MIN": "adday n tebdart", "MATH_ONLIST_TOOLTIP_MIN": "Ad d-yerr amḍan ameẓẓyan di tebdart.", "MATH_ONLIST_OPERATOR_MAX": "afellay n tebdart", @@ -173,18 +173,18 @@ "MATH_ONLIST_OPERATOR_AVERAGE": "talemmast n tebdart", "MATH_ONLIST_TOOLTIP_AVERAGE": "Ad d-yerr talemmas( tasnamḍant) n wazalen umḍinen di tebdart.", "MATH_ONLIST_OPERATOR_MEDIAN": "tanammast n tebdart", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Ad d-yerr amḍan n anammas n tebdart.", - "MATH_ONLIST_OPERATOR_MODE": "Tigwtiwin n tebdart", - "MATH_ONLIST_TOOLTIP_MODE": "Ad d-yerr tabdart n iferdisen i d-yettuɣalen s waṭas di tebdart.", + "MATH_ONLIST_TOOLTIP_MEDIAN": "Ad d-yerr amḍan n unammas n tebdart.", + "MATH_ONLIST_OPERATOR_MODE": "Tiggtiwin n tebdart", + "MATH_ONLIST_TOOLTIP_MODE": "Ad d-yerr tabdart n yiferdisen i d-yettuɣalen s waṭas di tebdart.", "MATH_ONLIST_OPERATOR_STD_DEV": "azza n tebdart", "MATH_ONLIST_TOOLTIP_STD_DEV": "Ad d-yerr azza n tebdart.", "MATH_ONLIST_OPERATOR_RANDOM": "aferdis agacuran n tebdart", "MATH_ONLIST_TOOLTIP_RANDOM": "Ad d-yerr aferdis seg tebdart s wudem agacuran.", "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", "MATH_MODULO_TITLE": "tasagert n %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Ad d-yerr tasagert n beṭṭu n sin n imḍanen.", + "MATH_MODULO_TOOLTIP": "Ad d-yerr tasagert n beṭṭu n sin n yimḍanen.", "MATH_CONSTRAIN_TITLE": "Err tamara i %1 gar %2 akked %3", - "MATH_CONSTRAIN_TOOLTIP": "Err tamara n umiḍan akken ad yili gar snat n tlisa (ddant).", + "MATH_CONSTRAIN_TOOLTIP": "Err tamara n umḍan akken ad yili gar snat n tlisa (ddant).", "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", "MATH_RANDOM_INT_TITLE": "ummid agacuran gar %1 akked %2", "MATH_RANDOM_INT_TOOLTIP": "Ad d-yerr ummid agacuran gar snat n tlisa, ddant.", @@ -196,44 +196,44 @@ "MATH_ATAN2_TOOLTIP": "Ad d-yerr arctangent n waggaz (X, Y) s tfesniwin deg -180 ɣer 180.", "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", "TEXT_TEXT_TOOLTIP": "Asekkil, awal neɣ izirig n uḍris.", - "TEXT_JOIN_TITLE_CREATEWITH": "rnu aḍṛis s", - "TEXT_JOIN_TOOLTIP": "Ad yernu taceqquft n uḍris s usdukel gar yal amḍan n iferdisen.", + "TEXT_JOIN_TITLE_CREATEWITH": "rnu aḍris s", + "TEXT_JOIN_TOOLTIP": "Ad yernu taceqquft n uḍris s usdukel gar yal amḍan n yiferdisen.", "TEXT_CREATE_JOIN_TITLE_JOIN": "sdukkel", - "TEXT_CREATE_JOIN_TOOLTIP": "Rnu, kkes, neɣ ales asmizzwer n tgezmiyin akken ad talseḍ tawila n iḥder-agi.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Rnu aferdis ar uḍris.", - "TEXT_APPEND_TITLE": "Rnu aḍris %2 ar %1", - "TEXT_APPEND_TOOLTIP": "Rnu aḍris ar umutti '%1'.", + "TEXT_CREATE_JOIN_TOOLTIP": "Rnu, kkes, neɣ ales asmizzwer n tgezmiyin akken ad talseḍ tawila n yiḥder-a.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Rnu aferdis ɣer uḍris.", + "TEXT_APPEND_TITLE": "Rnu aḍris %2 ɣer %1", + "TEXT_APPEND_TOOLTIP": "Rnu aḍris ɣer umutti '%1'.", "TEXT_LENGTH_TITLE": "teɣzi n %1", - "TEXT_LENGTH_TOOLTIP": "Ad d-yerr amḍan n isekkilen (ddab ula d imellalen) deg uḍris d-ittunefken.", + "TEXT_LENGTH_TOOLTIP": "Ad d-yerr amḍan n yisekkilen (ddan ula d imellalen) deg uḍris d-ittunefken.", "TEXT_ISEMPTY_TITLE": "%1 d ilem", "TEXT_ISEMPTY_TOOLTIP": "Add d-yerr idetti ma yella aḍris d ilem.", - "TEXT_INDEXOF_TOOLTIP": "Ad d-yerr amatar n tmeḍriwt tamezwarut/taneggarut n uḍris amewaru deg uḍris wis sin. Ad d-yerr %1 ma yella ulac adris.", + "TEXT_INDEXOF_TOOLTIP": "Ad d-yerr amatar n tmeḍriwt tamezwarut/taneggarut n uḍris amezwaru deg uḍris wis sin. Ad d-yerr %1 ma yella ulac aḍris.", "TEXT_INDEXOF_TITLE": "deg uḍris %1 %2 %3", "TEXT_INDEXOF_OPERATOR_FIRST": "af-d timeḍriwt tamezwarut n uḍris", "TEXT_INDEXOF_OPERATOR_LAST": "af-d timeḍriwt taneggarut deg uḍris", "TEXT_CHARAT_TITLE": "deg uḍris %1 %2", "TEXT_CHARAT_FROM_START": "awi asekkel #", - "TEXT_CHARAT_FROM_END": "awi-d asekkil # si tagara", + "TEXT_CHARAT_FROM_END": "awi-d asekkil # si taggara", "TEXT_CHARAT_FIRST": "awi-d asekkil amezwaru", "TEXT_CHARAT_LAST": "awi-d asekkil aneggaru", "TEXT_CHARAT_RANDOM": "awi-d asekkil s wudem agacuran", - "TEXT_CHARAT_TOOLTIP": "Ad d-yerr asekkil deg wuṭṭun yettwammlen.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Ad d-yerr aḥric yettwammlen deg uḍris.", + "TEXT_CHARAT_TOOLTIP": "Ad d-yerr asekkil deg wuṭṭun yettwamlen.", + "TEXT_GET_SUBSTRING_TOOLTIP": "Ad d-yerr aḥric yettwamlen deg uḍris.", "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "deg uḍris", "TEXT_GET_SUBSTRING_START_FROM_START": "awi-d azrir asnawan seg usekkil #", - "TEXT_GET_SUBSTRING_START_FROM_END": "awi-d azrir asnawan seg usekkil # si tagara", + "TEXT_GET_SUBSTRING_START_FROM_END": "awi-d azrir asnawan seg usekkil # si taggara", "TEXT_GET_SUBSTRING_START_FIRST": "awi-d azrir asnawan seg usekkil amezwaru", - "TEXT_GET_SUBSTRING_END_FROM_START": "arama d asekkil #", - "TEXT_GET_SUBSTRING_END_FROM_END": "arama d asekkil # si tagara", - "TEXT_GET_SUBSTRING_END_LAST": "arama d asekkil aneggaru", + "TEXT_GET_SUBSTRING_END_FROM_START": "armi d asekkil #", + "TEXT_GET_SUBSTRING_END_FROM_END": "armi d asekkil # si taggara", + "TEXT_GET_SUBSTRING_END_LAST": "armi d asekkil aneggaru", "TEXT_CHANGECASE_TOOLTIP": "Ad d-yerr anɣel n uḍris s truẓi-nniḍen.", "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "s USEKKIL AMEQQRAN", "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "s usekkil ameẓẓyan", "TEXT_CHANGECASE_OPERATOR_TITLECASE": "s Umeqqran Di Tazwara n Yal Awal.", - "TEXT_TRIM_TOOLTIP": "Ad d-yerr anɣel n uḍris s isekkilen ilmawen yettwakksen seg ixf neɣ i sin.", - "TEXT_TRIM_OPERATOR_BOTH": "Tukksa n isekkilen imellalen seg sin n idisan", - "TEXT_TRIM_OPERATOR_LEFT": "tukksa n isekkilen seg uzelmaḍ", - "TEXT_TRIM_OPERATOR_RIGHT": "tukksa n isekkilen seg uyeffus", + "TEXT_TRIM_TOOLTIP": "Ad d-yerr anɣel n uḍris s yisekkilen ilmawen yettwakksen seg yixf neɣ i sin.", + "TEXT_TRIM_OPERATOR_BOTH": "Tukksa n yisekkilen imellalen seg sin n yidisan", + "TEXT_TRIM_OPERATOR_LEFT": "tukksa n yisekkilen seg uzelmaḍ", + "TEXT_TRIM_OPERATOR_RIGHT": "tukksa n yisekkilen seg uyeffus", "TEXT_PRINT_TITLE": "ad d-yesken %1", "TEXT_PRINT_TOOLTIP": "Sken aḍris, amḍan neɣ azal-nniḍen d-ittunefken.", "TEXT_PROMPT_TYPE_TEXT": "aneftaɣ i uḍris s yizen", @@ -241,62 +241,62 @@ "TEXT_PROMPT_TOOLTIP_NUMBER": "Suter amḍan i useqdac.", "TEXT_PROMPT_TOOLTIP_TEXT": "Suter aḍris i useqdac.", "TEXT_COUNT_MESSAGE0": "amḍan %1 ɣef %2", - "TEXT_COUNT_TOOLTIP": "Ad isiḍen amḍan n tmeḍriwt n uḍris deg ayeḍ.", + "TEXT_COUNT_TOOLTIP": "Ad isiḍen amḍan n tmeḍriwt n uḍris deg wayeḍ.", "TEXT_REPLACE_MESSAGE0": "semselsi %1 s %2 di %3", - "TEXT_REPLACE_TOOLTIP": "As isemselsi akk timeḍriwin n uḍris s wayeḍ.", + "TEXT_REPLACE_TOOLTIP": "Ad isemselsi akk timeḍriwin n uḍris s wayeḍ.", "TEXT_REVERSE_MESSAGE0": "tti %1", - "TEXT_REVERSE_TOOLTIP": "Ad yetti asmizzwer n isekkilen deg uḍris.", + "TEXT_REVERSE_TOOLTIP": "Ad yetti asmizzwer n yisekkilen deg uḍris.", "LISTS_CREATE_EMPTY_TITLE": "rnu tabdart tilemt", "LISTS_CREATE_EMPTY_TOOLTIP": "Ad d-yerr tabdart n teɣzi 0 ur yegbiren ara ikalasen", - "LISTS_CREATE_WITH_TOOLTIP": "Ad yernu tabdart s umḍan n iferdisen.", + "LISTS_CREATE_WITH_TOOLTIP": "Ad yernu tabdart s umḍan n yiferdisen.", "LISTS_CREATE_WITH_INPUT_WITH": "rnu tabdart s", "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "tabdart", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Rnu, kkes, neɣ ales asmizzwer n tgezmiyin akken ad talseḍ tawila n iḥder-agi n tebdart.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Ad yernu aferdis ar tebdart.", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Rnu, kkes, neɣ ales asmizzwer n tgezmiyin akken ad talseḍ tawila n yiḥder-a n tebdart.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Ad yernu aferdis ɣer tebdart.", "LISTS_REPEAT_TOOLTIP": "Ad yernu tabdart inetmen n wazal yettunefken ddeqs n tikal s umḍan yettwammlen.", "LISTS_REPEAT_TITLE": "ad yernu tabdart s uferdis %1 s tmeḍriwt %2", "LISTS_LENGTH_TITLE": "teɣzi n %1", "LISTS_LENGTH_TOOLTIP": "Ad d-yerr teɣzi n tebdart.", "LISTS_ISEMPTY_TITLE": "%1 d ilem", - "LISTS_ISEMPTY_TOOLTIP": "Ad d-yerr idetti ma yella tabdart d tilemt.", + "LISTS_ISEMPTY_TOOLTIP": "Ad d-yerr idetti mayella tabdart d tilemt.", "LISTS_INLIST": "di tebdart", - "LISTS_INDEX_OF_FIRST": "aff-d timeḍriwt tamezwarut n uferdis", + "LISTS_INDEX_OF_FIRST": "af-d timeḍriwt tamezwarut n uferdis", "LISTS_INDEX_OF_LAST": "af-d timeḍriwt taneggarut n uferdis", - "LISTS_INDEX_OF_TOOLTIP": "Ad d-yerr amatar n tmeḍriwt tamezwarut/taneggarut n uferdis amewaru deg tebdart. Ad d-yerr %1 ma yella ulac aferdis.", + "LISTS_INDEX_OF_TOOLTIP": "Ad d-yerr amatar n tmeḍriwt tamezwarut/taneggarut n uferdis amezwaru deg tebdart. Ad d-yerr %1 ma yella ulac aferdis.", "LISTS_GET_INDEX_GET": "awi", - "LISTS_GET_INDEX_GET_REMOVE": "awi u kkes", + "LISTS_GET_INDEX_GET_REMOVE": "awi rnu kkes", "LISTS_GET_INDEX_REMOVE": "kkes", - "LISTS_GET_INDEX_FROM_END": "# si tagara", + "LISTS_GET_INDEX_FROM_END": "# si taggara", "LISTS_GET_INDEX_FIRST": "amezwaru", "LISTS_GET_INDEX_LAST": "aneggaru", "LISTS_GET_INDEX_RANDOM": "agacuran", "LISTS_INDEX_FROM_START_TOOLTIP": "%1 d aferdis amezwaru.", "LISTS_INDEX_FROM_END_TOOLTIP": "%1 d aferdis aneggaru.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Ad d-yerr aferdis n wadig yettwammlen deg tabdart.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Ad d-yerr aferdis amezwaru n tebdart..", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Ad d-yerr aferdis n wadig yettwamlen deg tabdart.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Ad d-yerr aferdis amezwaru n tebdart.", "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Ad d-yerr aferdis aneggaru di tebdart.", "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Ad yerr aferdis agacuran di tebdart.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Ad yekkes sakin ad d-yerr aferdis n wadig yettwammlen deg tabdart.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Ad yekkes syin ad d-yerr aferdis n wadig yettwamlen deg tabdart.", "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Ad yekkes sakin ad -yerr aferdis amezwaru di tebdart.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Ad yekkes sakin ad -yerr aferdis aneggaru di tebdart.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Ad yekkes sakin ad yerr aferdis aneggaru di tebdart.", "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Ad yekkes sakin ad d-yerr aferdis agacuran di tebdart.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Ad yekkes aferdis n wadig yettwammlen deg tabdart.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Ad yekkes aferdis amezwaru n tebdart..", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Ad yekkes aferdis n wadig yettwamlen deg tabdart.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Ad yekkes aferdis amezwaru n tebdart.", "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Ad yekkes aferdis aneggaru di tebdart.", "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Ad yekkes aferdis agacuran di tebdart.", "LISTS_SET_INDEX_SET": "sbadu", "LISTS_SET_INDEX_INSERT": "ger s", "LISTS_SET_INDEX_INPUT_TO": "am", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Ad yesbadu aferdis n wadig yettwammlen deg tabdart.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Ad yesbadu aferdis n wadig yettwamlen deg tabdart.", "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Ad d-yerr aferdis amezwaru di tebdart.", "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Ad d-yerr aferdis aneggaru di tebdart.", "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Ad yesbadu aferdis agacuran di tebdart.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Ad iger aferdis n wadig yettwammlen deg tabdart.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Ad iger aferdis n wadig yettwamlen deg tabdart.", "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Ad iger aferdis di tazwara n tebdart.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Ad yernu aferdis ar tagara n tebdart.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Ad yernu aferdis ar taggara n tebdart.", "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Ad iger aferdis s wudem agacuran deg tebdart.", "LISTS_GET_SUBLIST_START_FROM_START": "awi-d tabdart tasnawant seg #", - "LISTS_GET_SUBLIST_START_FROM_END": "awi-d tabdart tasnawant seg # si tagara", + "LISTS_GET_SUBLIST_START_FROM_END": "awi-d tabdart tasnawant seg # si taggara", "LISTS_GET_SUBLIST_START_FIRST": "awi-d tabdart tasnawant si tazwara", "LISTS_GET_SUBLIST_END_FROM_START": "ar #", "LISTS_GET_SUBLIST_END_FROM_END": "ar # si tagara", From 9513473c7438178329cf7f80beec870139928a5f Mon Sep 17 00:00:00 2001 From: alschmiedt Date: Mon, 20 Apr 2020 11:25:35 -0700 Subject: [PATCH 035/139] Make variable method public (#3840) * Make nameUsedWithAnyType public --- core/variables.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/variables.js b/core/variables.js index 271439a60..b1199fa4e 100644 --- a/core/variables.js +++ b/core/variables.js @@ -279,7 +279,7 @@ Blockly.Variables.createVariableButtonHandler = function( function(text) { if (text) { var existing = - Blockly.Variables.nameUsedWithAnyType_(text, workspace); + Blockly.Variables.nameUsedWithAnyType(text, workspace); if (existing) { if (existing.type == type) { var msg = Blockly.Msg['VARIABLE_ALREADY_EXISTS'].replace( @@ -424,9 +424,8 @@ Blockly.Variables.nameUsedWithOtherType_ = function(name, type, workspace) { * variable. * @return {Blockly.VariableModel} The variable with the given name, * or null if none was found. - * @private */ -Blockly.Variables.nameUsedWithAnyType_ = function(name, workspace) { +Blockly.Variables.nameUsedWithAnyType = function(name, workspace) { var allVariables = workspace.getVariableMap().getAllVariables(); name = name.toLowerCase(); From bb3b20443b93da756a45935e7f548f4958f6c5c7 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Mon, 20 Apr 2020 16:52:56 -0700 Subject: [PATCH 036/139] Convert remaining tests in workspace_test. (#3841) --- tests/jsunit/index.html | 1 - tests/jsunit/workspace_test.js | 301 ---------------------------- tests/mocha/workspace_test.js | 350 +++++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+), 302 deletions(-) delete mode 100644 tests/jsunit/workspace_test.js diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index 06c81a014..bf3cf3aba 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -22,7 +22,6 @@ - diff --git a/tests/jsunit/workspace_test.js b/tests/jsunit/workspace_test.js deleted file mode 100644 index 985da6a37..000000000 --- a/tests/jsunit/workspace_test.js +++ /dev/null @@ -1,301 +0,0 @@ -/** - * @license - * Copyright 2012 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - - -var workspace; -var mockControl_; - -function workspaceTest_setUp() { - defineGetVarBlock(); - workspace = new Blockly.Workspace(); -} - -function workspaceTest_tearDown() { - undefineGetVarBlock(); - if (mockControl_) { - mockControl_.restore(); - } - workspace.dispose(); -} - -function test_getWorkspaceById() { - var workspaceA = new Blockly.Workspace(); - var workspaceB = new Blockly.Workspace(); - try { - assertEquals('Find workspaceA.', workspaceA, - Blockly.Workspace.getById(workspaceA.id)); - assertEquals('Find workspaceB.', workspaceB, - Blockly.Workspace.getById(workspaceB.id)); - assertEquals('No workspace found.', null, - Blockly.Workspace.getById('I do not exist.')); - workspaceA.dispose(); - assertEquals('Can\'t find workspaceA.', null, - Blockly.Workspace.getById(workspaceA.id)); - assertEquals('WorkspaceB exists.', workspaceB, - Blockly.Workspace.getById(workspaceB.id)); - } finally { - workspaceB.dispose(); - workspaceA.dispose(); - } -} - -function test_getBlockById() { - workspaceTest_setUp(); - try { - var blockA = workspace.newBlock(''); - var blockB = workspace.newBlock(''); - assertEquals('Find blockA.', blockA, workspace.getBlockById(blockA.id)); - assertEquals('Find blockB.', blockB, workspace.getBlockById(blockB.id)); - assertEquals('No block found.', null, - workspace.getBlockById('I do not exist.')); - blockA.dispose(); - assertEquals('Can\'t find blockA.', null, workspace.getBlockById(blockA.id)); - assertEquals('BlockB exists.', blockB, workspace.getBlockById(blockB.id)); - workspace.clear(); - assertEquals('Can\'t find blockB.', null, workspace.getBlockById(blockB.id)); - } finally { - workspaceTest_tearDown(); - } -} - -function test_deleteVariable_InternalTrivial() { - workspaceTest_setUp(); - var var_1 = workspace.createVariable('name1', 'type1', 'id1'); - workspace.createVariable('name2', 'type2', 'id2'); - createMockVarBlock(workspace, 'id1'); - createMockVarBlock(workspace, 'id1'); - createMockVarBlock(workspace, 'id2'); - - var uses = workspace.getVariableUsesById(var_1.getId()); - workspace.deleteVariableInternal_(var_1, uses); - - var variable = workspace.getVariableById('id1'); - var block_var_name = workspace.topBlocks_[0].getVarModels()[0].name; - assertNull(variable); - checkVariableValues(workspace, 'name2', 'type2', 'id2'); - assertEquals('name2', block_var_name); - workspaceTest_tearDown(); -} - -// TODO(marisaleung): Test the alert for deleting a variable that is a procedure. - -function test_addTopBlock_TrivialFlyoutIsTrue() { - workspaceTest_setUp(); - var targetWorkspace = new Blockly.Workspace(); - workspace.isFlyout = true; - workspace.targetWorkspace = targetWorkspace; - targetWorkspace.createVariable('name1', '', '1'); - - // Flyout.init usually does this binding. - workspace.variableMap_ = targetWorkspace.getVariableMap(); - - try { - var block = createMockVarBlock(workspace, '1'); - workspace.removeTopBlock(block); - workspace.addTopBlock(block); - checkVariableValues(workspace, 'name1', '', '1'); - } finally { - workspaceTest_tearDown(); - // Have to dispose of the main workspace after the flyout workspace, because - // it holds the variable map. - // Normally the main workspace disposes of the flyout workspace. - targetWorkspace.dispose(); - } -} - -function test_clear_Trivial() { - workspaceTest_setUp(); - workspace.createVariable('name1', 'type1', 'id1'); - workspace.createVariable('name2', 'type2', 'id2'); - mockControl_ = setUpMockMethod(Blockly.Events, 'setGroup', [true, false], - null); - - try { - workspace.clear(); - var topBlocks_length = workspace.topBlocks_.length; - var varMapLength = Object.keys(workspace.variableMap_.variableMap_).length; - assertEquals(0, topBlocks_length); - assertEquals(0, varMapLength); - } finally { - workspaceTest_tearDown(); - } -} - -function test_clear_NoVariables() { - workspaceTest_setUp(); - mockControl_ = setUpMockMethod(Blockly.Events, 'setGroup', [true, false], - null); - - try { - workspace.clear(); - var topBlocks_length = workspace.topBlocks_.length; - var varMapLength = Object.keys(workspace.variableMap_.variableMap_).length; - assertEquals(0, topBlocks_length); - assertEquals(0, varMapLength); - } finally { - workspaceTest_tearDown(); - } -} - -function test_renameVariable_NoReference() { - // Test renaming a variable in the simplest case: when no blocks refer to it. - workspaceTest_setUp(); - var id = 'id1'; - var type = 'type1'; - var oldName = 'name1'; - var newName = 'name2'; - workspace.createVariable(oldName, type, id); - - try { - workspace.renameVariableById(id, newName); - checkVariableValues(workspace, newName, type, id); - // Renaming should not have created a new variable. - assertEquals(1, workspace.getAllVariables().length); - } finally { - workspaceTest_tearDown(); - } -} - -function test_renameVariable_ReferenceExists() { - // Test renaming a variable when a reference to it exists. - // Expect 'renameVariable' to change oldName variable name to newName. - workspaceTest_setUp(); - var newName = 'name2'; - - createVariableAndBlock(workspace); - - workspace.renameVariableById('id1', newName); - checkVariableValues(workspace, newName, 'type1', 'id1'); - // Renaming should not have created a new variable. - assertEquals(1, workspace.getAllVariables().length); - var block_var_name = workspace.topBlocks_[0].getVarModels()[0].name; - assertEquals(newName, block_var_name); - workspaceTest_tearDown(); -} - -function test_renameVariable_TwoVariablesSameType() { - // Expect 'renameVariable' to change oldName variable name to newName. - // Expect oldName block name to change to newName - workspaceTest_setUp(); - var id1 = 'id1'; - var id2 = 'id2'; - var type = 'type1'; - - var oldName = 'name1'; - var newName = 'name2'; - // Create two variables of the same type. - workspace.createVariable(oldName, type, id1); - workspace.createVariable(newName, type, id2); - // Create blocks to refer to both of them. - createMockVarBlock(workspace, id1); - createMockVarBlock(workspace, id2); - - workspace.renameVariableById(id1, newName); - checkVariableValues(workspace, newName, type, id2); - // The old variable should have been deleted. - var variable = workspace.getVariableById(id1); - assertNull(variable); - - // There should only be one variable left. - assertEquals(1, workspace.getAllVariables().length); - - // References should have the correct names. - var block_var_name_1 = workspace.topBlocks_[0].getVarModels()[0].name; - var block_var_name_2 = workspace.topBlocks_[1].getVarModels()[0].name; - assertEquals(newName, block_var_name_1); - assertEquals(newName, block_var_name_2); - - workspaceTest_tearDown(); -} - -function test_renameVariable_TwoVariablesDifferentType() { - // Expect the rename to succeed, because variables with different types are - // allowed to have the same name. - workspaceTest_setUp(); - createTwoVariablesAndBlocks(workspace); - - var newName = 'name2'; - workspace.renameVariableById('id1', newName); - - checkVariableValues(workspace, newName, 'type1', 'id1'); - checkVariableValues(workspace, newName, 'type2', 'id2'); - - // References shoul have the correct names. - var block_var_name_1 = workspace.topBlocks_[0].getVarModels()[0].name; - var block_var_name_2 = workspace.topBlocks_[1].getVarModels()[0].name; - assertEquals(newName, block_var_name_1); - assertEquals(newName, block_var_name_2); - - workspaceTest_tearDown(); -} - -function test_renameVariable_OldCase() { - // Rename a variable with a single reference. Update only the capitalization. - workspaceTest_setUp(); - var newName = 'Name1'; - - createVariableAndBlock(workspace); - - workspace.renameVariableById('id1', newName); - checkVariableValues(workspace, newName, 'type1', 'id1'); - var variable = workspace.getVariableById('id1'); - assertNotEquals('name1', variable.name); - workspaceTest_tearDown(); -} - -function test_renameVariable_TwoVariablesAndOldCase() { - // Test renaming a variable to an in-use name, but with different - // capitalization. The new capitalization should apply everywhere. - - // TODO (fenichel): What about different capitalization but also different - // types? - workspaceTest_setUp(); - var oldName = 'name1'; - var oldCase = 'Name2'; - var newName = 'name2'; - - var id1 = 'id1'; - var id2 = 'id2'; - - var type = 'type1'; - - workspace.createVariable(oldName, type, id1); - workspace.createVariable(oldCase, type, id2); - createMockVarBlock(workspace, id1); - createMockVarBlock(workspace, id2); - - workspace.renameVariableById(id1, newName); - - checkVariableValues(workspace, newName, type, id2); - - // The old variable should have been deleted. - var variable = workspace.getVariableById(id1); - assertNull(variable); - - // There should only be one variable left. - assertEquals(1, workspace.getAllVariables().length); - - // Blocks should now use the new capitalization. - var block_var_name_1 = workspace.topBlocks_[0].getVarModels()[0].name; - var block_var_name_2 = workspace.topBlocks_[1].getVarModels()[0].name; - assertEquals(newName, block_var_name_1); - assertEquals(newName, block_var_name_2); - workspaceTest_tearDown(); -} - -function test_deleteVariableById_Trivial() { - workspaceTest_setUp(); - createTwoVariablesAndBlocks(workspace); - - workspace.deleteVariableById('id1'); - checkVariableValues(workspace, 'name2', 'type2', 'id2'); - var variable = workspace.getVariableById('id1'); - var block_var_name = workspace.topBlocks_[0].getVarModels()[0].name; - assertNull(variable); - assertEquals('name2', block_var_name); - workspaceTest_tearDown(); -} diff --git a/tests/mocha/workspace_test.js b/tests/mocha/workspace_test.js index 42359bbfd..43066c830 100644 --- a/tests/mocha/workspace_test.js +++ b/tests/mocha/workspace_test.js @@ -23,6 +23,287 @@ suite('Workspace', function() { teardown(function() { delete Blockly.Blocks['get_var_block']; this.workspace.dispose(); + // Clear Blockly.Event state. + Blockly.Events.setGroup(false); + Blockly.Events.disabled_ = 0; + sinon.restore(); + }); + + suite('clear', function() { + test('Trivial', function() { + sinon.stub(Blockly.Events, "setGroup").returns(null); + this.workspace.createVariable('name1', 'type1', 'id1'); + this.workspace.createVariable('name2', 'type2', 'id2'); + this.workspace.newBlock(''); + + this.workspace.clear(); + chai.assert.equal(this.workspace.topBlocks_.length, 0); + var varMapLength = + Object.keys(this.workspace.variableMap_.variableMap_).length; + chai.assert.equal(varMapLength, 0); + }); + + test('No variables', function() { + sinon.stub(Blockly.Events, "setGroup").returns(null); + this.workspace.newBlock(''); + + this.workspace.clear(); + chai.assert.equal(this.workspace.topBlocks_.length, 0); + var varMapLength = + Object.keys(this.workspace.variableMap_.variableMap_).length; + chai.assert.equal(varMapLength, 0); + }); + }); + + suite('deleteVariable', function() { + setup(function() { + // Create two variables of different types. + this.var1 = this.workspace.createVariable('name1', 'type1', 'id1'); + this.var2 = this.workspace.createVariable('name2', 'type2', 'id2'); + // Create blocks to refer to both of them. + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id2'); + Blockly.Events.enable(); + }); + + test('deleteVariableInternal_', function() { + var uses = this.workspace.getVariableUsesById(this.var1.getId()); + this.workspace.deleteVariableInternal_(this.var1, uses); + + var variable = this.workspace.getVariableById('id1'); + chai.assert.isNull(variable); + var blockVarName = this.workspace.topBlocks_[0].getVarModels()[0].name; + assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); + chai.assert.equal(blockVarName, 'name2'); + }); + + test('deleteVariableById one usage', function() { + // Deleting variable one usage should not trigger confirm dialog. + var stub = + sinon.stub(Blockly, "confirm").callsArgWith(1, true); + this.workspace.deleteVariableById('id2'); + + sinon.assert.notCalled(stub); + var variable = this.workspace.getVariableById('id2'); + chai.assert.isNull(variable); + assertVariableValues(this.workspace, 'name1', 'type1', 'id1'); + var blockVarName = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVarName, 'name1'); + }); + + test('deleteVariableById multiple usages confirm', function() { + // Deleting variable with multiple usages triggers confirm dialog. + var stub = + sinon.stub(Blockly, "confirm").callsArgWith(1, true); + this.workspace.deleteVariableById('id1'); + + sinon.assert.calledOnce(stub); + var variable = this.workspace.getVariableById('id1'); + chai.assert.isNull(variable); + assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); + var blockVarName = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVarName, 'name2'); + }); + + test('deleteVariableById multiple usages cancel', function() { + // Deleting variable with multiple usages triggers confirm dialog. + var stub = + sinon.stub(Blockly, "confirm").callsArgWith(1, false); + this.workspace.deleteVariableById('id1'); + + sinon.assert.calledOnce(stub); + assertVariableValues(this.workspace, 'name1', 'type1', 'id1'); + assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); + var blockVarName1 = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVarName1, 'name1'); + var blockVarName2 = this.workspace.topBlocks_[1].getVarModels()[0].name; + chai.assert.equal(blockVarName2, 'name1'); + var blockVarName3 = this.workspace.topBlocks_[2].getVarModels()[0].name; + chai.assert.equal(blockVarName3, 'name2'); + }); + }); + + suite('renameVariable', function() { + setup(function() { + this.workspace.createVariable('name1', 'type1', 'id1'); + }); + test('No references', function() { + this.workspace.renameVariableById('id1', 'name2'); + assertVariableValues(this.workspace, 'name2', 'type1', 'id1'); + // Renaming should not have created a new variable. + chai.assert.equal(this.workspace.getAllVariables().length, 1); + }); + + test('Reference exists', function() { + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + Blockly.Events.enable(); + + this.workspace.renameVariableById('id1', 'name2'); + assertVariableValues(this.workspace, 'name2', 'type1', 'id1'); + // Renaming should not have created a new variable. + chai.assert.equal(this.workspace.getAllVariables().length, 1); + var blockVarName = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVarName, 'name2'); + }); + + test('Reference exists different capitalizations', function() { + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + Blockly.Events.enable(); + + this.workspace.renameVariableById('id1', 'Name1'); + assertVariableValues(this.workspace, 'Name1', 'type1', 'id1'); + // Renaming should not have created a new variable. + chai.assert.equal(this.workspace.getAllVariables().length, 1); + var blockVarName = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVarName, 'Name1'); + }); + + suite('Two variables rename overlap', function() { + test('Same type', function() { + this.workspace.createVariable('name2', 'type1', 'id2'); + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id2'); + Blockly.Events.enable(); + + this.workspace.renameVariableById('id1', 'name2'); + + // The second variable should remain unchanged. + assertVariableValues(this.workspace, 'name2', 'type1', 'id2'); + // The first variable should have been deleted. + var variable = this.workspace.getVariableById('id1'); + chai.assert.isNull(variable); + // There should only be one variable left. + chai.assert.equal(this.workspace.getAllVariables().length, 1); + + // Both blocks should now reference variable with name2. + var blockVar1 = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVar1, 'name2'); + var blockVar2 = this.workspace.topBlocks_[1].getVarModels()[0].name; + chai.assert.equal(blockVar2, 'name2'); + }); + + test('Different type', function() { + this.workspace.createVariable('name2', 'type2', 'id2'); + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id2'); + Blockly.Events.enable(); + + this.workspace.renameVariableById('id1', 'name2'); + + // Variables with different type are allowed to have the same name. + assertVariableValues(this.workspace, 'name2', 'type1', 'id1'); + assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); + + // Both blocks should now reference variable with name2. + var blockVar1 = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVar1, 'name2'); + var blockVar2 = this.workspace.topBlocks_[1].getVarModels()[0].name; + chai.assert.equal(blockVar2, 'name2'); + }); + + test('Same type different capitalization', function() { + this.workspace.createVariable('name2', 'type1', 'id2'); + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id2'); + Blockly.Events.enable(); + + this.workspace.renameVariableById('id1', 'Name2'); + + // The second variable should be updated. + assertVariableValues(this.workspace, 'Name2', 'type1', 'id2'); + // The first variable should have been deleted. + var variable = this.workspace.getVariableById('id1'); + chai.assert.isNull(variable); + // There should only be one variable left. + chai.assert.equal(this.workspace.getAllVariables().length, 1); + + // Both blocks should now reference variable with Name2. + var blockVar1 = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVar1, 'Name2'); + var blockVar2 = this.workspace.topBlocks_[1].getVarModels()[0].name; + chai.assert.equal(blockVar2, 'Name2'); + }); + + test('Different type different capitalization', function() { + this.workspace.createVariable('name2', 'type2', 'id2'); + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id1'); + block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('id2'); + Blockly.Events.enable(); + + this.workspace.renameVariableById('id1', 'Name2'); + + // Variables with different type are allowed to have the same name. + assertVariableValues(this.workspace, 'Name2', 'type1', 'id1'); + // Second variable should remain unchanged. + assertVariableValues(this.workspace, 'name2', 'type2', 'id2'); + + // Only first block should use new capitalization. + var blockVar1 = this.workspace.topBlocks_[0].getVarModels()[0].name; + chai.assert.equal(blockVar1, 'Name2'); + var blockVar2 = this.workspace.topBlocks_[1].getVarModels()[0].name; + chai.assert.equal(blockVar2, 'name2'); + }); + }); + }); + + suite('addTopBlock', function() { + setup(function() { + this.targetWorkspace = new Blockly.Workspace(); + this.workspace.isFlyout = true; + this.workspace.targetWorkspace = this.targetWorkspace; + }); + + teardown(function() { + // Have to dispose of the main workspace after the flyout workspace + // because it holds the variable map. + // Normally the main workspace disposes of the flyout workspace. + this.targetWorkspace.dispose(); + }); + + test('Trivial Flyout is True', function() { + this.targetWorkspace.createVariable('name1', '', '1'); + + // Flyout.init usually does this binding. + this.workspace.variableMap_ = this.targetWorkspace.getVariableMap(); + + // Turn off events to avoid testing XML at the same time. + Blockly.Events.disable(); + var block = new Blockly.Block(this.workspace, 'get_var_block'); + block.inputList[0].fieldRow[0].setValue('1'); + Blockly.Events.enable(); + + this.workspace.removeTopBlock(block); + this.workspace.addTopBlock(block); + assertVariableValues(this.workspace, 'name1', '', '1'); + }); }); suite('getTopBlocks(ordered=true)', function() { @@ -354,4 +635,73 @@ suite('Workspace', function() { }); }); + suite('getById', function() { + setup(function() { + this.workspaceB = new Blockly.Workspace(); + }); + + teardown(function() { + this.workspaceB.dispose(); + }); + + test('Trivial', function() { + chai.assert.equal(Blockly.Workspace.getById( + this.workspace.id), this.workspace, 'Find workspace'); + chai.assert.equal(Blockly.Workspace.getById( + this.workspaceB.id), this.workspaceB, 'Find workspaceB'); + }); + + test('Null id', function() { + chai.assert.isNull(Blockly.Workspace.getById(null)); + }); + + test('Non-existent id', function() { + chai.assert.isNull(Blockly.Workspace.getById('badId')); + }); + + test('After dispose', function() { + this.workspaceB.dispose(); + chai.assert.isNull(Blockly.Workspace.getById(this.workspaceB.id)); + }); + }); + + suite('getBlockById', function() { + setup(function() { + this.blockA = this.workspace.newBlock(''); + this.blockB = this.workspace.newBlock(''); + this.workspaceB = new Blockly.Workspace(); + }); + + teardown(function() { + this.workspaceB.dispose(); + }); + + test('Trivial', function() { + chai.assert.equal( + this.workspace.getBlockById(this.blockA.id),this.blockA); + chai.assert.equal( + this.workspace.getBlockById(this.blockB.id), this.blockB); + }); + + test('Null id', function() { + chai.assert.isNull(this.workspace.getBlockById(null)); + }); + + test('Non-existent id', function() { + chai.assert.isNull(this.workspace.getBlockById('badId')); + }); + + test('After dispose', function() { + this.blockA.dispose(); + chai.assert.isNull(this.workspace.getBlockById(this.blockA)); + chai.assert.equal( + this.workspace.getBlockById(this.blockB.id), this.blockB); + }); + + test('After clear', function() { + this.workspace.clear(); + chai.assert.isNull(this.workspace.getBlockById(this.blockA)); + chai.assert.isNull(this.workspace.getBlockById(this.blockB)); + }); + }); }); From 61c60019fda68f0330eba1fbea58b32833dc55b7 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Tue, 21 Apr 2020 14:03:32 -0700 Subject: [PATCH 037/139] Converting widget div tests to mocha. (#3844) --- tests/jsunit/index.html | 1 - tests/jsunit/widget_div_test.js | 138 --------------------------- tests/mocha/index.html | 1 + tests/mocha/widget_div_test.js | 161 ++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+), 139 deletions(-) delete mode 100644 tests/jsunit/widget_div_test.js create mode 100644 tests/mocha/widget_div_test.js diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index bf3cf3aba..feb2d2e93 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -19,7 +19,6 @@ - diff --git a/tests/jsunit/widget_div_test.js b/tests/jsunit/widget_div_test.js deleted file mode 100644 index db15dbe37..000000000 --- a/tests/jsunit/widget_div_test.js +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - - -function widgetdiv_testHelper_makeBBox(left, top, width, height) { - return { - left: left, - right: left + width, - top: top, - bottom: top + height - }; -} - -function widgetdiv_testHelper_makeSize(width, height) { - return { - width: width, - height: height - }; -} - -var widgetDiv_test_viewport = widgetdiv_testHelper_makeBBox(0, 0, 1000, 1000); -var widgetDiv_test_widgetSize = widgetdiv_testHelper_makeSize(100, 100); - -// Anchor is always 90 px wide and 90 px tall for this test. -var widgetDiv_test_anchorSize = 90; - -function widgetdiv_testHelper_makeAnchor(left, top) { - return { - left: left, - right: left + widgetDiv_test_anchorSize, - top: top, - bottom: top + widgetDiv_test_anchorSize - }; -} - -function test_widgetDiv_topConflict() { - var anchorTop = 50; - // Anchor placed close to the top. - var anchorBBox = widgetdiv_testHelper_makeAnchor(500, anchorTop); - - // The widget div should be placed just below the anchor. - var calculated = Blockly.WidgetDiv.calculateY_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize); - assertEquals(anchorTop + widgetDiv_test_anchorSize, calculated); -} - -function test_widgetDiv_bottomConflict() { - var anchorTop = 900; - // Anchor placed close to the bottom. - var anchorBBox = widgetdiv_testHelper_makeAnchor(500, anchorTop); - - // The widget div should be placed just above the anchor. - var calculated = Blockly.WidgetDiv.calculateY_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize); - assertEquals(anchorTop - widgetDiv_test_widgetSize.height, calculated); -} - -function test_widgetDiv_noYConflict() { - var anchorTop = 500; - // Anchor placed in the middle. - var anchorBBox = widgetdiv_testHelper_makeAnchor(500, anchorTop); - - // The widget div should be placed just below the anchor. - var calculated = Blockly.WidgetDiv.calculateY_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize); - assertEquals(anchorTop + widgetDiv_test_anchorSize, calculated); -} - - -function test_widgetDiv_leftConflict_LTR() { - var anchorLeft = 50; - // Anchor placed close to the left side. - var anchorBBox = widgetdiv_testHelper_makeAnchor(anchorLeft, 500); - - // The widget div should be placed at the anchor. - var calculated = Blockly.WidgetDiv.calculateX_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize, false /* rtl */); - assertEquals(anchorLeft, calculated); -} - -function test_widgetDiv_rightConflict_LTR() { - var anchorLeft = 950; - // Anchor placed close to the right side. - var anchorBBox = widgetdiv_testHelper_makeAnchor(anchorLeft, 500); - - // The widget div should be placed as far right as possible--at the edge of - // the screen. - var calculated = Blockly.WidgetDiv.calculateX_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize, false /* rtl */); - assertEquals(1000 - widgetDiv_test_widgetSize.width, calculated); -} - -function test_widgetDiv_noXConflict_LTR() { - var anchorLeft = 500; - // Anchor in the middle - var anchorBBox = widgetdiv_testHelper_makeAnchor(anchorLeft, 500); - // The widget div should be placed just at the left side of the anchor. - var calculated = Blockly.WidgetDiv.calculateX_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize, false /* rtl */); - assertEquals(anchorLeft, calculated); -} - -function test_widgetDiv_leftConflict_RTL() { - var anchorLeft = 10; - // Anchor placed close to the left side. - var anchorBBox = widgetdiv_testHelper_makeAnchor(anchorLeft, 500); - // The widget div should be placed as far left as possible--at the edge of - // the screen. - var calculated = Blockly.WidgetDiv.calculateX_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize, true /* rtl */); - assertEquals(0, calculated); -} - -function test_widgetDiv_rightConflict_RTL() { - var anchorLeft = 950; - // Anchor placed close to the right side. - var anchorBBox = widgetdiv_testHelper_makeAnchor(anchorLeft, 500); - - // The widget div should be placed as far right as possible--at the edge of - // the screen. - var calculated = Blockly.WidgetDiv.calculateX_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize, true /* rtl */); - assertEquals(1000 - widgetDiv_test_widgetSize.width, calculated); -} - -function test_widgetDiv_noXConflict_RTL() { - var anchorLeft = 500; - // anchor placed in the middle - var anchorBBox = widgetdiv_testHelper_makeAnchor(anchorLeft, 500); - // The widget div should be placed at the right side of the anchor. - var calculated = Blockly.WidgetDiv.calculateX_(widgetDiv_test_viewport, - anchorBBox, widgetDiv_test_widgetSize, true /* rtl */); - assertEquals(anchorBBox.right - widgetDiv_test_widgetSize.width, calculated); -} diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 65a64d1a9..c3f0e03c9 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -62,6 +62,7 @@ + diff --git a/tests/mocha/widget_div_test.js b/tests/mocha/widget_div_test.js new file mode 100644 index 000000000..bc90ad960 --- /dev/null +++ b/tests/mocha/widget_div_test.js @@ -0,0 +1,161 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +suite('WidgetDiv', function() { + + suite('positionWithAnchor', function() { + function makeBBox(left, top, width, height) { + return { + left: left, + right: left + width, + top: top, + bottom: top + height, + width: width, + height: height + }; + } + + setup(function() { + Blockly.WidgetDiv.createDom(); + this.viewportBBox = makeBBox(0, 0, 1000, 1003); + this.widgetSize = { + width: 100, + height: 102 + }; + this.anchorSize = { + width: 90, + height: 91 + }; + + this.testWidgetPosition = function( + anchorBBox, rtl, expectedX, expectedY, expectedHeight) { + Blockly.WidgetDiv.positionWithAnchor( + this.viewportBBox, anchorBBox, this.widgetSize, rtl); + var style = Blockly.WidgetDiv.DIV.style; + chai.assert.equal(style.left, expectedX + 'px', 'Left'); + chai.assert.equal(style.top, expectedY + 'px', 'Top'); + chai.assert.equal(style.height, expectedHeight + 'px', 'Height'); + }; + }); + + suite('LTR', function() { + test('noConflict', function() { + // Anchor placed in the middle. + var anchorBBox = + makeBBox(500, 500, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed just below at the left side of the + // anchor. + var expectedX = anchorBBox.left; + var expectedY = anchorBBox.top + this.anchorSize.height; + this.testWidgetPosition( + anchorBBox, false, expectedX, expectedY, this.widgetSize.height); + }); + + test('topConflict', function() { + // Anchor close to the top. + var anchorBBox = + makeBBox(500, 50, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed just below the anchor. + var expectedX = anchorBBox.left; + var expectedY = anchorBBox.top + this.anchorSize.height; + this.testWidgetPosition( + anchorBBox, false, expectedX, expectedY, this.widgetSize.height); + }); + + test('bottomConflict', function() { + // Anchor placed close to the bottom. + var anchorBBox = + makeBBox(500, 900, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed just above the anchor. + var expectedX = anchorBBox.left; + var expectedY = anchorBBox.top - this.widgetSize.height; + this.testWidgetPosition( + anchorBBox, false, expectedX, expectedY, this.widgetSize.height); + }); + + test('leftConflict', function() { + // Anchor placed close to the left side. + var anchorBBox = + makeBBox(50, 500, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed at the anchor. + var expectedX = anchorBBox.left; + var expectedY = anchorBBox.top + this.anchorSize.height; + this.testWidgetPosition( + anchorBBox, false, expectedX, expectedY, this.widgetSize.height); + }); + + test('rightConflict', function() { + // Anchor placed close to the right side. + var anchorBBox = + makeBBox(950, 500, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed as far right as possible--at the edge of + // the screen. + var expectedX = this.viewportBBox.width - this.widgetSize.width; + var expectedY = anchorBBox.top + this.anchorSize.height; + this.testWidgetPosition( + anchorBBox, false, expectedX, expectedY, this.widgetSize.height); + }); + }); + suite('RTL', function() { + test('noConflict', function() { + // Anchor placed in the middle + var anchorBBox = + makeBBox(500, 500, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed at the right side of the anchor. + var expectedX = anchorBBox.right - this.widgetSize.width; + var expectedY = anchorBBox.top + this.anchorSize.height; + this.testWidgetPosition( + anchorBBox, true, expectedX, expectedY, this.widgetSize.height); + }); + + test('topConflict', function() { + // Anchor close to the top. + var anchorBBox = + makeBBox(500, 50, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed just below the anchor. + var expectedX = anchorBBox.right - this.widgetSize.width; + var expectedY = anchorBBox.top + this.anchorSize.height; + this.testWidgetPosition( + anchorBBox, true, expectedX, expectedY, this.widgetSize.height); + }); + + test('bottomConflict', function() { + // Anchor placed close to the bottom. + var anchorBBox = + makeBBox(500, 900, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed just above the anchor. + var expectedX = anchorBBox.right - this.widgetSize.width; + var expectedY = anchorBBox.top - this.widgetSize.height; + this.testWidgetPosition( + anchorBBox, true, expectedX, expectedY, this.widgetSize.height); + }); + + test('leftConflict', function() { + // Anchor placed close to the left side. + var anchorBBox = + makeBBox(10, 500, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed as far left as possible--at the edge of + // the screen. + var expectedX = 0; + var expectedY = anchorBBox.top + this.anchorSize.height; + this.testWidgetPosition( + anchorBBox, true, expectedX, expectedY, this.widgetSize.height); + }); + + test('rightConflict', function() { + // Anchor placed close to the right side. + var anchorBBox = + makeBBox(950, 500, this.anchorSize.width, this.anchorSize.height); + // The widget div should be placed as far right as possible--at the edge of + // the screen. + var expectedX = this.viewportBBox.width - this.widgetSize.width; + var expectedY = anchorBBox.top + this.anchorSize.height; + this.testWidgetPosition( + anchorBBox, true, expectedX, expectedY, this.widgetSize.height); + }); + }); + }); +}); From b934fdc93ce36caae56044dcbc879f790a28eef1 Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Tue, 21 Apr 2020 17:38:26 -0700 Subject: [PATCH 038/139] Converting generator tests to mocha. (#3845) --- tests/jsunit/generator_test.js | 173 --------------------------------- tests/jsunit/index.html | 3 +- tests/mocha/generator_test.js | 158 ++++++++++++++++++++++++++++++ tests/mocha/index.html | 6 ++ 4 files changed, 165 insertions(+), 175 deletions(-) delete mode 100644 tests/jsunit/generator_test.js create mode 100644 tests/mocha/generator_test.js diff --git a/tests/jsunit/generator_test.js b/tests/jsunit/generator_test.js deleted file mode 100644 index b7187991b..000000000 --- a/tests/jsunit/generator_test.js +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @license - * Copyright 2012 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -'use strict'; - -goog.require('Blockly.Dart'); -goog.require('Blockly.JavaScript'); -goog.require('Blockly.Lua'); -goog.require('Blockly.PHP'); -goog.require('Blockly.Python'); - -var workspace; - -function defineGeneratorTestBlocks() { - Blockly.defineBlocksWithJsonArray([{ - "type": "stack_block", - "message0": "", - "previousStatement": null, - "nextStatement": null - }, - { - "type": "row_block", - "message0": "%1", - "args0": [ - { - "type": "input_value", - "name": "INPUT" - } - ], - "output": null, - "nextStatement": null - }, - { - "type": "controls_repeat_ext", - "message0": "Repeat Loop", - "message1": "%1", - "args1": [{ - "type": "input_statement", - "name": "DO" - }], - "previousStatement": null, - "nextStatement": null - }]); -} - -function undefineGeneratorTestBlocks() { - delete Blockly.Blocks['stack_block']; - delete Blockly.Blocks['row_block']; -} - -function generatorTest_setUp() { - defineGeneratorTestBlocks(); - workspace = new Blockly.Workspace(); -} - -function generatorTest_tearDown() { - undefineGeneratorTestBlocks(); - workspace.dispose(); -} - -function blockToCodeTestSetup(generator) { - var row_block = workspace.newBlock('row_block'); - var stack_block = workspace.newBlock('stack_block'); - - generator.row_block = function(block){return 'row_block'}; - generator.stack_block = function(block){return 'stack_block'}; - row_block.nextConnection.connect(stack_block.previousConnection); - return row_block; -} - -function blockToCodeTest(generator, opt_thisOnly) { - var row_block = blockToCodeTestSetup(generator); - return generator.blockToCode(row_block, opt_thisOnly); -} - -function disabledBlockTest(generator, opt_thisOnly) { - var row_block = blockToCodeTestSetup(generator); - row_block.disabled=true; - return generator.blockToCode(row_block, opt_thisOnly); -} - -function nestedLoopTest(generator, opt_thisOnly) { - Blockly.Msg['CONTROLS_REPEAT_TITLE'] = 'repeat %1 times'; - var blockA = workspace.newBlock('controls_repeat_ext'); - var blockB = workspace.newBlock('controls_repeat_ext'); - var blockC = workspace.newBlock('controls_repeat_ext'); - generator.controls_repeat_ext = getControlRepeatFunc(generator); - - blockA.getInput('DO').connection.connect(blockB.previousConnection); - blockA.nextConnection.connect(blockC.previousConnection); - return generator.blockToCode(blockA, opt_thisOnly); -} - -function getControlRepeatFunc(generator) { - return function(block){ - return '{' + generator.statementToCode(block, 'DO') + '}'; - }; -} - -function test_blockToCodeOnAllGeneartors() { - generatorTest_setUp(); - - assertEquals(blockToCodeTest(Blockly.Dart, true), 'row_block'); - assertEquals(blockToCodeTest(Blockly.Dart, false), 'row_blockstack_block'); - - assertEquals(blockToCodeTest(Blockly.JavaScript, true), 'row_block'); - assertEquals(blockToCodeTest(Blockly.JavaScript, false), 'row_blockstack_block'); - - assertEquals(blockToCodeTest(Blockly.Lua, true), 'row_block'); - assertEquals(blockToCodeTest(Blockly.Lua, false), 'row_blockstack_block'); - - assertEquals(blockToCodeTest(Blockly.PHP, true), 'row_block'); - assertEquals(blockToCodeTest(Blockly.PHP, false), 'row_blockstack_block'); - - assertEquals(blockToCodeTest(Blockly.Python, true), 'row_block'); - assertEquals(blockToCodeTest(Blockly.Python, false), 'row_blockstack_block'); - - generatorTest_tearDown(); -} - -function test_disabledBlockToCode() { - generatorTest_setUp(); - - assertEquals(disabledBlockTest(Blockly.Dart, true), ''); - assertEquals(disabledBlockTest(Blockly.Dart, false), 'stack_block'); - - assertEquals(disabledBlockTest(Blockly.JavaScript, true), ''); - assertEquals(disabledBlockTest(Blockly.JavaScript, false), 'stack_block'); - - assertEquals(disabledBlockTest(Blockly.Lua, true), ''); - assertEquals(disabledBlockTest(Blockly.Lua, false), 'stack_block'); - - assertEquals(disabledBlockTest(Blockly.PHP, true), ''); - assertEquals(disabledBlockTest(Blockly.PHP, false), 'stack_block'); - - assertEquals(disabledBlockTest(Blockly.Python, true), ''); - assertEquals(disabledBlockTest(Blockly.Python, false), 'stack_block'); - - generatorTest_tearDown(); -} - -// { {}} represents a nested block -//{ {}}{} represents a nested block with a block after it -function test_nestedLoopBlockToCode() { - generatorTest_setUp(); - - assertEquals(nestedLoopTest(Blockly.Dart, true), '{ {}}'); - assertEquals(nestedLoopTest(Blockly.Dart, false), '{ {}}{}'); - - assertEquals(nestedLoopTest(Blockly.JavaScript, true), '{ {}}'); - assertEquals(nestedLoopTest(Blockly.JavaScript, false), '{ {}}{}'); - - assertEquals(nestedLoopTest(Blockly.Lua, true), '{ {}}'); - assertEquals(nestedLoopTest(Blockly.Lua, false), '{ {}}{}'); - - assertEquals(nestedLoopTest(Blockly.PHP, true), '{ {}}'); - assertEquals(nestedLoopTest(Blockly.PHP, false), '{ {}}{}'); - - assertEquals(nestedLoopTest(Blockly.Python, true), '{ {}}'); - assertEquals(nestedLoopTest(Blockly.Python, false), '{ {}}{}'); - - generatorTest_tearDown(); -} - -function test_prefix() { - var generator = new Blockly.Generator('INTERCAL'); - assertEquals('Prefix nothing.', '', generator.prefixLines('', '')); - assertEquals('Prefix a word.', '@Hello', generator.prefixLines('Hello', '@')); - assertEquals('Prefix one line.', '12Hello\n', generator.prefixLines('Hello\n', '12')); - assertEquals('Prefix two lines.', '***Hello\n***World\n', generator.prefixLines('Hello\nWorld\n', '***')); -} \ No newline at end of file diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index feb2d2e93..38ad75f9a 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -17,8 +17,7 @@ - - + diff --git a/tests/mocha/generator_test.js b/tests/mocha/generator_test.js new file mode 100644 index 000000000..cf91990ea --- /dev/null +++ b/tests/mocha/generator_test.js @@ -0,0 +1,158 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +goog.require('Blockly.Dart'); +goog.require('Blockly.JavaScript'); +goog.require('Blockly.Lua'); +goog.require('Blockly.PHP'); +goog.require('Blockly.Python'); + +suite('Generator', function() { + setup(function() { + this.workspace = new Blockly.Workspace(); + }); + + teardown(function() { + this.workspace.dispose(); + }); + + suite('prefix', function() { + setup(function() { + this.generator = new Blockly.Generator('INTERCAL'); + }); + + test('Nothing', function() { + chai.assert.equal(this.generator.prefixLines('', ''), ''); + }); + + test('One word', function() { + chai.assert.equal(this.generator.prefixLines('Hello', '@'), '@Hello') ; + }); + + test('One line', function() { + chai.assert.equal(this.generator.prefixLines('Hello\n', '12'), '12Hello\n'); + }); + + test('Two lines', function() { + chai.assert.equal(this.generator.prefixLines('Hello\nWorld\n', '***'), '***Hello\n***World\n'); + }); + }); + + suite('blockToCode', function() { + setup(function() { + Blockly.defineBlocksWithJsonArray([{ + "type": "stack_block", + "message0": "", + "previousStatement": null, + "nextStatement": null + }, + { + "type": "row_block", + "message0": "%1", + "args0": [ + { + "type": "input_value", + "name": "INPUT" + } + ], + "output": null, + "nextStatement": null + }]); + var rowBlock = this.workspace.newBlock('row_block'); + var stackBlock = this.workspace.newBlock('stack_block'); + + this.blockToCodeTest = function( + generator, blockDisabled, opt_thisOnly, + expectedCode, opt_message) { + generator.row_block = function(_){return 'row_block';}; + generator.stack_block = function(_){return 'stack_block';}; + rowBlock.nextConnection.connect(stackBlock.previousConnection); + rowBlock.disabled = blockDisabled; + + var code = generator.blockToCode(rowBlock, opt_thisOnly); + chai.assert.equal(code, expectedCode, opt_message); + }; + }); + + teardown(function() { + delete Blockly.Blocks['stack_block']; + delete Blockly.Blocks['row_block']; + }); + + var testCase = [ + [Blockly.Dart, 'Dart'], + [Blockly.JavaScript, 'JavaScript'], + [Blockly.Lua, 'Lua'], + [Blockly.PHP, 'PHP'], + [Blockly.Python, 'Python']]; + + suite('Trivial', function() { + testCase.forEach(function(testCase) { + var generator = testCase[0]; + var name = testCase[1]; + test(name, function() { + this.blockToCodeTest(generator, false, true, 'row_block'); + this.blockToCodeTest( + generator, false, false, 'row_blockstack_block', 'thisOnly=false'); + }); + }); + }); + + suite('Disabled block', function() { + testCase.forEach(function(testCase) { + var generator = testCase[0]; + var name = testCase[1]; + test(name, function() { + this.blockToCodeTest(generator, true, true, ''); + this.blockToCodeTest(generator, true, false, 'stack_block', 'thisOnly=false'); + }); + }); + }); + + suite('Nested block', function() { + setup(function() { + Blockly.defineBlocksWithJsonArray([ { + "type": "test_loop_block", + "message0": "Repeat Loop", + "message1": "%1", + "args1": [{ + "type": "input_statement", + "name": "DO" + }], + "previousStatement": null, + "nextStatement": null + }]); + var blockA = this.workspace.newBlock('test_loop_block'); + var blockB = this.workspace.newBlock('test_loop_block'); + var blockC = this.workspace.newBlock('test_loop_block'); + this.loopTest = function( + generator, opt_thisOnly, expectedCode, opt_message) { + generator.test_loop_block = function(block){ + return '{' + generator.statementToCode(block, 'DO') + '}'; + }; + blockA.getInput('DO').connection.connect(blockB.previousConnection); + blockA.nextConnection.connect(blockC.previousConnection); + + var code = generator.blockToCode(blockA, opt_thisOnly); + chai.assert.equal(code, expectedCode, opt_message); + }; + }); + + teardown(function() { + delete Blockly.Blocks['test_loop_block']; + }); + + testCase.forEach(function(testCase) { + var generator = testCase[0]; + var name = testCase[1]; + test(name, function() { + this.loopTest(generator, true, '{ {}}'); + this.loopTest(generator, false, '{ {}}{}', 'thisOnly=false'); + }); + }); + }); + }); +}); diff --git a/tests/mocha/index.html b/tests/mocha/index.html index c3f0e03c9..09d2e7cdf 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -6,6 +6,11 @@ + + + + + @@ -47,6 +52,7 @@ + From 10444d76ecfbd6fe73fe3dc3eefb0f75c1673861 Mon Sep 17 00:00:00 2001 From: alschmiedt Date: Wed, 22 Apr 2020 08:47:08 -0700 Subject: [PATCH 039/139] Toolbox tests (#3846) * Add tests for toolbox --- tests/mocha/index.html | 32 +++ tests/mocha/run_mocha_tests_in_browser.js | 2 +- tests/mocha/toolbox_test.js | 237 ++++++++++++++++++++++ 3 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 tests/mocha/toolbox_test.js diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 09d2e7cdf..a1c57c74b 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -63,6 +63,7 @@ + @@ -77,6 +78,17 @@ + + +