diff --git a/tests/browser/test/mutator_test.js b/tests/browser/test/mutator_test.js new file mode 100644 index 00000000000..f4f4b20154c --- /dev/null +++ b/tests/browser/test/mutator_test.js @@ -0,0 +1,96 @@ +/** + * @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, + connect, + switchRTL, + dragBlockTypeFromFlyout, + getSelectedBlockId, + screenDirection, +} = require('./test_setup'); + +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 () { + this.browser = await testSetup(testFileLocations.PLAYGROUND); + }); + + test('This test mutating a block creates more inputs', async function () { + await testingMutator(this.browser, screenDirection.LTR); + }); +}); + +async function testingMutator(browser, delta) { + // Drag out print from flyout. + const controlIfFlyout = await dragBlockTypeFromFlyout( + browser, + 'Logic', + 'controls_if', + delta * 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', + ); + 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)', + ); + await elseIfFlyout.dragAndDrop({x: delta * 50, y: 42}); + await browser.pause(100); + + await browser.pause(100); + // 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; + }); + + // 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', + ); + // 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, + ); + await browser.pause(200); + + // Get the ids for block after mutating + const afterInputs = await browser.execute(() => { + const afterInputs = + Blockly.getMainWorkspace().getAllBlocks()[0].inputList.length; + return afterInputs; + }); + + chai.assert.equal(afterInputs, 4); +} diff --git a/tests/browser/test/test_setup.js b/tests/browser/test/test_setup.js index 386c94b4df8..9376db984f2 100644 --- a/tests/browser/test/test_setup.js +++ b/tests/browser/test/test_setup.js @@ -220,13 +220,27 @@ 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 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. */ -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) { @@ -255,6 +269,7 @@ async function getLocationOfBlockConnection(browser, id, connectionName) { }, id, connectionName, + mutatorBlockId, ); } @@ -266,6 +281,8 @@ 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 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. */ async function connect( @@ -274,24 +291,47 @@ async function connect( draggedConnection, targetBlock, targetConnection, + mutatorBlockId, + dragBlockSelector, ) { - const draggedLocation = await getLocationOfBlockConnection( - browser, - draggedBlock.id, - draggedConnection, - ); - const targetLocation = await getLocationOfBlockConnection( - browser, - targetBlock.id, - targetConnection, - ); + 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, + ); + targetLocation = await getLocationOfBlockConnection( + browser, + targetBlock.id, + targetConnection, + ); + } const delta = { x: targetLocation.x - draggedLocation.x, y: targetLocation.y - draggedLocation.y, }; - await draggedBlock.dragAndDrop(delta); - await browser.pause(200); + if (mutatorBlockId) { + await dragBlockSelector.dragAndDrop(delta); + } else { + await draggedBlock.dragAndDrop(delta); + } } /**