From c3b2dae6a4f2c0cba19185c854b457bab65cab1d Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Tue, 11 Jul 2023 10:35:25 -0400 Subject: [PATCH 01/10] chore: create mutator test --- tests/browser/test/mutator_test.js | 83 ++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/browser/test/mutator_test.js diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js new file mode 100644 index 00000000000..dc17dfd9247 --- /dev/null +++ b/tests/browser/test/mutator_test.js @@ -0,0 +1,83 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Node.js script to run Automated tests in Chrome, via webdriver. + */ + +const chai = require('chai'); +const { + testSetup, + testFileLocations, + getSelectedBlockElement, + getNthBlockOfCategory, + getBlockTypeFromCategory, + connect, + switchRTL, +} = require('./test_setup'); + +let browser; +suite('Testing Field Edits', function (done) { + // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test + this.timeout(0); + + // Setup Selenium for all of the tests + suiteSetup(async function () { + browser = await testSetup(testFileLocations.playground); + }); + + test('Testing Field Edits LTR', async function () { + await testingMutator(1); + }); + + + // Teardown entire suite after test are done running + suiteTeardown(async function () { + await browser.deleteSession(); + }); +}); + +async function testingMutator(delta) { + // Drag out print from flyout. + const controlIfFlyout = await getBlockTypeFromCategory( + browser, + 'Logic', + 'controls_if' + ); + await controlIfFlyout.dragAndDrop({x: (delta*50), y: 50}); + //Get the number of transform elements on the if do block + const ifDo = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected' + ); + let ifDoNumHTML= await ifDo.getHTML(); + let ifDoTransformCountBefore=(ifDoNumHTML.match(/transform/g) || []).length; + console.log(ifDoTransformCountBefore); + //Click mutator + const mutatorWheel = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected > g.blocklyIconGroup' + ); + + await mutatorWheel.click(); + + const elseIfFlyout = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyFlyout > g > g.blocklyBlockCanvas > g:nth-child(3)' + ); + + elseIfFlyout.dragAndDrop({x: (delta*50), y: 42}) + await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec + + const elseIf = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable' + ); + + elseIf.dragAndDrop({x: (delta)*-25, y: -10}) + await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec + ifDoNumHTML= await ifDo.getHTML(); + let ifDoTransformCountAfter=(ifDoNumHTML.match(/transform/g) || []).length; + + chai.assert.isTrue(ifDoTransformCountAfter>ifDoTransformCountBefore); + +} \ No newline at end of file From 0e1db5b569712294beb8afd81612528a7a4e1e62 Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Tue, 11 Jul 2023 11:17:15 -0400 Subject: [PATCH 02/10] chore: create test for undo block movements and editing a field --- tests/browser/test/mutator_test.js | 74 ++++++++++++++---------------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js index dc17dfd9247..3e4dcf1117a 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.js @@ -12,10 +12,7 @@ const chai = require('chai'); const { testSetup, testFileLocations, - getSelectedBlockElement, - getNthBlockOfCategory, getBlockTypeFromCategory, - connect, switchRTL, } = require('./test_setup'); @@ -33,7 +30,6 @@ suite('Testing Field Edits', function (done) { await testingMutator(1); }); - // Teardown entire suite after test are done running suiteTeardown(async function () { await browser.deleteSession(); @@ -41,43 +37,43 @@ suite('Testing Field Edits', function (done) { }); async function testingMutator(delta) { - // Drag out print from flyout. - const controlIfFlyout = await getBlockTypeFromCategory( - browser, - 'Logic', - 'controls_if' - ); - await controlIfFlyout.dragAndDrop({x: (delta*50), y: 50}); - //Get the number of transform elements on the if do block - const ifDo = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected' - ); - let ifDoNumHTML= await ifDo.getHTML(); - let ifDoTransformCountBefore=(ifDoNumHTML.match(/transform/g) || []).length; - console.log(ifDoTransformCountBefore); - //Click mutator - const mutatorWheel = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected > g.blocklyIconGroup' - ); - - await mutatorWheel.click(); + // Drag out print from flyout. + const controlIfFlyout = await getBlockTypeFromCategory( + browser, + 'Logic', + 'controls_if' + ); + await controlIfFlyout.dragAndDrop({x: delta * 50, y: 50}); + // Get the number of transform elements on the if do block + const ifDo = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected' + ); + let ifDoNumHTML = await ifDo.getHTML(); + const ifDoTransformCountBefore = (ifDoNumHTML.match(/transform/g) || []).length; + console.log(ifDoTransformCountBefore); + // Click mutator + const mutatorWheel = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected > g.blocklyIconGroup' + ); - const elseIfFlyout = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyFlyout > g > g.blocklyBlockCanvas > g:nth-child(3)' - ); + await mutatorWheel.click(); + // Create the new configuration + const elseIfFlyout = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyFlyout > g > g.blocklyBlockCanvas > g:nth-child(3)' + ); - elseIfFlyout.dragAndDrop({x: (delta*50), y: 42}) - await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec + elseIfFlyout.dragAndDrop({x: delta * 50, y: 42}); + await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec - const elseIf = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable' - ); + const elseIf = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable' + ); - elseIf.dragAndDrop({x: (delta)*-25, y: -10}) - await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec - ifDoNumHTML= await ifDo.getHTML(); - let ifDoTransformCountAfter=(ifDoNumHTML.match(/transform/g) || []).length; + elseIf.dragAndDrop({x: delta * -25, y: -10}); + await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec + // Check to see that the new configuration has more transform elements + ifDoNumHTML = await ifDo.getHTML(); + const ifDoTransformCountAfter = (ifDoNumHTML.match(/transform/g) || []).length; - chai.assert.isTrue(ifDoTransformCountAfter>ifDoTransformCountBefore); - -} \ No newline at end of file + chai.assert.isTrue(ifDoTransformCountAfter > ifDoTransformCountBefore); +} From 1ebc84f1b1f3026253d9b7d462187062af4b8d13 Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Tue, 11 Jul 2023 14:28:23 -0400 Subject: [PATCH 03/10] chore: create test for mutator --- tests/browser/test/mutator_test.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js index 3e4dcf1117a..e04a14d75f6 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.js @@ -14,10 +14,12 @@ const { testFileLocations, getBlockTypeFromCategory, switchRTL, + dragBlockTypeFromFlyout, + screenDirection, } = require('./test_setup'); let browser; -suite('Testing Field Edits', function (done) { +suite('Testing Mutator', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test this.timeout(0); @@ -27,7 +29,12 @@ suite('Testing Field Edits', function (done) { }); test('Testing Field Edits LTR', async function () { - await testingMutator(1); + await testingMutator(screenDirection.LTR); + }); + + test('Testing Field Edits RTL', async function () { + await switchRTL(browser); + await testingMutator(screenDirection.RTL); }); // Teardown entire suite after test are done running @@ -38,18 +45,20 @@ suite('Testing Field Edits', function (done) { async function testingMutator(delta) { // Drag out print from flyout. - const controlIfFlyout = await getBlockTypeFromCategory( + const controlIfFlyout = await dragBlockTypeFromFlyout( browser, 'Logic', - 'controls_if' + 'controls_if', + delta * 50, + 50 ); - await controlIfFlyout.dragAndDrop({x: delta * 50, y: 50}); // Get the number of transform elements on the if do block const ifDo = await browser.$( '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected' ); let ifDoNumHTML = await ifDo.getHTML(); - const ifDoTransformCountBefore = (ifDoNumHTML.match(/transform/g) || []).length; + const ifDoTransformCountBefore = (ifDoNumHTML.match(/transform/g) || []) + .length; console.log(ifDoTransformCountBefore); // Click mutator const mutatorWheel = await browser.$( @@ -73,7 +82,8 @@ async function testingMutator(delta) { await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec // Check to see that the new configuration has more transform elements ifDoNumHTML = await ifDo.getHTML(); - const ifDoTransformCountAfter = (ifDoNumHTML.match(/transform/g) || []).length; + const ifDoTransformCountAfter = (ifDoNumHTML.match(/transform/g) || []) + .length; chai.assert.isTrue(ifDoTransformCountAfter > ifDoTransformCountBefore); } From 04d3421c7301d9583abe5c1983dd93b829135a39 Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Fri, 14 Jul 2023 10:23:17 -0400 Subject: [PATCH 04/10] chore: creating test for mutator --- tests/browser/test/mutator_test.js | 42 ++++++++++++------------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js index e04a14d75f6..a11155bf6ee 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.js @@ -12,7 +12,7 @@ const chai = require('chai'); const { testSetup, testFileLocations, - getBlockTypeFromCategory, + getSelectedBlockId, switchRTL, dragBlockTypeFromFlyout, screenDirection, @@ -31,15 +31,16 @@ suite('Testing Mutator', function (done) { test('Testing Field Edits LTR', async function () { await testingMutator(screenDirection.LTR); }); - + /* test('Testing Field Edits RTL', async function () { await switchRTL(browser); await testingMutator(screenDirection.RTL); }); + */ // Teardown entire suite after test are done running suiteTeardown(async function () { - await browser.deleteSession(); + //await browser.deleteSession(); }); }); @@ -52,38 +53,27 @@ async function testingMutator(delta) { delta * 50, 50 ); - // Get the number of transform elements on the if do block - const ifDo = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected' - ); - let ifDoNumHTML = await ifDo.getHTML(); - const ifDoTransformCountBefore = (ifDoNumHTML.match(/transform/g) || []) - .length; - console.log(ifDoTransformCountBefore); - // Click mutator + // Click on the mutator and drag out else ig block const mutatorWheel = await browser.$( '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected > g.blocklyIconGroup' ); - await mutatorWheel.click(); - // Create the new configuration const elseIfFlyout = await browser.$( '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyFlyout > g > g.blocklyBlockCanvas > g:nth-child(3)' ); - elseIfFlyout.dragAndDrop({x: delta * 50, y: 42}); - await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec - - const elseIf = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable' + await browser.pause(100); + // Get the ids for the blocks in the mutator + blockIds = await browser.execute( + () => { + const mutatorBlock = Blockly.getMainWorkspace().getAllBlocks()[0]; + // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block + const mutatorWorkspaceFirstBlock = mutatorBlock.mutator.getWorkspace().getAllBlocks(false)[0].id; + let blockIds=[Blockly.getMainWorkspace().getAllBlocks()[0].id,mutatorWorkspaceFirstBlock,Blockly.common.getSelected()?.id]; + return blockIds; + } ); - elseIf.dragAndDrop({x: delta * -25, y: -10}); - await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec - // Check to see that the new configuration has more transform elements - ifDoNumHTML = await ifDo.getHTML(); - const ifDoTransformCountAfter = (ifDoNumHTML.match(/transform/g) || []) - .length; - chai.assert.isTrue(ifDoTransformCountAfter > ifDoTransformCountBefore); + chai.assert.equal(blockIds.length, '3'); } From 3a31ce05d705b91915bb38702a99680a26803e4f Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Mon, 17 Jul 2023 16:09:50 -0400 Subject: [PATCH 05/10] chore: create test for undo block movements and editing a field --- tests/browser/test/mutator_test.js | 8 +++-- tests/browser/test/test_setup.js | 51 ++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js index a11155bf6ee..4320a9704b3 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.js @@ -12,7 +12,7 @@ const chai = require('chai'); const { testSetup, testFileLocations, - getSelectedBlockId, + connect, switchRTL, dragBlockTypeFromFlyout, screenDirection, @@ -69,11 +69,13 @@ async function testingMutator(delta) { const mutatorBlock = Blockly.getMainWorkspace().getAllBlocks()[0]; // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block const mutatorWorkspaceFirstBlock = mutatorBlock.mutator.getWorkspace().getAllBlocks(false)[0].id; - let blockIds=[Blockly.getMainWorkspace().getAllBlocks()[0].id,mutatorWorkspaceFirstBlock,Blockly.common.getSelected()?.id]; + let blockIds=[Blockly.getMainWorkspace().getAllBlocks()[0].id]; return blockIds; } ); + // Connect the mutator blocks + await connect(browser, blockIds[1], 'OUTPUT', blockIds[1], 'RETURN',blockIds[0]); - chai.assert.equal(blockIds.length, '3'); + chai.assert.equal(blockIds, '3'); } diff --git a/tests/browser/test/test_setup.js b/tests/browser/test/test_setup.js index 588b2c52dbe..7f7a1062035 100644 --- a/tests/browser/test/test_setup.js +++ b/tests/browser/test/test_setup.js @@ -205,13 +205,22 @@ async function getBlockTypeFromWorkspace(browser, blockType, position) { * @param id The ID of the block the connection is on. * @param connectionName Which connection to return. An input name * to get a value or statement connection, and otherwise the type of the connection. + * @param mutatorBlockId a string that represents the main block id * @return A Promise that resolves to the location of the specific connection in screen * coordinates. */ -async function getLocationOfBlockConnection(browser, id, connectionName) { +async function getLocationOfBlockConnection(browser, id, connectionName, mutatorBlockId,isSecondBlock) { return await browser.execute( - (id, connectionName) => { - const block = Blockly.getMainWorkspace().getBlockById(id); + (id, connectionName,mutatorBlockId, isSecondBlock) => { + let block; + console.log(id); + if(mutatorBlockId &&!isSecondBlock){ + block = Blockly.getMainWorkspace().getBlockById(mutatorBlockId).mutator.getWorkspace().getBlockById(id); + }else if(mutatorBlockId && isSecondBlock) { + block = Blockly.common.getSelected(); + } else { + block = Blockly.getMainWorkspace().getBlockById(id); + } let connection; switch (connectionName) { @@ -239,7 +248,9 @@ async function getLocationOfBlockConnection(browser, id, connectionName) { ); }, id, - connectionName + connectionName, + mutatorBlockId, + isSecondBlock ); } @@ -250,6 +261,7 @@ async function getLocationOfBlockConnection(browser, id, connectionName) { * @param draggedConnection The active connection on the block being dragged. * @param targetBlock The block to drag to. * @param targetConnection The connection to connect to on the target block. + * @param mutatorBlockId a string that represents the main block id * @return A Promise that resolves when the actions are completed. */ async function connect( @@ -257,18 +269,37 @@ async function connect( draggedBlock, draggedConnection, targetBlock, - targetConnection + targetConnection, + mutatorBlockId ) { - const draggedLocation = await getLocationOfBlockConnection( + let draggedLocation; + let targetLocation; + if(mutatorBlockId){ + draggedLocation = await getLocationOfBlockConnection( + browser, + draggedBlock, + draggedConnection, + mutatorBlockId, + true + ); + targetLocation = await getLocationOfBlockConnection( + browser, + targetBlock, + targetConnection, + mutatorBlockId, + ); +}else{ + draggedLocation = await getLocationOfBlockConnection( browser, draggedBlock.id, - draggedConnection + draggedConnection, ); - const targetLocation = await getLocationOfBlockConnection( + targetLocation = await getLocationOfBlockConnection( browser, targetBlock.id, - targetConnection - ); + targetConnection, + ) +} const delta = { x: targetLocation.x - draggedLocation.x, From 6ba086d7cc8a69616501636c3fbf5c2356a10020 Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Tue, 18 Jul 2023 09:05:12 -0400 Subject: [PATCH 06/10] chore: create mutator test --- core/generator.ts | 7 +- core/main.js | 14 +- generators/python/python_generator.js | 36 ++--- package-lock.json | 4 +- package.json | 2 +- scripts/migration/renamings.json5 | 18 +++ .../browser/test/basic_block_factory_test.js | 2 +- tests/browser/test/basic_block_test.js | 55 ++++++++ tests/browser/test/basic_playground_test.js | 129 +++++++++++++++--- tests/browser/test/block_undo_test.js | 2 +- tests/browser/test/extensive_test.js | 2 +- tests/browser/test/field_edits_test.js | 2 +- tests/browser/test/procedure_test.js | 2 +- tests/browser/test/test_setup.js | 121 ++++++++++------ typings/dart.d.ts | 21 +++ typings/javascript.d.ts | 38 ++++++ typings/lua.d.ts | 15 ++ typings/php.d.ts | 40 ++++++ typings/python.d.ts | 24 ++++ 19 files changed, 433 insertions(+), 101 deletions(-) create mode 100644 tests/browser/test/basic_block_test.js diff --git a/core/generator.ts b/core/generator.ts index 2485e589877..28d6d1f762e 100644 --- a/core/generator.ts +++ b/core/generator.ts @@ -49,7 +49,7 @@ export class CodeGenerator { * legitimately appear in a function definition (or comment), and it must * not confuse the regular expression parser. */ - protected FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}'; + FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}'; FUNCTION_NAME_PLACEHOLDER_REGEXP_: RegExp; /** @@ -471,10 +471,7 @@ export class CodeGenerator { * @returns The actual name of the new function. This may differ from * desiredName if the former has already been taken by the user. */ - protected provideFunction_( - desiredName: string, - code: string[] | string - ): string { + provideFunction_(desiredName: string, code: string[] | string): string { if (!this.definitions_[desiredName]) { const functionName = this.nameDB_!.getDistinctName( desiredName, diff --git a/core/main.js b/core/main.js index 0b8e1a1712a..cc83733d46c 100644 --- a/core/main.js +++ b/core/main.js @@ -32,8 +32,8 @@ Object.defineProperties(Blockly, { * Must be in the range of 0 (inclusive) to 1 (exclusive). * @name Blockly.HSV_SATURATION * @type {number} - * @deprecated Use Blockly.colour.getHsvSaturation() / .setHsvSaturation( - * instead. (July 2023) + * @deprecated Use Blockly.utils.colour.getHsvSaturation() / + * .setHsvSaturation() instead. (July 2023) * @suppress {checkTypes} */ HSV_SATURATION: { @@ -42,7 +42,7 @@ Object.defineProperties(Blockly, { 'Blockly.HSV_SATURATION', 'version 10', 'version 11', - 'Blockly.colour.getHsvSaturation()' + 'Blockly.utils.colour.getHsvSaturation()' ); return colour.getHsvSaturation(); }, @@ -51,7 +51,7 @@ Object.defineProperties(Blockly, { 'Blockly.HSV_SATURATION', 'version 10', 'version 11', - 'Blockly.colour.setHsvSaturation()' + 'Blockly.utils.colour.setHsvSaturation()' ); colour.setHsvSaturation(newValue); }, @@ -61,7 +61,7 @@ Object.defineProperties(Blockly, { * Must be in the range of 0 (inclusive) to 1 (exclusive). * @name Blockly.HSV_VALUE * @type {number} - * @deprecated Use Blockly.colour.getHsvValue() / .setHsvValue instead. + * @deprecated Use Blockly.utils.colour.getHsvValue() / .setHsvValue instead. * (July 2023) * @suppress {checkTypes} */ @@ -71,7 +71,7 @@ Object.defineProperties(Blockly, { 'Blockly.HSV_VALUE', 'version 10', 'version 11', - 'Blockly.colour.getHsvValue()' + 'Blockly.utils.colour.getHsvValue()' ); return colour.getHsvValue(); }, @@ -80,7 +80,7 @@ Object.defineProperties(Blockly, { 'Blockly.HSV_VALUE', 'version 10', 'version 11', - 'Blockly.colour.setHsvValue()' + 'Blockly.utils.colour.setHsvValue()' ); colour.setHsvValue(newValue); }, diff --git a/generators/python/python_generator.js b/generators/python/python_generator.js index 5897b436607..2f0aabe0c13 100644 --- a/generators/python/python_generator.js +++ b/generators/python/python_generator.js @@ -72,7 +72,7 @@ export class PythonGenerator extends CodeGenerator { // (foo.bar)() -> foo.bar() // (foo[0])() -> foo[0]() [Order.MEMBER, Order.FUNCTION_CALL], - + // not (not foo) -> not not foo [Order.LOGICAL_NOT, Order.LOGICAL_NOT], // a and (b and c) -> a and b and c @@ -80,7 +80,7 @@ export class PythonGenerator extends CodeGenerator { // a or (b or c) -> a or b or c [Order.LOGICAL_OR, Order.LOGICAL_OR] ]; - + constructor(name) { super(name ?? 'Python'); this.isInitialized = false; @@ -143,7 +143,7 @@ export class PythonGenerator extends CodeGenerator { 'vars,xrange,zip' ); } - + /** * Initialise the database of variable names. * @param {!Workspace} workspace Workspace to generate code from. @@ -151,22 +151,22 @@ export class PythonGenerator extends CodeGenerator { */ init(workspace) { super.init(workspace); - + /** * Empty loops or conditionals are not allowed in Python. */ this.PASS = this.INDENT + 'pass\n'; - + if (!this.nameDB_) { this.nameDB_ = new Names(this.RESERVED_WORDS_); } else { this.nameDB_.reset(); } - + this.nameDB_.setVariableMap(workspace.getVariableMap()); this.nameDB_.populateVariables(workspace); this.nameDB_.populateProcedures(workspace); - + const defvars = []; // Add developer variables (not created or named by the user). const devVarList = Variables.allDeveloperVariables(workspace); @@ -175,7 +175,7 @@ export class PythonGenerator extends CodeGenerator { this.nameDB_.getName(devVarList[i], Names.DEVELOPER_VARIABLE_TYPE) + ' = None'); } - + // Add user variables, but only ones that are being used. const variables = Variables.allUsedVarModels(workspace); for (let i = 0; i < variables.length; i++) { @@ -183,11 +183,11 @@ export class PythonGenerator extends CodeGenerator { this.nameDB_.getName(variables[i].getId(), NameType.VARIABLE) + ' = None'); } - + this.definitions_['variables'] = defvars.join('\n'); this.isInitialized = true; } - + /** * Prepend the generated code with import statements and variable definitions. * @param {string} code Generated code. @@ -208,12 +208,12 @@ export class PythonGenerator extends CodeGenerator { // Call Blockly.CodeGenerator's finish. code = super.finish(code); this.isInitialized = false; - + this.nameDB_.reset(); const allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; } - + /** * Naked values are top-level blocks with outputs that aren't plugged into * anything. @@ -223,7 +223,7 @@ export class PythonGenerator extends CodeGenerator { scrubNakedValue(line) { return line + '\n'; } - + /** * Encode a string as a properly escaped Python string, complete with quotes. * @param {string} string Text to encode. @@ -232,7 +232,7 @@ export class PythonGenerator extends CodeGenerator { */ quote_(string) { string = string.replace(/\\/g, '\\\\').replace(/\n/g, '\\\n'); - + // Follow the CPython behaviour of repr() for a non-byte string. let quote = '\''; if (string.indexOf('\'') !== -1) { @@ -244,7 +244,7 @@ export class PythonGenerator extends CodeGenerator { } return quote + string + quote; } - + /** * Encode a string as a properly escaped multiline Python string, complete * with quotes. @@ -258,7 +258,7 @@ export class PythonGenerator extends CodeGenerator { // + '\n' + return lines.join(' + \'\\n\' + \n'); } - + /** * Common tasks for generating Python from blocks. * Handles comments for the specified block and any connected value blocks. @@ -297,7 +297,7 @@ export class PythonGenerator extends CodeGenerator { const nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock); return commentCode + code + nextCode; } - + /** * Gets a property and adjusts the value, taking into account indexing. * If a static int, casts to an integer, otherwise returns a code string. @@ -315,7 +315,7 @@ export class PythonGenerator extends CodeGenerator { const defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; const atOrder = delta ? this.ORDER_ADDITIVE : this.ORDER_NONE; let at = this.valueToCode(block, atId, atOrder) || defaultAtIndex; - + if (stringUtils.isNumber(at)) { // If the index is a naked number, adjust it right now. at = parseInt(at, 10) + delta; diff --git a/package-lock.json b/package-lock.json index d8c25f0c7f5..5d4019525bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "blockly", - "version": "10.0.1", + "version": "10.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "blockly", - "version": "10.0.1", + "version": "10.0.2", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index a5c91d25f98..354553b55a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blockly", - "version": "10.0.1", + "version": "10.0.2", "description": "Blockly is a library for building visual programming editors.", "keywords": [ "blockly" diff --git a/scripts/migration/renamings.json5 b/scripts/migration/renamings.json5 index ee1c33834f7..97fbc3fc0fc 100644 --- a/scripts/migration/renamings.json5 +++ b/scripts/migration/renamings.json5 @@ -1577,5 +1577,23 @@ }, ], + '10.0.1': [ + { + oldName: 'Blockly', + exports: { + HSV_SATURATION: { + newModule: 'Blockly.utils.colour', + getMethod: 'getHsvSaturation', + setMethod: 'setHsvSaturation', + }, + HSV_VALUE: { + newModule: 'Blockly.utils.colour', + getMethod: 'getHsvValue', + setMethod: 'setHsvValue', + }, + }, + }, + ], + 'develop': [], } diff --git a/tests/browser/test/basic_block_factory_test.js b/tests/browser/test/basic_block_factory_test.js index cd9f098006d..def7ef0ef5f 100644 --- a/tests/browser/test/basic_block_factory_test.js +++ b/tests/browser/test/basic_block_factory_test.js @@ -18,7 +18,7 @@ suite('Testing Connecting Blocks', function (done) { // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.blockfactory); + browser = await testSetup(testFileLocations.BLOCK_FACTORY); }); test('Testing Block Drag', async function () { diff --git a/tests/browser/test/basic_block_test.js b/tests/browser/test/basic_block_test.js new file mode 100644 index 00000000000..4a2a3ea2080 --- /dev/null +++ b/tests/browser/test/basic_block_test.js @@ -0,0 +1,55 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Node.js script to run Automated tests in Chrome, via + * webdriver, of basic Blockly block functionality. + */ + +const chai = require('chai'); +const { + testSetup, + testFileLocations, + getAllBlocks, + getSelectedBlockElement, + switchRTL, + dragBlockTypeFromFlyout, + screenDirection, +} = require('./test_setup'); +const {Key} = require('webdriverio'); + +let browser; + +suite('Basic block tests', function (done) { + // Setting timeout to unlimited as the webdriver takes a longer time + // to run than most mocha test + this.timeout(0); + + // Setup Selenium for all of the tests + suiteSetup(async function () { + browser = await testSetup( + testFileLocations.PLAYGROUND + '?toolbox=test-blocks' + ); + }); + + test('Drag three blocks into the workspace', async function () { + for (let i = 1; i <= 3; i++) { + await dragBlockTypeFromFlyout( + browser, + 'Basic', + 'test_basic_empty', + 250, + 50 * i + ); + chai.assert.equal((await getAllBlocks(browser)).length, i); + } + }); + + // Teardown entire suite after test are done running + suiteTeardown(async function () { + await browser.deleteSession(); + }); +}); diff --git a/tests/browser/test/basic_playground_test.js b/tests/browser/test/basic_playground_test.js index dd93549297e..2805be12cde 100644 --- a/tests/browser/test/basic_playground_test.js +++ b/tests/browser/test/basic_playground_test.js @@ -13,6 +13,8 @@ const { testSetup, testFileLocations, dragNthBlockFromFlyout, + dragBlockTypeFromFlyout, + connect, contextMenuSelect, } = require('./test_setup'); @@ -22,9 +24,10 @@ async function getIsCollapsed(browser, blockId) { }, blockId); } -async function getIsEnabled(browser, blockId) { +async function getIsDisabled(browser, blockId) { return await browser.execute((blockId) => { - return Blockly.getMainWorkspace().getBlockById(blockId).isEnabled(); + const block = Blockly.getMainWorkspace().getBlockById(blockId); + return !block.isEnabled() || block.getInheritedDisabled(); }, blockId); } @@ -35,13 +38,13 @@ async function getCommentText(browser, blockId) { } let browser; -suite('Testing Connecting Blocks', function (done) { +suite('Testing Connecting Blocks', function () { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test this.timeout(0); // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.playground); + browser = await testSetup(testFileLocations.PLAYGROUND); }); test('Testing Block Flyout', async function () { @@ -74,52 +77,46 @@ suite('Testing Connecting Blocks', function (done) { * These tests have to run together. Each test acts on the state left by the * previous test, and each test has a single assertion. */ -suite('Right Clicking on Blocks', function (done) { +suite('Right Clicking on Blocks', function () { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test this.timeout(0); // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.playground); + browser = await testSetup(testFileLocations.PLAYGROUND); this.block = await dragNthBlockFromFlyout(browser, 'Loops', 0, 20, 20); this.blockId = this.block.id; }); test('clicking the collapse option collapses the block', async function () { await contextMenuSelect(browser, this.block, 'Collapse Block'); - const isCollapsed = await getIsCollapsed(browser, this.blockId); - chai.assert.isTrue(isCollapsed); + chai.assert.isTrue(await getIsCollapsed(browser, this.blockId)); }); // Assumes that test('clicking the expand option expands the block', async function () { await contextMenuSelect(browser, this.block, 'Expand Block'); - const isCollapsed = await getIsCollapsed(browser, this.blockId); - chai.assert.isFalse(isCollapsed); + chai.assert.isFalse(await getIsCollapsed(browser, this.blockId)); }); test('clicking the disable option disables the block', async function () { await contextMenuSelect(browser, this.block, 'Disable Block'); - const isEnabled = await getIsEnabled(browser, this.blockId); - chai.assert.isFalse(isEnabled); + chai.assert.isTrue(await getIsDisabled(browser, this.blockId)); }); test('clicking the enable option enables the block', async function () { await contextMenuSelect(browser, this.block, 'Enable Block'); - const isEnabled = await getIsEnabled(browser, this.block.id); - chai.assert.isTrue(isEnabled); + chai.assert.isFalse(await getIsDisabled(browser, this.block.id)); }); test('clicking the add comment option adds a comment to the block', async function () { await contextMenuSelect(browser, this.block, 'Add Comment'); - const commentText = await getCommentText(browser, this.block.id); - chai.assert.equal(commentText, ''); + chai.assert.equal(await getCommentText(browser, this.block.id), ''); }); test('clicking the remove comment option removes a comment from the block', async function () { await contextMenuSelect(browser, this.block, 'Remove Comment'); - const commentText = await getCommentText(browser, this.block.id); - chai.assert.isNull(commentText); + chai.assert.isNull(await getCommentText(browser, this.block.id)); }); // Teardown entire suite after test are done running @@ -127,3 +124,99 @@ suite('Right Clicking on Blocks', function (done) { await browser.deleteSession(); }); }); + +suite('Disabling', function () { + // Setting timeout to unlimited as the webdriver takes a longer + // time to run than most mocha tests. + this.timeout(0); + + suiteSetup(async function () { + browser = await testSetup(testFileLocations.PLAYGROUND); + }); + + setup(async function () { + await browser.refresh(); + }); + + test( + 'children connected to value inputs are disabled when the ' + + 'parent is diabled', + async function () { + const parent = await dragBlockTypeFromFlyout( + browser, + 'Logic', + 'controls_if', + 10, + 10 + ); + const child = await dragBlockTypeFromFlyout( + browser, + 'Logic', + 'logic_boolean', + 110, + 110 + ); + await connect(browser, child, 'OUTPUT', parent, 'IF0'); + + await contextMenuSelect(browser, parent, 'Disable Block'); + + chai.assert.isTrue(await getIsDisabled(browser, child.id)); + } + ); + + test( + 'children connected to statement inputs are disabled when the ' + + 'parent is disabled', + async function () { + const parent = await dragBlockTypeFromFlyout( + browser, + 'Logic', + 'controls_if', + 10, + 10 + ); + const child = await dragBlockTypeFromFlyout( + browser, + 'Logic', + 'controls_if', + 110, + 110 + ); + await connect(browser, child, 'PREVIOUS', parent, 'IF0'); + + await contextMenuSelect(browser, parent, 'Disable Block'); + + chai.assert.isTrue(await getIsDisabled(browser, child.id)); + } + ); + + test( + 'children connected to next connections are not disabled when the ' + + 'parent is disabled', + async function () { + const parent = await dragBlockTypeFromFlyout( + browser, + 'Logic', + 'controls_if', + 10, + 10 + ); + const child = await dragBlockTypeFromFlyout( + browser, + 'Logic', + 'controls_if', + 110, + 110 + ); + await connect(browser, child, 'PREVIOUS', parent, 'NEXT'); + + await contextMenuSelect(browser, parent, 'Disable Block'); + + chai.assert.isFalse(await getIsDisabled(browser, child.id)); + } + ); + + suiteTeardown(async function () { + await browser.deleteSession(); + }); +}); diff --git a/tests/browser/test/block_undo_test.js b/tests/browser/test/block_undo_test.js index d11c95c5360..1acfbd6f9be 100644 --- a/tests/browser/test/block_undo_test.js +++ b/tests/browser/test/block_undo_test.js @@ -25,7 +25,7 @@ suite('Testing undo block movement', function (done) { // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.playground); + browser = await testSetup(testFileLocations.PLAYGROUND); }); test('Undoing Block Movement LTR', async function () { diff --git a/tests/browser/test/extensive_test.js b/tests/browser/test/extensive_test.js index edfd5d3b970..015877400d6 100644 --- a/tests/browser/test/extensive_test.js +++ b/tests/browser/test/extensive_test.js @@ -23,7 +23,7 @@ suite('This tests loading Large Configuration and Deletion', function (done) { // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.playground); + browser = await testSetup(testFileLocations.PLAYGROUND); }); test('This test loading from JSON results in the correct number of blocks', async function () { diff --git a/tests/browser/test/field_edits_test.js b/tests/browser/test/field_edits_test.js index b7a25c75b64..5a88b7b8f65 100644 --- a/tests/browser/test/field_edits_test.js +++ b/tests/browser/test/field_edits_test.js @@ -26,7 +26,7 @@ suite('Testing Field Edits', function (done) { // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.playground); + browser = await testSetup(testFileLocations.PLAYGROUND); }); test('Testing Field Edits LTR', async function () { diff --git a/tests/browser/test/procedure_test.js b/tests/browser/test/procedure_test.js index e8890d988f0..0a675a836a5 100644 --- a/tests/browser/test/procedure_test.js +++ b/tests/browser/test/procedure_test.js @@ -26,7 +26,7 @@ suite('Testing Connecting Blocks', function (done) { // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.code); + browser = await testSetup(testFileLocations.CODE_DEMO); }); test('Testing Procedure', async function () { diff --git a/tests/browser/test/test_setup.js b/tests/browser/test/test_setup.js index 7f7a1062035..fa674d9f475 100644 --- a/tests/browser/test/test_setup.js +++ b/tests/browser/test/test_setup.js @@ -5,8 +5,11 @@ */ /** - * @fileoverview Node.js script to run automated functional tests in Chrome, via webdriver. + * @fileoverview Node.js script to run automated functional tests in + * Chrome, via webdriver. + * * This file is to be used in the suiteSetup for any automated fuctional test. + * * Note: In this file many functions return browser elements that can * be clicked or otherwise interacted with through Selenium WebDriver. These * elements are not the raw HTML and SVG elements on the page; they are @@ -18,8 +21,7 @@ const path = require('path'); const {posixPath} = require('../../../scripts/helpers'); let browser; -async function testSetup(testFile) { - let url; +async function testSetup(url) { const options = { capabilities: { 'browserName': 'chrome', @@ -45,25 +47,6 @@ async function testSetup(testFile) { options.capabilities['goog:chromeOptions'].args.push('--disable-gpu'); } // Use Selenium to bring up the page - if (testFile == testFileLocations.blockfactory) { - url = - 'file://' + - posixPath( - path.join(__dirname, '..', '..', '..', 'demos', 'blockfactory') - ) + - '/index.html'; - } else if (testFile == testFileLocations.code) { - url = - 'file://' + - posixPath(path.join(__dirname, '..', '..', '..', 'demos', 'code')) + - '/index.html'; - } else { - url = - 'file://' + - posixPath(path.join(__dirname, '..', '..')) + - '/playground.html'; - } - console.log(url); console.log('Starting webdriverio...'); browser = await webdriverio.remote(options); console.log('Loading URL: ' + url); @@ -72,13 +55,23 @@ async function testSetup(testFile) { } const testFileLocations = { - blockfactory: 0, - code: 1, - playground: 2, + BLOCK_FACTORY: + 'file://' + + posixPath(path.join(__dirname, '..', '..', '..', 'demos', 'blockfactory')) + + '/index.html', + CODE_DEMO: + 'file://' + + posixPath(path.join(__dirname, '..', '..', '..', 'demos', 'code')) + + '/index.html', + PLAYGROUND: + 'file://' + + posixPath(path.join(__dirname, '..', '..')) + + '/playground.html', }; /** * Enum for both LTR and RTL use cases. + * * @readonly * @enum {number} */ @@ -146,8 +139,8 @@ async function getCategory(browser, categoryName) { * @param browser The active WebdriverIO Browser object. * @param categoryName The name of the toolbox category to search. * @param n Which block to select, 0-indexed from the top of the category. - * @return A Promise that resolves to the root element of the nth block in the - * given category. + * @return A Promise that resolves to the root element of the nth + * block in the given category. */ async function getNthBlockOfCategory(browser, categoryName, n) { const category = await getCategory(browser, categoryName); @@ -163,8 +156,8 @@ async function getNthBlockOfCategory(browser, categoryName, n) { * @param browser The active WebdriverIO Browser object. * @param categoryName The name of the toolbox category to search. * @param blockType The type of the block to search for. - * @return A Promise that resolves to the root element of the first block with the - * given type in the given category. + * @return A Promise that resolves to the root element of the first + * block with the given type in the given category. */ async function getBlockTypeFromCategory(browser, categoryName, blockType) { const category = await getCategory(browser, categoryName); @@ -242,6 +235,7 @@ async function getLocationOfBlockConnection(browser, id, connectionName, mutator block.getRelativeToSurfaceXY(), connection.getOffsetInBlock() ); + console.log(Blockly); return Blockly.utils.svgMath.wsToScreenCoordinates( Blockly.getMainWorkspace(), loc @@ -256,6 +250,7 @@ async function getLocationOfBlockConnection(browser, id, connectionName, mutator /** * Drags a block toward another block so that the specified connections attach. + * * @param browser The active WebdriverIO Browser object. * @param draggedBlock The block to drag. * @param draggedConnection The active connection on the block being dragged. @@ -310,6 +305,7 @@ async function connect( /** * Switch the playground to RTL mode. + * * @param browser The active WebdriverIO Browser object. * @return A Promise that resolves when the actions are completed. */ @@ -321,14 +317,16 @@ async function switchRTL(browser) { /** * Drag the specified block from the flyout and return the root element * of the block. + * * @param browser The active WebdriverIO Browser object. * @param categoryName The name of the toolbox category to search. * @param n Which block to select, indexed from the top of the category. - * @param x The x-distance to drag, as a delta from the block's initial location - * on screen. - * @param y The y-distance to drag, as a delta from the block's initial location - * on screen. - * @return A Promise that resolves to the root element of the newly created block. + * @param x The x-distance to drag, as a delta from the block's + * initial location on screen. + * @param y The y-distance to drag, as a delta from the block's + * initial location on screen. + * @return A Promise that resolves to the root element of the newly + * created block. */ async function dragNthBlockFromFlyout(browser, categoryName, n, x, y) { const flyoutBlock = await getNthBlockOfCategory(browser, categoryName, n); @@ -339,14 +337,16 @@ async function dragNthBlockFromFlyout(browser, categoryName, n, x, y) { /** * Drag the specified block from the flyout and return the root element * of the block. + * * @param browser The active WebdriverIO Browser object. * @param categoryName The name of the toolbox category to search. * @param type The type of the block to search for. - * @param x The x-distance to drag, as a delta from the block's initial location - * on screen. - * @param y The y-distance to drag, as a delta from the block's initial location - * on screen. - * @return A Promise that resolves to the root element of the newly created block. + * @param x The x-distance to drag, as a delta from the block's + * initial location on screen. + * @param y The y-distance to drag, as a delta from the block's + * initial location on screen. + * @return A Promise that resolves to the root element of the newly + * created block. */ async function dragBlockTypeFromFlyout(browser, categoryName, type, x, y) { const flyoutBlock = await getBlockTypeFromCategory( @@ -359,19 +359,49 @@ async function dragBlockTypeFromFlyout(browser, categoryName, type, x, y) { } /** - * Right-click on the specified block, then click on the specified context menu - * item. + * Right-click on the specified block, then click on the specified + * context menu item. + * * @param browser The active WebdriverIO Browser object. * @param block The block to click, as an interactable element. * @param itemText The display text of the context menu item to click. * @return A Promise that resolves when the actions are completed. */ async function contextMenuSelect(browser, block, itemText) { - await block.click({button: 2}); - await browser.pause(200); + // Clicking will always happen in the middle of the block's bounds + // (including children) by default, which causes problems if it has holes + // (e.g. statement inputs). + // Instead we want to click 20% from the right and 5% from the top. + const xOffset = -Math.round((await block.getSize('width')) * 0.3); + const yOffset = -Math.round((await block.getSize('height')) * 0.45); + + await block.click({button: 2, x: xOffset, y: yOffset}); + await browser.pause(100); + const item = await browser.$(`div=${itemText}`); await item.click(); - await browser.pause(200); + + await browser.pause(100); +} + +/** + * Get all blocks on the main workspace. Because the blocks have circular + * references that can't be JSON-encoded they can't be returned directly, so + * extract relevant properties only. + * + * @param browser The active WebdriverIO Browser object. + * @return A Promise that resolves to an array of blocks on the main workspace. + */ +async function getAllBlocks(browser) { + return browser.execute(() => { + // return Blockly.getMainWorkspace().getAllBlocks(false); + return Blockly.getMainWorkspace() + .getAllBlocks(false) + .map((block) => ({ + type: block.type, + id: block.id, + })); + }); } module.exports = { @@ -384,10 +414,11 @@ module.exports = { getNthBlockOfCategory, getBlockTypeFromCategory, dragNthBlockFromFlyout, + dragBlockTypeFromFlyout, connect, switchRTL, contextMenuSelect, - dragBlockTypeFromFlyout, screenDirection, getBlockTypeFromWorkspace, + getAllBlocks, }; diff --git a/typings/dart.d.ts b/typings/dart.d.ts index a547e00fe5d..4dda479a497 100644 --- a/typings/dart.d.ts +++ b/typings/dart.d.ts @@ -4,4 +4,25 @@ * SPDX-License-Identifier: Apache-2.0 */ +export enum Order { + ATOMIC = 0, // 0 "" ... + UNARY_POSTFIX = 1, // expr++ expr-- () [] . ?. + UNARY_PREFIX = 2, // -expr !expr ~expr ++expr --expr + MULTIPLICATIVE = 3, // * / % ~/ + ADDITIVE = 4, // + - + SHIFT = 5, // << >> + BITWISE_AND = 6, // & + BITWISE_XOR = 7, // ^ + BITWISE_OR = 8, // | + RELATIONAL = 9, // >= > <= < as is is! + EQUALITY = 10, // == != + LOGICAL_AND = 11, // && + LOGICAL_OR = 12, // || + IF_NULL = 13, // ?? + CONDITIONAL = 14, // expr ? expr : expr + CASCADE = 15, // .. + ASSIGNMENT = 16, // = *= /= ~/= %= += -= <<= >>= &= ^= |= + NONE = 99, // (...) +} + export declare const dartGenerator: any; diff --git a/typings/javascript.d.ts b/typings/javascript.d.ts index cbb55fd65c9..b507a9be4a4 100644 --- a/typings/javascript.d.ts +++ b/typings/javascript.d.ts @@ -4,4 +4,42 @@ * SPDX-License-Identifier: Apache-2.0 */ +export enum Order { + ATOMIC = 0, // 0 "" ... + NEW = 1.1, // new + MEMBER = 1.2, // . [] + FUNCTION_CALL = 2, // () + INCREMENT = 3, // ++ + DECREMENT = 3, // -- + BITWISE_NOT = 4.1, // ~ + UNARY_PLUS = 4.2, // + + UNARY_NEGATION = 4.3, // - + LOGICAL_NOT = 4.4, // ! + TYPEOF = 4.5, // typeof + VOID = 4.6, // void + DELETE = 4.7, // delete + AWAIT = 4.8, // await + EXPONENTIATION = 5.0, // ** + MULTIPLICATION = 5.1, // * + DIVISION = 5.2, // / + MODULUS = 5.3, // % + SUBTRACTION = 6.1, // - + ADDITION = 6.2, // + + BITWISE_SHIFT = 7, // << >> >>> + RELATIONAL = 8, // < <= > >= + IN = 8, // in + INSTANCEOF = 8, // instanceof + EQUALITY = 9, // == != === !== + BITWISE_AND = 10, // & + BITWISE_XOR = 11, // ^ + BITWISE_OR = 12, // | + LOGICAL_AND = 13, // && + LOGICAL_OR = 14, // || + CONDITIONAL = 15, // ?: + ASSIGNMENT = 16, // = += -= **= *= /= %= <<= >>= ... + YIELD = 17, // yield + COMMA = 18, // , + NONE = 99, // (...) +} + export declare const javascriptGenerator: any; diff --git a/typings/lua.d.ts b/typings/lua.d.ts index 551c67772f7..693fb0ba25f 100644 --- a/typings/lua.d.ts +++ b/typings/lua.d.ts @@ -4,4 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ +export enum Order { + ATOMIC = 0, // literals + // The next level was not explicit in documentation and inferred by Ellen. + HIGH = 1, // Function calls, tables[] + EXPONENTIATION = 2, // ^ + UNARY = 3, // not # - ~ + MULTIPLICATIVE = 4, // * / % + ADDITIVE = 5, // + - + CONCATENATION = 6, // .. + RELATIONAL = 7, // < > <= >= ~= == + AND = 8, // and + OR = 9, // or + NONE = 99, +} + export declare const luaGenerator: any; diff --git a/typings/php.d.ts b/typings/php.d.ts index df438507ae9..29a223613be 100644 --- a/typings/php.d.ts +++ b/typings/php.d.ts @@ -4,4 +4,44 @@ * SPDX-License-Identifier: Apache-2.0 */ +export enum Order { + ATOMIC = 0, // 0 "" ... + CLONE = 1, // clone + NEW = 1, // new + MEMBER = 2.1, // [] + FUNCTION_CALL = 2.2, // () + POWER = 3, // ** + INCREMENT = 4, // ++ + DECREMENT = 4, // -- + BITWISE_NOT = 4, // ~ + CAST = 4, // (int) (float) (string) (array) ... + SUPPRESS_ERROR = 4, // @ + INSTANCEOF = 5, // instanceof + LOGICAL_NOT = 6, // ! + UNARY_PLUS = 7.1, // + + UNARY_NEGATION = 7.2, // - + MULTIPLICATION = 8.1, // * + DIVISION = 8.2, // / + MODULUS = 8.3, // % + ADDITION = 9.1, // + + SUBTRACTION = 9.2, // - + STRING_CONCAT = 9.3, // . + BITWISE_SHIFT = 10, // << >> + RELATIONAL = 11, // < <= > >= + EQUALITY = 12, // == != === !== <> <=> + REFERENCE = 13, // & + BITWISE_AND = 13, // & + BITWISE_XOR = 14, // ^ + BITWISE_OR = 15, // | + LOGICAL_AND = 16, // && + LOGICAL_OR = 17, // || + IF_NULL = 18, // ?? + CONDITIONAL = 19, // ?: + ASSIGNMENT = 20, // = += -= *= /= %= <<= >>= ... + LOGICAL_AND_WEAK = 21, // and + LOGICAL_XOR = 22, // xor + LOGICAL_OR_WEAK = 23, // or + NONE = 99, // (...) +} + export declare const phpGenerator: any; diff --git a/typings/python.d.ts b/typings/python.d.ts index ab931669b18..6d6449e3791 100644 --- a/typings/python.d.ts +++ b/typings/python.d.ts @@ -4,4 +4,28 @@ * SPDX-License-Identifier: Apache-2.0 */ +export enum Order { + ATOMIC = 0, // 0 "" ... + COLLECTION = 1, // tuples, lists, dictionaries + STRING_CONVERSION = 1, // `expression...` + MEMBER = 2.1, // . [] + FUNCTION_CALL = 2.2, // () + EXPONENTIATION = 3, // ** + UNARY_SIGN = 4, // + - + BITWISE_NOT = 4, // ~ + MULTIPLICATIVE = 5, // * / // % + ADDITIVE = 6, // + - + BITWISE_SHIFT = 7, // << >> + BITWISE_AND = 8, // & + BITWISE_XOR = 9, // ^ + BITWISE_OR = 10, // | + RELATIONAL = 11, // in, not in, is, is not, >, >=, <>, !=, == + LOGICAL_NOT = 12, // not + LOGICAL_AND = 13, // and + LOGICAL_OR = 14, // or + CONDITIONAL = 15, // if else + LAMBDA = 16, // lambda + NONE = 99, // (...) +} + export declare const pythonGenerator: any; From bc4198398592316538779a3fb26d536ac14a377a Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Thu, 20 Jul 2023 15:54:19 -0400 Subject: [PATCH 07/10] chore: create mutator test --- tests/browser/test/mutator_test.js | 58 ++++++++++++++++++++++-------- tests/browser/test/test_setup.js | 49 +++++++++++++++++++++---- 2 files changed, 85 insertions(+), 22 deletions(-) diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js index 4320a9704b3..dd5f2011a0d 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.js @@ -15,32 +15,27 @@ const { connect, switchRTL, dragBlockTypeFromFlyout, + getSelectedBlockId, screenDirection, } = require('./test_setup'); let browser; -suite('Testing Mutator', function (done) { +suite('This tests mutating a Blockly block', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test this.timeout(0); // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.playground); + browser = await testSetup(testFileLocations.PLAYGROUND); }); - test('Testing Field Edits LTR', async function () { + test('This test mutating a block creates more inputs', async function () { await testingMutator(screenDirection.LTR); }); - /* - test('Testing Field Edits RTL', async function () { - await switchRTL(browser); - await testingMutator(screenDirection.RTL); - }); - */ // Teardown entire suite after test are done running suiteTeardown(async function () { - //await browser.deleteSession(); + await browser.deleteSession(); }); }); @@ -58,24 +53,57 @@ async function testingMutator(delta) { '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected > g.blocklyIconGroup' ); await mutatorWheel.click(); + await browser.pause(100); const elseIfFlyout = await browser.$( '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyFlyout > g > g.blocklyBlockCanvas > g:nth-child(3)' ); - elseIfFlyout.dragAndDrop({x: delta * 50, y: 42}); + await elseIfFlyout.dragAndDrop({x: delta * 50, y: 42}); + // Get the original number of mutator inputs + await browser.pause(100); + + // Get the ids for block before mutating + originalInputs = await browser.execute( + () => { + const originalInputs = Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; + // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block + + return originalInputs; + } + ); + await browser.pause(100); // Get the ids for the blocks in the mutator blockIds = await browser.execute( () => { const mutatorBlock = Blockly.getMainWorkspace().getAllBlocks()[0]; // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block - const mutatorWorkspaceFirstBlock = mutatorBlock.mutator.getWorkspace().getAllBlocks(false)[0].id; - let blockIds=[Blockly.getMainWorkspace().getAllBlocks()[0].id]; + const blockIds=[mutatorBlock.id,mutatorBlock.mutator.getWorkspace().getAllBlocks()[0].id,mutatorBlock.mutator.getWorkspace().getAllBlocks()[1].id]; return blockIds; } ); + + // Click on the mutator and drag out else ig block + const dragBlockSelector = await browser.$( + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable' + ); + // For some reason this needs a lot more time + await browser.pause(2000); // Connect the mutator blocks - await connect(browser, blockIds[1], 'OUTPUT', blockIds[1], 'RETURN',blockIds[0]); + await connect(browser, blockIds[2], 'PREVIOUS', blockIds[1], 'NEXT',blockIds[0],dragBlockSelector); + + // For some reason this needs a lot more time + await browser.pause(200); + + // Get the ids for block after mutating + afterInputs = await browser.execute( + () => { + const afterInputs = Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; + // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block + + return afterInputs; + } + ); - chai.assert.equal(blockIds, '3'); + chai.assert.isTrue(afterInputs>originalInputs); } diff --git a/tests/browser/test/test_setup.js b/tests/browser/test/test_setup.js index edc54bc4939..9c10815124a 100644 --- a/tests/browser/test/test_setup.js +++ b/tests/browser/test/test_setup.js @@ -199,13 +199,20 @@ async function getBlockTypeFromWorkspace(browser, blockType, position) { * @param connectionName Which connection to return. An input name to * get a value or statement connection, and otherwise the type of * the connection. + * @param mutatorBlockId The block that holds the mutator icon * @return A Promise that resolves to the location of the specific * connection in screen coordinates. */ -async function getLocationOfBlockConnection(browser, id, connectionName) { +async function getLocationOfBlockConnection(browser, id, connectionName, mutatorBlockId) { return await browser.execute( - (id, connectionName) => { - const block = Blockly.getMainWorkspace().getBlockById(id); + (id, connectionName,mutatorBlockId) => { + let block; + if(mutatorBlockId){ + block = Blockly.getMainWorkspace().getBlockById(mutatorBlockId).mutator.getWorkspace().getBlockById(id); + + }else{ + block= Blockly.getMainWorkspace().getBlockById(id); + } let connection; switch (connectionName) { @@ -234,7 +241,8 @@ async function getLocationOfBlockConnection(browser, id, connectionName) { ); }, id, - connectionName + connectionName, + mutatorBlockId ); } @@ -246,6 +254,7 @@ async function getLocationOfBlockConnection(browser, id, connectionName) { * @param draggedConnection The active connection on the block being dragged. * @param targetBlock The block to drag to. * @param targetConnection The connection to connect to on the target block. + * @param mutatorBlockId The block that holds the mutator icon * @return A Promise that resolves when the actions are completed. */ async function connect( @@ -253,24 +262,50 @@ async function connect( draggedBlock, draggedConnection, targetBlock, - targetConnection + targetConnection, + mutatorBlockId, + dragBlockSelector ) { - const draggedLocation = await getLocationOfBlockConnection( + + let draggedLocation; + let targetLocation + + if(mutatorBlockId){ + draggedLocation = await getLocationOfBlockConnection( + browser, + draggedBlock, + draggedConnection, + mutatorBlockId + ); + targetLocation = await getLocationOfBlockConnection( + browser, + targetBlock, + targetConnection, + mutatorBlockId + ); + + }else{ + draggedLocation = await getLocationOfBlockConnection( browser, draggedBlock.id, draggedConnection ); - const targetLocation = await getLocationOfBlockConnection( + targetLocation = await getLocationOfBlockConnection( browser, targetBlock.id, targetConnection ); + } const delta = { x: targetLocation.x - draggedLocation.x, y: targetLocation.y - draggedLocation.y, }; + if(mutatorBlockId){ + await dragBlockSelector.dragAndDrop(delta); + }else{ await draggedBlock.dragAndDrop(delta); + } } /** From 8806d7a371d14ffd6b89223a9856fff45ecc2dcc Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Thu, 20 Jul 2023 15:58:20 -0400 Subject: [PATCH 08/10] chore: create mutator test --- tests/browser/test/mutator_test.js | 71 ++++++++++++++++-------------- tests/browser/test/test_setup.js | 59 +++++++++++++------------ 2 files changed, 71 insertions(+), 59 deletions(-) diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js index dd5f2011a0d..4399804733b 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.js @@ -61,49 +61,56 @@ async function testingMutator(delta) { // Get the original number of mutator inputs await browser.pause(100); - // Get the ids for block before mutating - originalInputs = await browser.execute( - () => { - const originalInputs = Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; - // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block - - return originalInputs; - } - ); + // Get the ids for block before mutating + const originalInputs = await browser.execute(() => { + const originalInputs = + Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; + // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block + + return originalInputs; + }); await browser.pause(100); - // Get the ids for the blocks in the mutator - blockIds = await browser.execute( - () => { - const mutatorBlock = Blockly.getMainWorkspace().getAllBlocks()[0]; - // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block - const blockIds=[mutatorBlock.id,mutatorBlock.mutator.getWorkspace().getAllBlocks()[0].id,mutatorBlock.mutator.getWorkspace().getAllBlocks()[1].id]; - return blockIds; - } - ); + // Get the ids for the blocks in the mutator + const blockIds = await browser.execute(() => { + const mutatorBlock = Blockly.getMainWorkspace().getAllBlocks()[0]; + // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block + const blockIds = [ + mutatorBlock.id, + mutatorBlock.mutator.getWorkspace().getAllBlocks()[0].id, + mutatorBlock.mutator.getWorkspace().getAllBlocks()[1].id, + ]; + return blockIds; + }); // Click on the mutator and drag out else ig block const dragBlockSelector = await browser.$( '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable' ); - // For some reason this needs a lot more time + // For some reason this needs a lot more time await browser.pause(2000); - // Connect the mutator blocks - await connect(browser, blockIds[2], 'PREVIOUS', blockIds[1], 'NEXT',blockIds[0],dragBlockSelector); + // Connect the mutator blocks + await connect( + browser, + blockIds[2], + 'PREVIOUS', + blockIds[1], + 'NEXT', + blockIds[0], + dragBlockSelector + ); - // For some reason this needs a lot more time + // For some reason this needs a lot more time await browser.pause(200); - // Get the ids for block after mutating - afterInputs = await browser.execute( - () => { - const afterInputs = Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; - // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block - - return afterInputs; - } - ); + // Get the ids for block after mutating + const afterInputs = await browser.execute(() => { + const afterInputs = + Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; + // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block + return afterInputs; + }); - chai.assert.isTrue(afterInputs>originalInputs); + chai.assert.isTrue(afterInputs > originalInputs); } diff --git a/tests/browser/test/test_setup.js b/tests/browser/test/test_setup.js index 7cbe1e58a44..ee250927bf0 100644 --- a/tests/browser/test/test_setup.js +++ b/tests/browser/test/test_setup.js @@ -206,15 +206,22 @@ async function getBlockTypeFromWorkspace(browser, blockType, position) { * @return A Promise that resolves to the location of the specific * connection in screen coordinates. */ -async function getLocationOfBlockConnection(browser, id, connectionName, mutatorBlockId) { +async function getLocationOfBlockConnection( + browser, + id, + connectionName, + mutatorBlockId +) { return await browser.execute( - (id, connectionName,mutatorBlockId) => { - let block; - if(mutatorBlockId){ - block = Blockly.getMainWorkspace().getBlockById(mutatorBlockId).mutator.getWorkspace().getBlockById(id); - - }else{ - block= Blockly.getMainWorkspace().getBlockById(id); + (id, connectionName, mutatorBlockId) => { + let block; + if (mutatorBlockId) { + block = Blockly.getMainWorkspace() + .getBlockById(mutatorBlockId) + .mutator.getWorkspace() + .getBlockById(id); + } else { + block = Blockly.getMainWorkspace().getBlockById(id); } let connection; @@ -270,11 +277,10 @@ async function connect( mutatorBlockId, dragBlockSelector ) { - let draggedLocation; - let targetLocation + let targetLocation; - if(mutatorBlockId){ + if (mutatorBlockId) { draggedLocation = await getLocationOfBlockConnection( browser, draggedBlock, @@ -287,28 +293,27 @@ async function connect( targetConnection, mutatorBlockId ); - - }else{ - draggedLocation = await getLocationOfBlockConnection( - browser, - draggedBlock.id, - draggedConnection - ); - targetLocation = await getLocationOfBlockConnection( - browser, - targetBlock.id, - targetConnection - ); + } else { + draggedLocation = await getLocationOfBlockConnection( + browser, + draggedBlock.id, + draggedConnection + ); + targetLocation = await getLocationOfBlockConnection( + browser, + targetBlock.id, + targetConnection + ); } const delta = { x: targetLocation.x - draggedLocation.x, y: targetLocation.y - draggedLocation.y, }; - if(mutatorBlockId){ + if (mutatorBlockId) { await dragBlockSelector.dragAndDrop(delta); - }else{ - await draggedBlock.dragAndDrop(delta); + } else { + await draggedBlock.dragAndDrop(delta); } } @@ -431,4 +436,4 @@ module.exports = { screenDirection, getBlockTypeFromWorkspace, getAllBlocks, -}; \ No newline at end of file +}; From cda94a186cd279c4c2b2abf75ed132a63d325ede Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Thu, 20 Jul 2023 16:13:59 -0400 Subject: [PATCH 09/10] chore: create mutator test --- tests/browser/test/mutator_test.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js index 4399804733b..6e7f44fc88f 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.js @@ -65,8 +65,6 @@ async function testingMutator(delta) { const originalInputs = await browser.execute(() => { const originalInputs = Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; - // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block - return originalInputs; }); @@ -83,7 +81,7 @@ async function testingMutator(delta) { return blockIds; }); - // Click on the mutator and drag out else ig block + // The flyout block and the workspace block have the same id, so to get around that I pass in the selector to the connect function const dragBlockSelector = await browser.$( '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable' ); @@ -107,8 +105,6 @@ async function testingMutator(delta) { const afterInputs = await browser.execute(() => { const afterInputs = Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; - // Adding the first element in the array is the original block id, the second is the first mutator block, and the third is the second mutator block - return afterInputs; }); From 5e6fd1381f824318a8771198b384487ddf3085f7 Mon Sep 17 00:00:00 2001 From: Eric Blackmon Date: Thu, 27 Jul 2023 08:29:51 -0400 Subject: [PATCH 10/10] chore: create mutator test --- tests/browser/test/mutator_test.js | 34 ++++++++---------------------- tests/browser/test/test_setup.js | 21 ++++++++---------- 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js index 6e7f44fc88f..f4f4b20154c 100644 --- a/tests/browser/test/mutator_test.js +++ b/tests/browser/test/mutator_test.js @@ -19,55 +19,41 @@ const { screenDirection, } = require('./test_setup'); -let browser; suite('This tests mutating a Blockly block', function (done) { // Setting timeout to unlimited as the webdriver takes a longer time to run than most mocha test this.timeout(0); // Setup Selenium for all of the tests suiteSetup(async function () { - browser = await testSetup(testFileLocations.PLAYGROUND); + this.browser = await testSetup(testFileLocations.PLAYGROUND); }); test('This test mutating a block creates more inputs', async function () { - await testingMutator(screenDirection.LTR); - }); - - // Teardown entire suite after test are done running - suiteTeardown(async function () { - await browser.deleteSession(); + await testingMutator(this.browser, screenDirection.LTR); }); }); -async function testingMutator(delta) { +async function testingMutator(browser, delta) { // Drag out print from flyout. const controlIfFlyout = await dragBlockTypeFromFlyout( browser, 'Logic', 'controls_if', delta * 50, - 50 + 50, ); // Click on the mutator and drag out else ig block const mutatorWheel = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected > g.blocklyIconGroup' + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBlockCanvas > g.blocklyDraggable.blocklySelected > g.blocklyIconGroup', ); await mutatorWheel.click(); await browser.pause(100); const elseIfFlyout = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyFlyout > g > g.blocklyBlockCanvas > g:nth-child(3)' + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyFlyout > g > g.blocklyBlockCanvas > g:nth-child(3)', ); await elseIfFlyout.dragAndDrop({x: delta * 50, y: 42}); - // Get the original number of mutator inputs await browser.pause(100); - // Get the ids for block before mutating - const originalInputs = await browser.execute(() => { - const originalInputs = - Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; - return originalInputs; - }); - await browser.pause(100); // Get the ids for the blocks in the mutator const blockIds = await browser.execute(() => { @@ -83,7 +69,7 @@ async function testingMutator(delta) { // The flyout block and the workspace block have the same id, so to get around that I pass in the selector to the connect function const dragBlockSelector = await browser.$( - '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable' + '#blocklyDiv > div > svg.blocklySvg > g > g.blocklyBubbleCanvas > g > g:nth-child(2) > svg:nth-child(1) > g > g.blocklyBlockCanvas > g.blocklyDraggable', ); // For some reason this needs a lot more time await browser.pause(2000); @@ -95,10 +81,8 @@ async function testingMutator(delta) { blockIds[1], 'NEXT', blockIds[0], - dragBlockSelector + dragBlockSelector, ); - - // For some reason this needs a lot more time await browser.pause(200); // Get the ids for block after mutating @@ -108,5 +92,5 @@ async function testingMutator(delta) { return afterInputs; }); - chai.assert.isTrue(afterInputs > originalInputs); + chai.assert.equal(afterInputs, 4); } diff --git a/tests/browser/test/test_setup.js b/tests/browser/test/test_setup.js index 59a8421cef9..9376db984f2 100644 --- a/tests/browser/test/test_setup.js +++ b/tests/browser/test/test_setup.js @@ -220,7 +220,7 @@ async function getBlockTypeFromWorkspace(browser, blockType, position) { * @param connectionName Which connection to return. An input name to * get a value or statement connection, and otherwise the type of * the connection. - * @param mutatorBlockId The block that holds the mutator icon + * @param mutatorBlockId The block that holds the mutator icon or null if the target block is on the main workspace * @return A Promise that resolves to the location of the specific * connection in screen coordinates. */ @@ -228,7 +228,7 @@ async function getLocationOfBlockConnection( browser, id, connectionName, - mutatorBlockId + mutatorBlockId, ) { return await browser.execute( (id, connectionName, mutatorBlockId) => { @@ -269,10 +269,7 @@ async function getLocationOfBlockConnection( }, id, connectionName, -<<<<<<< HEAD - mutatorBlockId -======= ->>>>>>> upstream/develop + mutatorBlockId, ); } @@ -284,7 +281,7 @@ async function getLocationOfBlockConnection( * @param draggedConnection The active connection on the block being dragged. * @param targetBlock The block to drag to. * @param targetConnection The connection to connect to on the target block. - * @param mutatorBlockId The block that holds the mutator icon + * @param mutatorBlockId The block that holds the mutator icon or null if the target block is on the main workspace * @param dragBlockSelector The selector of the block to drag * @return A Promise that resolves when the actions are completed. */ @@ -295,7 +292,7 @@ async function connect( targetBlock, targetConnection, mutatorBlockId, - dragBlockSelector + dragBlockSelector, ) { let draggedLocation; let targetLocation; @@ -305,24 +302,24 @@ async function connect( browser, draggedBlock, draggedConnection, - mutatorBlockId + mutatorBlockId, ); targetLocation = await getLocationOfBlockConnection( browser, targetBlock, targetConnection, - mutatorBlockId + mutatorBlockId, ); } else { draggedLocation = await getLocationOfBlockConnection( browser, draggedBlock.id, - draggedConnection + draggedConnection, ); targetLocation = await getLocationOfBlockConnection( browser, targetBlock.id, - targetConnection + targetConnection, ); }