-
Notifications
You must be signed in to change notification settings - Fork 13
chore: Add tests for focus after deletion. #531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
johnnesky
merged 5 commits into
RaspberryPiFoundation:main
from
johnnesky:nesky_delete_tests
May 19, 2025
Merged
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
8115d40
chore: Add tests for focus after deletion.
johnnesky c95259b
Formatting fixes.
johnnesky a7a94df
Added comment clarifying why the test is adding a block.
johnnesky 91bc13c
Remove ".only" from test suite to enable other tests.
johnnesky ccbb281
Fix lint errors.
johnnesky File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2025 Google LLC | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import * as chai from 'chai'; | ||
| import { | ||
| blockIsPresent, | ||
| currentFocusIsMainWorkspace, | ||
| setCurrentCursorNodeById, | ||
| getCurrentFocusNodeId, | ||
| getFocusedBlockType, | ||
| moveToToolboxCategory, | ||
| testSetup, | ||
| testFileLocations, | ||
| PAUSE_TIME, | ||
| tabNavigateToWorkspace, | ||
| } from './test_setup.js'; | ||
| import {Key} from 'webdriverio'; | ||
|
|
||
| suite.only('Deleting Blocks', function () { | ||
| // Setting timeout to unlimited as these tests take a longer time to run than most mocha test | ||
| this.timeout(0); | ||
|
|
||
| setup(async function () { | ||
| this.browser = await testSetup(testFileLocations.NAVIGATION_TEST_BLOCKS); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| }); | ||
|
|
||
| test('Deleting block selects previous connection', async function () { | ||
| await tabNavigateToWorkspace(this.browser); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| await setCurrentCursorNodeById(this.browser, 'controls_if_2'); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'controls_if_2')) | ||
| .equal(true); | ||
|
|
||
| await this.browser.keys(Key.Backspace); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'controls_if_2')) | ||
| .equal(false); | ||
|
|
||
| chai | ||
| .expect(await getCurrentFocusNodeId(this.browser)) | ||
| .to.include('controls_if_1_connection_'); | ||
| }); | ||
|
|
||
| test('Cutting block selects previous connection', async function () { | ||
| await tabNavigateToWorkspace(this.browser); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| await setCurrentCursorNodeById(this.browser, 'controls_if_2'); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'controls_if_2')) | ||
| .equal(true); | ||
|
|
||
| await this.browser.keys([Key.Ctrl, 'x']); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'controls_if_2')) | ||
| .equal(false); | ||
|
|
||
| chai | ||
| .expect(await getCurrentFocusNodeId(this.browser)) | ||
| .to.include('controls_if_1_connection_'); | ||
| }); | ||
|
|
||
| test('Deleting block also deletes children and inputs', async function () { | ||
| await tabNavigateToWorkspace(this.browser); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| await setCurrentCursorNodeById(this.browser, 'controls_if_2'); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'logic_boolean_1')) | ||
| .equal(true); | ||
| chai.expect(await blockIsPresent(this.browser, 'text_print_1')).equal(true); | ||
|
|
||
| await this.browser.keys(Key.Backspace); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'logic_boolean_1')) | ||
| .equal(false); | ||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'text_print_1')) | ||
| .equal(false); | ||
| }); | ||
|
|
||
| test('Cutting block also removes children and inputs', async function () { | ||
| await tabNavigateToWorkspace(this.browser); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| await setCurrentCursorNodeById(this.browser, 'controls_if_2'); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'logic_boolean_1')) | ||
| .equal(true); | ||
| chai.expect(await blockIsPresent(this.browser, 'text_print_1')).equal(true); | ||
|
|
||
| await this.browser.keys([Key.Ctrl, 'x']); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'logic_boolean_1')) | ||
| .equal(false); | ||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'text_print_1')) | ||
| .equal(false); | ||
| }); | ||
|
|
||
| test('Deleting inline input selects parent connection', async function () { | ||
| await tabNavigateToWorkspace(this.browser); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| await setCurrentCursorNodeById(this.browser, 'logic_boolean_1'); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'logic_boolean_1')) | ||
| .equal(true); | ||
|
|
||
| await this.browser.keys(Key.Backspace); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'logic_boolean_1')) | ||
| .equal(false); | ||
|
|
||
| chai | ||
| .expect(await getCurrentFocusNodeId(this.browser)) | ||
| .to.include('controls_if_2_connection_'); | ||
| }); | ||
|
|
||
| test('Cutting inline input selects parent connection', async function () { | ||
| await tabNavigateToWorkspace(this.browser); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| await setCurrentCursorNodeById(this.browser, 'logic_boolean_1'); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'logic_boolean_1')) | ||
| .equal(true); | ||
|
|
||
| await this.browser.keys([Key.Ctrl, 'x']); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai | ||
| .expect(await blockIsPresent(this.browser, 'logic_boolean_1')) | ||
| .equal(false); | ||
|
|
||
| chai | ||
| .expect(await getCurrentFocusNodeId(this.browser)) | ||
| .to.include('controls_if_2_connection_'); | ||
| }); | ||
|
|
||
| test('Deleting stranded block selects workspace', async function () { | ||
| await tabNavigateToWorkspace(this.browser); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| // The test workspace doesn't already contain a stranded block, so add one. | ||
| await moveToToolboxCategory(this.browser, 'Math'); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| // Move to flyout. | ||
| await this.browser.keys(Key.ArrowRight); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| // Select number block. | ||
| await this.browser.keys(Key.Enter); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| // Confirm move. | ||
| await this.browser.keys(Key.Enter); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai.assert.equal('math_number', await getFocusedBlockType(this.browser)); | ||
|
|
||
| await this.browser.keys(Key.Backspace); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai.expect(await currentFocusIsMainWorkspace(this.browser)).equal(true); | ||
| }); | ||
|
|
||
| test('Cutting stranded block selects workspace', async function () { | ||
| await tabNavigateToWorkspace(this.browser); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| // The test workspace doesn't already contain a stranded block, so add one. | ||
| await moveToToolboxCategory(this.browser, 'Math'); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| // Move to flyout. | ||
| await this.browser.keys(Key.ArrowRight); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| // Select number block. | ||
| await this.browser.keys(Key.Enter); | ||
| await this.browser.pause(PAUSE_TIME); | ||
| // Confirm move. | ||
| await this.browser.keys(Key.Enter); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai.assert.equal('math_number', await getFocusedBlockType(this.browser)); | ||
|
|
||
| await this.browser.keys([Key.Ctrl, 'x']); | ||
| await this.browser.pause(PAUSE_TIME); | ||
|
|
||
| chai.expect(await currentFocusIsMainWorkspace(this.browser)).equal(true); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -171,6 +171,62 @@ | |
| await workspaceElement.click(); | ||
| } | ||
|
|
||
| /** | ||
|
Check warning on line 174 in test/webdriverio/test/test_setup.ts
|
||
| * Focuses the toolbox category with the given name. | ||
| * | ||
| * @param browser The active WebdriverIO Browser object. | ||
| * @param blockId The id of the block. | ||
|
Check warning on line 178 in test/webdriverio/test/test_setup.ts
|
||
| */ | ||
| export async function moveToToolboxCategory( | ||
| browser: WebdriverIO.Browser, | ||
| category: string, | ||
| ) { | ||
| await browser.keys('t'); | ||
| const categoryIndex = await browser.execute((category) => { | ||
| const all = Array.from( | ||
| document.querySelectorAll('.blocklyToolboxCategoryLabel'), | ||
| ).map((node) => node.textContent); | ||
| return all.indexOf(category); | ||
| }, category); | ||
| if (categoryIndex < 0) { | ||
| throw new Error(`No category found: ${category}`); | ||
| } | ||
| if (categoryIndex > 0) { | ||
| await browser.keys(webdriverio.Key.ArrowDown.repeat(categoryIndex)); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Returns whether the workspace contains a block with the given id. | ||
| * | ||
| * @param browser The active WebdriverIO Browser object. | ||
| * @param blockId The id of the block. | ||
| */ | ||
| export async function blockIsPresent( | ||
| browser: WebdriverIO.Browser, | ||
| blockId: string, | ||
| ): Promise<boolean> { | ||
| return await browser.execute((blockId) => { | ||
| const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg; | ||
| const block = workspaceSvg.getBlockById(blockId); | ||
| return block !== null; | ||
| }, blockId); | ||
| } | ||
|
|
||
| /** | ||
| * Returns whether the main workspace is the current focus. | ||
| * | ||
| * @param browser The active WebdriverIO Browser object. | ||
| */ | ||
| export async function currentFocusIsMainWorkspace( | ||
| browser: WebdriverIO.Browser, | ||
| ): Promise<boolean> { | ||
| return await browser.execute(() => { | ||
| const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg; | ||
| return Blockly.getFocusManager().getFocusedNode() === workspaceSvg; | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Select a block with the given id as the current cursor node. | ||
| * | ||
|
|
@@ -191,7 +247,7 @@ | |
| } | ||
|
|
||
| /** | ||
| * Select a block with the given id as the current cursor node. | ||
| * Select a block's field with the given block id and field name. | ||
| * | ||
| * @param browser The active WebdriverIO Browser object. | ||
| * @param blockId The id of the block to select. | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.