diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..bc5a5f3c6 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,76 @@ +{ + "rules": { + "curly": ["error"], + "eol-last": ["error"], + "_comment": "Blockly/Google use 2-space indents", + "_comment": "Blockly/Google uses +4 space indents for line continuations.", + "_comment": "Ignore default rules for ternary expressions.", + "indent": [ + "error", 2, + { + "SwitchCase": 1, + "MemberExpression": 2, + "ObjectExpression": 1, + "FunctionDeclaration": { + "body": 1, + "parameters": 2 + }, + "FunctionExpression": { + "body": 1, + "parameters": 2 + }, + "CallExpression": { + "arguments": 2 + }, + "ignoredNodes": ["ConditionalExpression"] + } + ], + "keyword-spacing": ["error"], + "linebreak-style": ["error", "unix"], + "max-len": [ + "error", + { + "code": 100, + "tabWidth": 4, + "ignoreStrings": true, + "ignoreRegExpLiterals": true + } + ], + "no-trailing-spaces": ["error", { "skipBlankLines": true }], + "no-unused-vars": [ + "error", + { + "args": "after-used", + "_comment": "Ignore vars starting with an underscore.", + "varsIgnorePattern": "^_", + "_comment": "Ignore arguments starting with an underscore.", + "argsIgnorePattern": "^_" + } + ], + "no-use-before-define": ["error"], + "_comment":"Blockly uses for exporting symbols. no-self-assign added in eslint 5.", + "no-self-assign": ["off"], + "_comment": "Blockly uses single quotes except for JSON blobs, which must use double quotes.", + "quotes": ["off"], + "semi": ["error", "always"], + "_comment": "Blockly doesn't have space before function paren", + "space-before-function-paren": ["error", "never"], + "space-infix-ops": ["error"], + "_comment": "Blockly uses 'use strict' in files", + "strict": ["off"], + "_comment": "Blockly often uses cond-assignment in loops", + "no-cond-assign": ["off"], + "_comment": "Closure style allows redeclarations", + "no-redeclare": ["off"], + "valid-jsdoc": ["error", {"requireReturn": false}], + "no-console": ["off"] + }, + "env": { + "browser": true + }, + "globals": { + "Blockly": true, + "goog": true + }, + "extends": "eslint:recommended" +} diff --git a/blockly_accessible_compressed.js b/blockly_accessible_compressed.js index 22be0080c..333de2689 100644 --- a/blockly_accessible_compressed.js +++ b/blockly_accessible_compressed.js @@ -5,7 +5,7 @@ var $jscomp=$jscomp||{};$jscomp.scope={};var COMPILED=!0,goog=goog||{};goog.glob goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&goog.isDef(b)?c[d]=b:c=c[d]&&c[d]!==Object.prototype[d]?c[d]:c[d]={}}; goog.define=function(a,b){if(!COMPILED){var c=goog.global.CLOSURE_UNCOMPILED_DEFINES,d=goog.global.CLOSURE_DEFINES;c&&void 0===c.nodeType&&Object.prototype.hasOwnProperty.call(c,a)?b=c[a]:d&&void 0===d.nodeType&&Object.prototype.hasOwnProperty.call(d,a)&&(b=d[a])}goog.exportPath_(a,b)};goog.DEBUG=!1;goog.LOCALE="en";goog.TRUSTED_SITE=!0;goog.STRICT_MODE_COMPATIBLE=!1;goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG;goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING=!1; goog.provide=function(a){if(goog.isInModuleLoader_())throw Error("goog.provide cannot be used within a module.");if(!COMPILED&&goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');goog.constructNamespace_(a)};goog.constructNamespace_=function(a,b){if(!COMPILED){delete goog.implicitNamespaces_[a];for(var c=a;(c=c.substring(0,c.lastIndexOf(".")))&&!goog.getObjectByName(c);)goog.implicitNamespaces_[c]=!0}goog.exportPath_(a,b)}; -goog.getScriptNonce=function(){null===goog.cspNonce_&&(goog.cspNonce_=goog.getScriptNonce_(goog.global.document)||"");return goog.cspNonce_};goog.NONCE_PATTERN_=/^[\w+/_-]+[=]{0,2}$/;goog.cspNonce_=null;goog.getScriptNonce_=function(a){return(a=a.querySelector("script[nonce]"))&&(a=a.nonce||a.getAttribute("nonce"))&&goog.NONCE_PATTERN_.test(a)?a:null};goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/; +goog.getScriptNonce=function(){null===goog.cspNonce_&&(goog.cspNonce_=goog.getScriptNonce_(goog.global.document)||"");return goog.cspNonce_};goog.NONCE_PATTERN_=/^[\w+/_-]+[=]{0,2}$/;goog.cspNonce_=null;goog.getScriptNonce_=function(a){return(a=a.querySelector&&a.querySelector("script[nonce]"))&&(a=a.nonce||a.getAttribute("nonce"))&&goog.NONCE_PATTERN_.test(a)?a:null};goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/; goog.module=function(a){if(!goog.isString(a)||!a||-1==a.search(goog.VALID_MODULE_RE_))throw Error("Invalid module identifier");if(!goog.isInGoogModuleLoader_())throw Error("Module "+a+" has been loaded incorrectly. Note, modules cannot be loaded as normal scripts. They require some kind of pre-processing step. You're likely trying to load a module via a script tag or as a part of a concatenated bundle without rewriting the module. For more info see: https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide."); if(goog.moduleLoaderState_.moduleName)throw Error("goog.module may only be called once per module.");goog.moduleLoaderState_.moduleName=a;if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a]}};goog.module.get=function(a){return goog.module.getInternal_(a)}; goog.module.getInternal_=function(a){if(!COMPILED){if(a in goog.loadedModules_)return goog.loadedModules_[a].exports;if(!goog.implicitNamespaces_[a])return a=goog.getObjectByName(a),null!=a?a:null}return null};goog.ModuleType={ES6:"es6",GOOG:"goog"};goog.moduleLoaderState_=null;goog.isInModuleLoader_=function(){return goog.isInGoogModuleLoader_()||goog.isInEs6ModuleLoader_()};goog.isInGoogModuleLoader_=function(){return!!goog.moduleLoaderState_&&goog.moduleLoaderState_.type==goog.ModuleType.GOOG}; @@ -16,13 +16,13 @@ if(!b||"function"!=typeof b.getCurrentModulePath)throw Error('Module with namesp COMPILED||(goog.isProvided_=function(a){return a in goog.loadedModules_||!goog.implicitNamespaces_[a]&&goog.isDefAndNotNull(goog.getObjectByName(a))},goog.implicitNamespaces_={"goog.module":!0});goog.getObjectByName=function(a,b){a=a.split(".");b=b||goog.global;for(var c=0;c>>0);goog.uidCounter_=0;goog.getHashCode=goog.getUid; @@ -41,31 +41,32 @@ goog.defineClass.SEAL_CLASS_INSTANCES=goog.DEBUG;goog.defineClass.createSealingC goog.defineClass.OBJECT_PROTOTYPE_FIELDS_="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" ");goog.defineClass.applyProperties_=function(a,b){for(var c in b)Object.prototype.hasOwnProperty.call(b,c)&&(a[c]=b[c]);for(var d=0;dNumber(a[1])?!1:b('(()=>{"use strict";class X{constructor(){if(new.target!=String)throw 1;this.x=42}}let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof String))throw 1;for(const a of[2,3]){if(a==2)continue;function f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()==3}})()')});a("es6-impl",function(){return!0});a("es7",function(){return b("2 ** 2 == 4")}); -a("es8",function(){return b("async () => 1, true")});a("es9",function(){return b("({...rest} = {}), true")});a("es_next",function(){return!1});return c},goog.Transpiler.prototype.needsTranspile=function(a,b){if("always"==goog.TRANSPILE)return!0;if("never"==goog.TRANSPILE)return!1;this.requiresTranspilation_||(this.requiresTranspilation_=this.createRequiresTranspilation_());if(a in this.requiresTranspilation_)return this.requiresTranspilation_[a]?!0:!goog.inHtmlDocument_()||"es6"!=b||"noModule"in goog.global.document.createElement("script")? -!1:!0;throw Error("Unknown language mode: "+a);},goog.Transpiler.prototype.transpile=function(a,b){return goog.transpile_(a,b)},goog.transpiler_=new goog.Transpiler,goog.protectScriptTag_=function(a){return a.replace(/<\/(SCRIPT)/ig,"\\x3c/$1")},goog.DebugLoader_=function(){this.dependencies_={};this.idToPath_={};this.written_={};this.loadingDeps_=[];this.depsToLoad_=[];this.paused_=!1;this.factory_=new goog.DependencyFactory(goog.transpiler_);this.deferredCallbacks_={};this.deferredQueue_=[]},goog.DebugLoader_.prototype.bootstrap= -function(a,b){function c(){d&&(goog.global.setTimeout(d,0),d=null)}var d=b;if(a.length){b=[];for(var e=0;e\x3c/script>")}else{var e=b.createElement("script");e.defer=goog.Dependency.defer_;e.async=!1;e.type="text/javascript";(d=goog.getScriptNonce())&&e.setAttribute("nonce",d);goog.DebugLoader_.IS_OLD_IE_? -(a.pause(),e.onreadystatechange=function(){if("loaded"==e.readyState||"complete"==e.readyState)a.loaded(),a.resume()}):e.onload=function(){e.onload=null;a.loaded()};e.src=this.path;b.head.appendChild(e)}}else goog.logToConsole_("Cannot use default debug loader outside of HTML documents."),"deps.js"==this.relativePath?(goog.logToConsole_("Consider setting CLOSURE_IMPORT_SCRIPT before loading base.js, or seting CLOSURE_NO_DEPS to true."),a.loaded()):a.pause()},goog.Es6ModuleDependency=function(a,b, -c,d,e){goog.Dependency.call(this,a,b,c,d,e)},goog.inherits(goog.Es6ModuleDependency,goog.Dependency),goog.Es6ModuleDependency.prototype.load=function(a){function b(a,b){b?d.write(' + diff --git a/tests/jsunit/utils_test.js b/tests/jsunit/utils_test.js index 98ffabd7f..ca6e77e63 100644 --- a/tests/jsunit/utils_test.js +++ b/tests/jsunit/utils_test.js @@ -232,3 +232,42 @@ function test_replaceMessageReferences() { 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_startsWith() { + assertEquals('Does not start with', false, Blockly.utils.startsWith('123', '2')); + assertEquals('Start with', true, Blockly.utils.startsWith('123', '12')); + assertEquals('Start with empty string 1', true, Blockly.utils.startsWith('123', '')); + assertEquals('Start with empty string 2', true, Blockly.utils.startsWith('', '')); +} + +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_toRadians() { + var quarter = Math.PI / 2; + assertEquals('-90', -quarter, Blockly.utils.toRadians(-90)); + assertEquals('0', 0, Blockly.utils.toRadians(0)); + assertEquals('90', quarter, Blockly.utils.toRadians(90)); + assertEquals('180', 2 * quarter, Blockly.utils.toRadians(180)); + assertEquals('270', 3 * quarter, Blockly.utils.toRadians(270)); + assertEquals('360', 4 * quarter, Blockly.utils.toRadians(360)); + assertEquals('450', 5 * quarter, Blockly.utils.toRadians(360 + 90)); +} + +function test_toDegrees() { + var quarter = Math.PI / 2; + assertEquals('-90', -90, Blockly.utils.toDegrees(-quarter)); + assertEquals('0', 0, Blockly.utils.toDegrees(0)); + assertEquals('90', 90, Blockly.utils.toDegrees(quarter)); + assertEquals('180', 180, Blockly.utils.toDegrees(2 * quarter)); + assertEquals('270', 270, Blockly.utils.toDegrees(3 * quarter)); + assertEquals('360', 360, Blockly.utils.toDegrees(4 * quarter)); + assertEquals('450', 360 + 90, Blockly.utils.toDegrees(5 * quarter)); +} diff --git a/media/test_200px.png b/tests/media/200px.png similarity index 100% rename from media/test_200px.png rename to tests/media/200px.png diff --git a/media/test_30px.png b/tests/media/30px.png similarity index 100% rename from media/test_30px.png rename to tests/media/30px.png diff --git a/media/test_50px.png b/tests/media/50px.png similarity index 100% rename from media/test_50px.png rename to tests/media/50px.png diff --git a/media/test_a.png b/tests/media/a.png similarity index 100% rename from media/test_a.png rename to tests/media/a.png diff --git a/media/test_b.png b/tests/media/b.png similarity index 100% rename from media/test_b.png rename to tests/media/b.png diff --git a/media/test_c.png b/tests/media/c.png similarity index 100% rename from media/test_c.png rename to tests/media/c.png diff --git a/media/test_d.png b/tests/media/d.png similarity index 100% rename from media/test_d.png rename to tests/media/d.png diff --git a/media/test_e.png b/tests/media/e.png similarity index 100% rename from media/test_e.png rename to tests/media/e.png diff --git a/media/test_f.png b/tests/media/f.png similarity index 100% rename from media/test_f.png rename to tests/media/f.png diff --git a/media/test_g.png b/tests/media/g.png similarity index 100% rename from media/test_g.png rename to tests/media/g.png diff --git a/media/test_h.png b/tests/media/h.png similarity index 100% rename from media/test_h.png rename to tests/media/h.png diff --git a/media/test_i.png b/tests/media/i.png similarity index 100% rename from media/test_i.png rename to tests/media/i.png diff --git a/media/test_j.png b/tests/media/j.png similarity index 100% rename from media/test_j.png rename to tests/media/j.png diff --git a/media/test_k.png b/tests/media/k.png similarity index 100% rename from media/test_k.png rename to tests/media/k.png diff --git a/media/test_l.png b/tests/media/l.png similarity index 100% rename from media/test_l.png rename to tests/media/l.png diff --git a/media/test_m.png b/tests/media/m.png similarity index 100% rename from media/test_m.png rename to tests/media/m.png diff --git a/tests/playground.html b/tests/playground.html index 745ba0cab..0b22f4a93 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -1131,10 +1131,18 @@ h1 { - - - - + + 123.456 + + + 123.456 + + + 123.456 + + + 60 + diff --git a/tests/workspace_svg/event_svg_test.js b/tests/workspace_svg/event_svg_test.js new file mode 100644 index 000000000..ae1055109 --- /dev/null +++ b/tests/workspace_svg/event_svg_test.js @@ -0,0 +1,90 @@ +/** + * @license + * Blockly Tests + * + * Copyright 2018 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict'; + +goog.require('goog.testing'); +goog.require('goog.testing.MockControl'); + +function eventSvg_setUpMockBlocks() { + // 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', + 'output': null + }, + { + 'type': 'test_val_in', + 'message0': 'test in %1', + 'args0': [ + { + 'type': 'input_value', + 'name': 'NAME' + } + ] + }]); +} + +function eventSvg_tearDownMockBlocks() { + delete Blockly.Blocks['field_variable_test_block']; + delete Blockly.Blocks['simple_test_block']; + delete Blockly.Blocks['test_val_in']; +} + +function eventSvg_createWorkspaceWithToolbox() { + var toolbox = document.getElementById('toolbox-categories'); + return Blockly.inject('blocklyDiv', {toolbox: toolbox}); +} + +function eventSvg_createNewBlock(workspace, type) { + var block = workspace.newBlock(type); + block.initSvg(); + return block; +} + +function test_blockDelete_svgDispose() { + eventSvg_setUpMockBlocks(); + var workspace = eventSvg_createWorkspaceWithToolbox(); + Blockly.Events.fire = temporary_fireEvent; + temporary_fireEvent.firedEvents_ = []; + try { + var block = eventSvg_createNewBlock(workspace); + block.setCommentText('test comment'); + var event = new Blockly.Events.BlockDelete(block); + workspace.clearUndo(); + block.dispose(); + var firedEvents = workspace.undoStack_; + assertEquals('Delete event created by dispose matches constructed delete event', + Blockly.Xml.domToText(event.oldXml), Blockly.Xml.domToText(firedEvents[0].oldXml)); + } finally { + eventSvg_tearDownMockBlocks(); + workspace.dispose(); + } +} \ No newline at end of file diff --git a/tests/workspace_svg/index.html b/tests/workspace_svg/index.html index 65890169a..53006a634 100644 --- a/tests/workspace_svg/index.html +++ b/tests/workspace_svg/index.html @@ -51,7 +51,11 @@ h1 {

Blockly Workspace testing

+ + + +