Commit Graph

136 Commits

Author SHA1 Message Date
Ben Henning
bea183d85d fix: Auto-close widget divs on lost focus (#9216)
## The basics

- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)

## The details
### Resolves

Fixes https://github.com/google/blockly-keyboard-experimentation/issues/563

### Proposed Changes

This expands the functionality introduced in #9213 to also include widget divs.

### Reason for Changes

MakeCode makes use of widget div in several field editors, so the issues described in https://github.com/google/blockly-keyboard-experimentation/issues/563 aren't fully mitigated with #9213 alone.

This PR essentially adds the same support for auto-closing as drop-down divs now have, and enables this functionality by default.

Note the drop-down div change: it was missed in #9123 that the API change for drop-down div's `show` function is actually API-breaking, so this updates that API to be properly backward compatible (and reverts one test change that makes use of it).

The `FocusManager` change actually corrects an implementation issue from #9123: not updating the tracked focus status before calling the callback can result in focus being inadvertently restored if the callback triggers returning focus due to a lost focus situation. This was wrong for drop-down divs, too, but it's harder to notice there because the dismissal of the drop-down div happens on a timer (which means there's sufficient time for `FocusManager`'s state to correct prior to attempting to return from the ephemeral focus state).

Demonstration of fixed behavior (since the inline number editor uses a widget div):

[Screen recording 2025-07-08 2.12.31 PM.webm](https://github.com/user-attachments/assets/7c3c7c3c-224c-48f4-b4af-bde86feecfa8)

### Test Coverage

New widget div tests have been added to verify the new parameter and auto-close functionality.

The `FocusManager` test was updated to account for the new, and correct, behavior around the internal tracked ephemeral focus state.

Note that some `tabindex` state has been clarified and cleaned up in the test index page and `FocusManager`. It's fine (and preferable) for ephemeral-used elements to always be focusable rather than making them dynamically so (which avoids state bleed across test runs which was happening one of the new tests).

https://github.com/google/blockly-keyboard-experimentation/pull/649 includes additional tests for validating widget behaviors.

### Documentation

No new documentation should be needed here--the API documentation changes should be sufficient.

One documentation update was made in `dropdowndiv.ts` that corrects the documentation parameter ordering.

### Additional Information

Nothing further to add.
2025-07-08 16:06:24 -07:00
Ben Henning
0e16b0405a fix: Auto close drop-down divs on lost focus (reapply) (#9213)
## The basics

- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)

## The details
### Resolves

Fixes https://github.com/google/blockly-keyboard-experimentation/issues/563

### Proposed Changes

This introduces support in `FocusManager` to receive feedback on when an ephemerally focused element entirely loses focus (that is, neither it nor any of its descendants have focus).

This also introduces a behavior change for drop-down divs using the previously mentioned functionality to automatically close themselves when they lose focus for any reason (e.g. clicking outside of the div or tab navigating away from it).

Finally, and **importantly**, this adds a case where ephemeral focus does _not_ automatically return to the previously focused node: when focus is lost to the ephemerally focused element's tree and isn't instead put on another focused node.

### Reason for Changes

Ultimately, focus is probably the best proxy for cases when a drop-down div ought to no longer be open. However, tracking focus only within the scope of the drop-down div utility is rather difficult since a lot of the same problems that `FocusManager` handles also occur here (with regards to both descendants and outside elements receiving focus). It made more sense to expand `FocusManager`'s ephemeral focus support:
- It was easier to implement this `FocusManager` and in a way that's much more robust (since it's leveraging existing event handlers).
- Using `FocusManager` trivialized the solution for drop-down divs.
- There could be other use cases where custom ephemeral focus uses might benefit from knowing when they lose focus.

This new support is enabled by default for all drop-down divs, but can be disabled by callers if they wish to revert to the previous behavior of not auto-closing.

The change for whether to restore ephemeral focus was needed to fix a drawback that arises from the automatic returning of ephemeral focus introduced in this PR: when a user clicks out of an open drop-down menu it will restore focus back to the node that held focus prior to taking ephemeral focus (since it properly hides the drop-down div and restores focus). This creates awkward behavior issues for both mouse and keyboard users:
- For mouse: trying to open a drop-down outside of Blockly will automatically close the drop-down when the Blockly drop-down finishes closing (since focus is stolen back away from the thing the user clicked on).
- For keyboard: tab navigating out of Blockly tries to force focus back to Blockly.

**New in v2 of this PR**: Commit 0363d67c18 is the main one that prevents #9203 from being reintroduced by ensuring that widget div only clears its contents after ephemeral focus has returned. This was missed in the first audit since it wasn't clear that this line, in particular, can cause a div with focus to be removed and thus focus lost: dfd565957b/core/widgetdiv.ts (L156)

### Test Coverage

New tests have been added for both the drop-down div and `FocusManager` components, and have been verified as failing without the new behaviors in place.

There may be other edge cases worth testing for `FocusManager` in particular, but the tests introduced in this PR seem to cover the most important cases.

**New in v2 of this PR**: A test was added to validate that widget div now clears its contents only after ephemeral focus has returned to avoid the desyncing scenario that led to #9203. This test has been verified to fail without the fix. There are also a few new tests being added in the keyboard navigation plugin repository that also validate this behavior at a higher level (see https://github.com/google/blockly-keyboard-experimentation/pull/649).

Demonstration of the new behavior:

[Screen recording 2025-07-01 6.28.37 PM.webm](https://github.com/user-attachments/assets/7af29fed-1ba1-4828-a6cd-65bb94509e72)

### Documentation

No new documentation changes seem needed beyond the code documentation updates.

### Additional Information

It's also possible to change the automatic restoration behavior to be conditional instead of always assuming focus shouldn't be reset if focus leaves the ephemeral element, but that's probably a better change if there's an actual user issue discovered with this approach.

This was originally introduced in #9175 but it was reverted in #9204 due to #9203.
2025-07-07 15:52:38 -07:00
Christopher Allen
7ad18f717a Revert "fix: Auto close drop-down divs on lost focus (#9175)" (#9204)
This reverts commit 4c78c1d4a3 / PR #9175.
2025-07-07 09:40:58 -07:00
Ben Henning
4c78c1d4a3 fix: Auto close drop-down divs on lost focus (#9175)
## The basics

- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)

## The details
### Resolves

Fixes https://github.com/google/blockly-keyboard-experimentation/issues/563

### Proposed Changes

This introduces support in `FocusManager` to receive feedback on when an ephemerally focused element entirely loses focus (that is, neither it nor any of its descendants have focus).

This also introduces a behavior change for drop-down divs using the previously mentioned functionality to automatically close themselves when they lose focus for any reason (e.g. clicking outside of the div or tab navigating away from it).

Finally, and **importantly**, this adds a case where ephemeral focus does _not_ automatically return to the previously focused node: when focus is lost to the ephemerally focused element's tree and isn't instead put on another focused node.

### Reason for Changes

Ultimately, focus is probably the best proxy for cases when a drop-down div ought to no longer be open. However, tracking focus only within the scope of the drop-down div utility is rather difficult since a lot of the same problems that `FocusManager` handles also occur here (with regards to both descendants and outside elements receiving focus). It made more sense to expand `FocusManager`'s ephemeral focus support:
- It was easier to implement this `FocusManager` and in a way that's much more robust (since it's leveraging existing event handlers).
- Using `FocusManager` trivialized the solution for drop-down divs.
- There could be other use cases where custom ephemeral focus uses might benefit from knowing when they lose focus.

This new support is enabled by default for all drop-down divs, but can be disabled by callers if they wish to revert to the previous behavior of not auto-closing.

The change for whether to restore ephemeral focus was needed to fix a drawback that arises from the automatic returning of ephemeral focus introduced in this PR: when a user clicks out of an open drop-down menu it will restore focus back to the node that held focus prior to taking ephemeral focus (since it properly hides the drop-down div and restores focus). This creates awkward behavior issues for both mouse and keyboard users:
- For mouse: trying to open a drop-down outside of Blockly will automatically close the drop-down when the Blockly drop-down finishes closing (since focus is stolen back away from the thing the user clicked on).
- For keyboard: tab navigating out of Blockly tries to force focus back to Blockly.

### Test Coverage

New tests have been added for both the drop-down div and `FocusManager` components, and have been verified as failing without the new behaviors in place.

There may be other edge cases worth testing for `FocusManager` in particular, but the tests introduced in this PR seem to cover the most important cases.

Demonstration of the new behavior:

[Screen recording 2025-07-01 6.28.37 PM.webm](https://github.com/user-attachments/assets/7af29fed-1ba1-4828-a6cd-65bb94509e72)

### Documentation

No new documentation changes seem needed beyond the code documentation updates.

### Additional Information

It's also possible to change the automatic restoration behavior to be conditional instead of always assuming focus shouldn't be reset if focus leaves the ephemeral element, but that's probably a better change if there's an actual user issue discovered with this approach.
2025-07-02 16:11:50 -07:00
Maribeth Moffatt
0498ed6174 feat: add keyboard navigation controller (#8924)
* feat: add keyboard navigation controller

* chore: add tests

* chore: fix tsdoc
2025-05-29 13:48:54 -07:00
Ben Henning
3cbca8e4b6 feat: Automatically manage focus tree tab indexes (#9079)
## The basics

- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)

## The details
### Resolves

Fixes #8965
Fixes #8978
Fixes #8970
Fixes https://github.com/google/blockly-keyboard-experimentation/issues/523
Fixes https://github.com/google/blockly-keyboard-experimentation/issues/547
Fixes part of #8910

### Proposed Changes

Fives groups of changes are included in this PR:
1. Support for automatic tab index management for focusable trees.
2. Support for automatic tab index management for focusable nodes.
3. Support for automatically hiding the flyout when back navigating from the toolbox.
4. A fix for `FocusManager` losing DOM syncing that was introduced in #9082.
5. Some cleanups for flyout and some tests for previous behavior changes to `FocusManager`.

### Reason for Changes

Infrastructure changes reasoning:
- Automatically managing tab indexes for both focusable trees and roots can largely reduce the difficulty of providing focusable nodes/trees and generally interacting with `FocusManager`. This facilitates a more automated navigation experience.
- The fix for losing DOM syncing is possibly not reliable, but there are at least now tests to cover for it. This may be a case where a `try{} finally{}` could be warranted, but the code will stay as-is unless requested otherwise.

`Flyout` changes:
- `Flyout` no longer needs to be a focusable tree, but removing that would be an API breakage. Instead, it throws for most of the normal tree/node calls as it should no longer be used as such. Instead, its workspace has been made top-level tabbable (in addition to the  main workspace) which solves the extra tab stop issues and general confusing inconsistencies between the flyout, toolbox, and workspace.
- `Flyout` now correctly auto-selects the first block (#9103 notwithstanding). Technically it did before, however the extra `Flyout` tabstop before its workspace caused the inconsistency (since focusing the `Flyout` itself did not auto-select, only selecting its workspace did).

Important caveats:
- `getAttribute` is used in place of directly fetching `.tabIndex` since the latter can apparently default to `-1` (and possibly `0`) in cases when it's not actually set. This is a very surprising behavior that leads to incorrect test results.
- Sometimes tab index still needs to be introduced (such as in cases where native DOM focus is needed, e.g. via `focus()` calls or clicking). This is demonstrated both by updates to `FocusManager`'s tests as well as toolbox's category and separator. This can be slightly tricky to miss as large parts of Blockly now depend on focus to represent their state, so clicking either needs to be managed by Blockly (with corresponding `focusNode` calls) or automatic (with a tab index defined for the element that can be clicked, or which has a child that can be clicked).

Note that nearly all elements used for testing focus in the test `index.html` page have had their tab indexes removed to lean on `FocusManager`'s automatic tab management (though as mentioned above there is still some manual tab index management required for `focus()`-specific tests).

### Test Coverage

New tests were added for all of the updated behaviors to `FocusManager`, including a new need to explicitly provide (and reset) tab indexes for all `focus()`-esque tests. This also includes adding new tests for some behaviors introduced in past PRs (a la #8910).

Note that all of the new and affected conditionals in `FocusManager` have been verified as having at least 1 test that breaks when it's removed (inverted conditions weren't thoroughly tested, but it's expected that they should also be well covered now).

Additional tests to cover the actual navigation flows will be added to the keyboard experimentation plugin repository as part of https://github.com/google/blockly-keyboard-experimentation/pull/557 (this PR needs to be merged first).

For manual testing, I mainly verified keyboard navigation with some cursory mouse & click testing in the simple playground. @rachel-fenichel also performed more thorough mouse & click testing (that yielded an actual issue that was fixed--see discussion below).

The core webdriver tests have been verified to have seemingly the same existing failures with and without these changes.

All of the following new keyboard navigation plugin tests have been verified as failing without the fixes introduced in this branch (and passing with them):
- `Tab navigating to flyout should auto-select first block`
- `Keyboard nav to different toolbox category should auto-select first block`
- `Keyboard nav to different toolbox category and block should select different block`
- `Tab navigate away from toolbox restores focus to initial element`
- `Tab navigate away from toolbox closes flyout`
- `Tab navigate away from flyout to toolbox and away closes flyout`
- `Tabbing to the workspace after selecting flyout block should close the flyout`
- `Tabbing to the workspace after selecting flyout block via workspace toolbox shortcut should close the flyout`
- `Tabbing back from workspace should reopen the flyout`
- `Navigation position in workspace should be retained when tabbing to flyout and back`
- `Clicking outside Blockly with focused toolbox closes the flyout`
- `Clicking outside Blockly with focused flyout closes the flyout`
- `Clicking on toolbox category focuses it and opens flyout`

### Documentation

No documentation changes are needed beyond the code doc changes included in the PR.

### Additional Information

An additional PR will be introduced for the keyboard experimentation plugin repository to add tests there (see test coverage above). This description will be updated with a link to that PR once it exists.
2025-05-29 12:09:59 -07:00
Rachel Fenichel
b6b229eb44 fix!: delete marker move event and tests (#9013) 2025-05-08 10:52:43 -07:00
Aaron Dodson
acdad98653 refactor!: Use navigation rulesets instead of ASTNode to control keyboard navigation. (#8992)
* feat: Add interfaces for keyboard navigation.

* feat: Add the Navigator.

* feat: Make core types conform to INavigable.

* feat: Require FlyoutItems elements to be INavigable.

* feat: Add navigation policies for built-in types.

* refactor: Convert Marker and LineCursor to operate on INavigables instead of ASTNodes.

* chore: Delete dead code in ASTNode.

* fix: Fix the tests.

* chore: Assuage the linter.

* fix: Fix advanced build/tests.

* chore: Restore ASTNode tests.

* refactor: Move isNavigable() validation into Navigator.

* refactor: Exercise navigation instead of ASTNode.

* chore: Rename astnode_test.js to navigation_test.js.

* chore: Enable the navigation tests.

* fix: Fix bug when retrieving the first child of an empty workspace.
2025-05-07 08:47:52 -07:00
Maribeth Moffatt
86c831a3fe fix: use copyable interface for cut action, add tests (#8993)
* fix: use copyable for cut action

* chore: rename keydown test

* chore: add tests for shortcut items not acting on focused connections
2025-05-06 11:37:28 -07:00
Aaron Dodson
c6e58c4f92 feat: Add support for displaying toast-style notifications. (#8896)
* feat: Allow resetting alert/prompt/confirm to defaults.

* chore: Add unit tests for Blockly.dialog.

* fix: Removed TEST_ONLY hack from Blockly.dialog.

* feat: Add a default toast notification implementation.

* feat: Add support for toasts to Blockly.dialog.

* chore: Add tests for default toast implementation.

* chore: Fix docstring.

* refactor: Use default arguments for dialog functions.

* refactor: Add 'close' to the list of messages.

* chore: Add new message in several other places.

* chore: clarify docstrings.

* feat: Make toast assertiveness configurable.
2025-04-21 15:32:45 -07:00
Ben Henning
3dc4d17b30 Update tests/mocha/index.html 2025-03-27 16:54:19 -07:00
Ben Henning
9ab77cedff chore: fix formatting issues 2025-03-27 22:04:51 +00:00
Ben Henning
516e3af936 feat: finish core impl + tests
This adds new tests for the FocusableTreeTraverser and fixes a number of
issues with the original implementation (one of which required two new
API methods to be added to IFocusableTree). More tests have also been
added for FocusManager, and defocusing tracked nodes/trees has been
fully implemented in FocusManager.
2025-03-27 21:57:30 +00:00
Ben Henning
d9beacddb4 feat: add FocusManager
This is the bulk of the work for introducing the central logical unit
for managing and sychronizing focus as a first-class Blockly concept
with that of DOM focus.

There's a lot to do yet, including:
- Ensuring clicks within Blockly's scope correctly sync back to focus
  changes.
- Adding support for, and testing, cases when focus is lost from all
  registered trees.
- Testing nested tree propagation.
- Testing the traverser utility class.
- Adding implementations for IFocusableTree and IFocusableNode
  throughout Blockly.
2025-03-21 00:33:51 +00:00
Aaron Dodson
9fcd5a3037 release: Merge branch 'rc/v11.2.0' into rc/v12.0.0 2024-12-04 12:06:12 -08:00
Aaron Dodson
2523093cc9 refactor!: Remove the InsertionMarkerManager. (#8649)
* refactor!: Remove the InsertionMarkerManager.

* chore: Remove unused imports.

* chore: Remove import of insertion marker manager test.
2024-11-07 12:15:55 -08:00
Ben Henning
3a3e83fe44 Fix workspace clean up not considering immovables.
At a high-level, this change ensures that cleaning up a workspace
doesn't move blocks in a way that overlaps with immovable blocks. It
also adds missing testing coverage for both Rect (used for bounding box
calculations during workspace cleanup) and WorkspaceSvg (for verifying
the updated clean up functionality).

This also renames the clean up function to be 'tidyUp' since that better
suits what's happening (as opposed to other clean-up routines which are
actually deinitializing objects).
2024-08-21 17:41:38 +00:00
Aaron Dodson
82c7aad4e7 feat: Add a VarTypeChange event. (#8402)
* feat: Add a VarTypeChange event.

* chore: Update copyright date.

* refactor: Inline fields in the constructor.
2024-07-29 12:00:52 -07:00
John Nesky
9a0619aa2a fix: Drag and Resize events for workspace comments (#8217)
* feat: Added a comment_drag event.

* Add workspace comment resize events.

* Addressing PR feedback.

* Fixed chai imports in new test files.

* Addressing more PR feedback.
2024-06-26 12:16:56 -07:00
dependabot[bot]
bfb5b1dd49 chore(deps): Bump chai from 4.3.10 to 5.1.1 (#8092)
* chore(deps): Bump chai from 4.3.10 to 5.1.1

  Bumps [chai](https://github.com/chaijs/chai) from 4.3.10 to 5.1.1.
  - [Release notes](https://github.com/chaijs/chai/releases)
  - [Changelog](https://github.com/chaijs/chai/blob/main/History.md)
  - [Commits](https://github.com/chaijs/chai/compare/v4.3.10...v5.1.1)

  ---
  updated-dependencies:
  - dependency-name: chai
    dependency-type: direct:development
    update-type: version-update:semver-major
  ...

  Signed-off-by: dependabot[bot] <support@github.com>

* fix(tests): Migrate all usage of chai to ESM (#8216)

* fix(tests): Migrate node tests from CJS to ESM

  This allows us to import (rather than require) chai, fixing failures
  caused by that package dropping suppport for CJS in chai v5.0.0.

* fix(tests): Have mocha tests directly import chai

  Previously they relied on obtaining it from the global scope, but it's
  better if imports are explicit.

* fix(tests): Remove broken load of chai as script

  Chai v5.0.0 no longer supports being loaded as a script, so this did
  nothing but emit an syntax error message on the console.

* fix(tests): Migrate browser tests from CJS to ESM

  This allows us to import (rather than require) chai, fixing failures
  caused by chai no longer supporting CJS.

* chore(tests): format

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Christopher Allen <cpcallen+git@google.com>
2024-06-17 16:48:21 +01:00
Beka Westberg
c704d5a887 revert: "feat: allow the dialog methods to take in extra parameters (#8084)" (#8085)
This reverts commit 278006b5f8.
2024-05-10 11:12:15 -07:00
Beka Westberg
278006b5f8 feat: allow the dialog methods to take in extra parameters (#8084)
* feat: allow prompt to take in additional params

* feat: allow confirm tot ake in extra args

* feat: allow alert dialog to take in extra parameters

* chore: add tests for dialog methods
2024-05-08 10:10:09 -07:00
John Nesky
cee7f916bb feat!: Invalid Blocks (#7958)
* feat: Invalid Blocks

* Rename the new json property from invalid to invalidReasons.

* Merged isValid into isEnabled.

* Minor fixes.

* More minor fixes.

* Reverting some stuff that didn't need to change.

* Addressing PR feedback.

* Update the BlockInfo interface to match State.

* Make BlockChange.disabledReason private.
2024-04-17 19:47:51 -07:00
Beka Westberg
fd177358ea feat: comment collapse event (#7949)
* feat: define comment collapse event

* feat: add firing collapse events

* chore: add round-trip test

* chore: add tests for firing collapse events

* chore: format
2024-04-04 15:48:34 -07:00
Beka Westberg
63eb4ecb2a fix: comment create and delete events (#7945)
* chore: switch events to use new comment class

* fix: switch create and delete events to use JSON

* work on getting new comments to fire events

* chore: fixup tests

* chore: rename workspace comment test to comment view test

* chore: add tests for firing events

* chore: remove TODO
2024-04-01 21:33:50 +00:00
Rachel Fenichel
67c3aae76c feat!: delete angle, colour, and multiline input fields and blocks (#7932)
* chore: delete mocha tests for angle field

* feat! : delete angle field

* chore(tests): delete colour tests from generator tests and golden files

* chore: delete colour blocks and associated generators

* chore: remove colour blocks from playgrounds

* chore: delete mocha tests for colour fields

* chore: fix incorrect comment

* chore: delete colour field from core

* chore: delete multiline input tests from generators tests and golden files

* chore: delete multiline text block and associated generators

* chore: remove multiline text block from playgrounds

* chore: delete mocha tests for multiline input field

* chore: delete multiline input field from core
2024-03-13 13:28:26 -07:00
Beka Westberg
fc4228ce03 feat: add comment view (for workspace comments, and block comments for partners) (#7914)
* feat: add basic comment view

* feat: add icons to comment

* chore: add text area to comment view

* feat: add getting size

* feat: add collapsing comment view

* feat: add setting editability

* feat: add location and text hooks.

* feat: add changing the size

* feat: resizing

* feat: add collapsing

* feat: add disposing

* feat: add cursors

* feat: add moving to the front

* chore: split construction into subprocedures

* chore: split resizing into subprocedures

* feat: handle RTL

* chore: add doc comments throughout file

* chore: reduce css specificity where possible

* chore: format

* feat: add remove change listener methods

* chore: add tests for listeners

* feat: add disposing accessors

* chore: add coordinate system notes

* chore: add issues to TODOs where possible

* chore: remove suite.only
2024-03-11 12:12:35 -07:00
Beka Westberg
02cd1c6a1b fix: blocks being dragged behind toolbox (#7619)
* fix: add layer manager to fix dragging

* chore: fix block animations

* chore: add tests

* chore: format
2023-11-08 15:25:45 -08:00
John Nesky
1b2e91246e chore: Use JSON objects for context menu callbackFactory (#7382)
* chore: use json object for context callbackFactory

* Add test file for context menu callback function.
2023-09-08 16:16:59 -07:00
Christopher Allen
be809d9d98 refactor(tests): Migrate generator tests to import shims; delete bootstrap.js (#7414)
* refactor(tests): Use shims instead of bootstrap to load Blockly

  - Modify tests/generators/index.html to import the test shims
    instead of using bootstrap.js to load Blockly.

  - Modify test/generators/webdriver.js to have it wait for the
    workspace to exist before calling loadSelected().  There was
    previously a race which index.html had been winning, but
    now webdriver.js is winning (and the tests failing because
    there is no workspace yet when start() is called.

* chore(tests): Delete bootstrap.js etc.

  - Delete bootstrap.js, bootstrap_helper.js, and bootstrap_done.mjs.
  - Remove remaining references to bootstrap.js

* refactor(build): Remove deps npm script

  buildDeps is now only needed by buildCompiled, not ever for
  runnning in uncompressed mode, so:

  - Remove the deps gulp task (and the deps npm script.
  - Have the minify task run buildJavaScript and buildDeps directly.

  Additionally, the buildAdvanceCompilationTest target hasn't
  needed deps.js for some time (if ever), so skip having it run
  buildDeps entirely.

* refactor(build): Repatriate DEPS_FILE to build_tasks.js

  Since this is no longer used anywhere else it doesn't need to
  live in common.js.

* fix(scripts): Remove vestigial references to deps.mocha.js

* docs(tests): Add additional explanatory note
2023-08-31 00:02:58 +01:00
Christopher Allen
6f20ac290d refactor(tests): Use import instead of goog.bootstrap to load Blockly in mocha tests (#7406)
* fix(build): Have buildShims clean up up after itself

  We need to create a build/package.json file to allow node.js to
  load build/src/core/blockly.js and the other chunk entry points
  as ES modules (it forcibly assumes .js means CJS even if one is
  trying to import, unless package.json says {"type": "module"}),
  but this interferes with scripts/migration/js2ts doing a
  require('build/deps.js'), which is _not_ an ES module.

  Specific error message was:

  /Users/cpcallen/src/blockly/scripts/migration/js2ts:56
  require(path.resolve(__dirname, '../../build/deps.js'));
  ^

  Error [ERR_REQUIRE_ESM]: require() of ES Module
  /Users/cpcallen/src/blockly/build/deps.js from /Users/cpcallen/src/blockly/scripts/migration/js2ts
  not supported.
  deps.js is treated as an ES module file as it is a .js file whose
  nearest parent package.json contains "type": "module" which
  declares all .js files in that package scope as ES modules.
  Instead rename deps.js to end in .cjs, change the requiring code
  to use dynamic import() which is available in all CommonJS
  modules, or change "type": "module" to "type": "commonjs" in
  /Users/cpcallen/src/blockly/build/package.json to treat all .js
  files as CommonJS (using .mjs for all ES modules instead).

      at Object.<anonymous> (/Users/cpcallen/src/blockly/scripts/migration/js2ts:56:1) {
    code: 'ERR_REQUIRE_ESM'
  }

* chore(tests): Reorder to put interesting script nearer top of file

* chore(tests): Add missing imports of closure/goog/goog.js

  These modules were depending on being loaded via the
  debug module loader, which cannot be used without first loading
  base.js as a script, and thereby defining goog.declareModuleId
  as a side effect—but if they are to be loaded via direct import
  statements then they need to actually import their own
  dependencies.

  This is a temporary measure as soon the goog.declareMouleId
  calls can themselves be deleted.

* refactor(tests): Use import instead of bootstrap to load Blockly

* chores(build): Stop generating deps.mocha.js

  This file was only needed by tests/mocha/index.html's use of
  the debug module loader (via bootstrap.js), which has now been
  removed.

* chore(tests): Remove unneeded goog.declareModuleId calls

  These were only needed because these modules were previously
  being loaded by goog.require and/or goog.bootstrap.

* chores(tests): Remove dead code

  We are fully committed to proper modules now.
2023-08-18 18:06:52 +01:00
Beka Westberg
001d9ff2c9 feat: make ICopyable generic and update clipboard APIs (#7348)
* chore: rename module-local variables to not conflict

* feat: make ICopyable generic and update clipboard APIs

* chore: switch over more things to use generic ICopyables

* chore: fix shortcut items using copy paste

* chore: add test for interface between clipboard and pasters

* chore: export isCopyable

* chore: format

* chore: fixup PR comments

* chore: add deprecation tags
2023-08-03 15:33:58 -07:00
dependabot[bot]
2546b01d70 chore(deps): Bump prettier from 2.8.8 to 3.0.0 (#7322)
* chore(deps): Bump prettier from 2.8.8 to 3.0.0

Bumps [prettier](https://github.com/prettier/prettier) from 2.8.8 to 3.0.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.8.8...3.0.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: Reformat using Prettier v3.0 defaults

The main change is to add trailing commas to the last line of
block-formatted function calls.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Christopher Allen <cpcallen+git@google.com>
2023-07-25 14:56:10 +00:00
John Nesky
b8ad7d307f feat: use new intermediate block change event for field edits, normal block change event for closing editor. #7105 (#7151)
* Copy core/events/events_block_change.ts to core/events/events_block_field_intermediate_change.ts

* New intermediate event type for field edits.

* Addressing PR feedback.

* Ran npm run format.

* Fixed procedure mutator responding to param edits.

* Intermediate events now inherit from BlockBase.

* Addressing feedback on PR.

* chore: format
2023-06-16 09:27:56 -07:00
Christopher Allen
817ffab754 refactor(tests): Update bootstrap.js to better support generator chunks (#7171)
Refactor bootstrap.js and bootstrap_helper.js to be able to deal
with generator chunks.  In particular for each chunk, specify:

- The goog.module ID to goog.require() in uncompressed mode.
- The script filename to load in compressed mode.
- Where the chunk's UMD wrapper will save the export object when
  loaded as a script.
- What global variable the chunk's export object should be saved in
  (if desired).
- Any individual named exports to destructure to global variables.

This allows the bootstrap scripts to be slightly simpler while
also being more flexible.
2023-06-15 21:03:04 +01:00
Beka Westberg
c6fbb85a69 Revert "chore!: remove angle field from core (#7155)" (#7158)
This reverts commit 0961aca4c8.
2023-06-13 15:25:41 -07:00
Beka Westberg
0961aca4c8 chore!: remove angle field from core (#7155)
* chore!: remove angle field from core

* chore: fix mocha failures
2023-06-13 15:09:15 -07:00
Maribeth Bottorff
88ff901a72 chore: use prettier instead of clang-format (#7014)
* chore: add and configure prettier

* chore: remove clang-format

* chore: remove clang-format config

* chore: lint additional ts files

* chore: fix lint errors in blocks

* chore: add prettier-ignore where needed

* chore: ignore js blocks when formatting

* chore: fix playground html syntax

* chore: fix yaml spacing from merge

* chore: convert text blocks to use arrow functions

* chore: format everything with prettier

* chore: fix lint unused imports in blocks
2023-05-10 16:01:39 -07:00
Beka Westberg
4cec0c23cc test: icon block hooks (#7053)
* chore: define test cases

* chore: add tests for icon block hooks

* chore: skip tests (whoops)

* chore: capitalization
2023-05-08 21:10:31 +00:00
Beka Westberg
83e3dcac70 feat: add after queued renders promises to render management (#6981)
* feat: add promise to render queue system

* chore: update docs for variables

* chore: add export of render management

* chore: add tests for resolving render management promises

* fix: modify insertion marker manager to use render management promises

* chore: format

* chore: remove callback from afterQueuedRenders

* chore: don't store resolver

* chore: rename afterQueuedRenders -> finishQueuedRenders

* chore: fix tests
2023-04-18 17:02:33 -07:00
Beka Westberg
da9ae8f472 chore: revert procedure events (#6795)
* chore: delete procedure events

* chore: delete event related tests
2023-01-26 09:25:42 -08:00
Beka Westberg
67275e4bba Revert "feat!: allow blocks to receive their own delete events" (#6676) 2022-12-01 14:55:31 -08:00
Beka Westberg
7b055dbc7e chore(tests): test running procedure events (#6627)
* chore: define necessary events

* chore: cleanup test organization

* chore: cleanup comment

* chore: move assertEventFiredShallow to test helpers

* chore: add tests for running the procedure change return events

* chore: work on tests??

* chore: add tests for running the change return events

* chore: add tests for running enable events

* chore: add tests for procedure rename events

* chore: add tests for renaming procedure parameters

* chore: add tests for running procedure create events

* chore: add tests for running procedure parameter create events

* chore: add tests for running procedure delete events

* chore: add tests for running procedure parameter delete events

* chore: skip all tests for running procedure events
2022-11-18 16:01:41 -08:00
Beka Westberg
f64c934f04 feat: refactor event serialization to use static fromJson method (#6614)
* feat: add new path for deserialization of events

* chore: add tests for round-tripping events

* chore: add static fromJson methods to all events

* chore: add inline docs to new static methods

* chore: add deprecation warnings

* chore: cleanup

* chore: add deprecation and docs to abstract

* chore: format

* chore: cleanup from rebase

* chore: update docs comment
2022-11-14 11:07:36 -08:00
Rachel Fenichel
82dc9664ba test: add tests for the insertion marker manager (#6596)
* test: make sure the insertion marker manager creates the correct number of markers

* test: add more tests for insertion marker manager

* chore: format

* test: respond to pr feedback

* test: make test names more descriptive

* test: add row_to_stack test block
2022-11-03 12:58:33 -07:00
Christopher Allen
52a0d525d7 chore(build): Remove build products from the Blockly repository (#6475)
* feat(build): Make build tasks invoke their prerequisites

  - Divide gulp targets into three kinds: main sequence,
    manually invokable, and script-only.  The first two categories
    automatically invoke their prerequisites.
  - Give (most of) the affected gulp targets shorter and more memorable
    names that could become their npm script names in future.

* feat(build): Make package tasks invoke their prerequisites

  Have the package task invoke the cleanBuildDir (as well as
  cleanPackageDir) and build tasks.  Remove the checkBuildDir
  task as it is now redundant since a fresh build is done every
  time.

* feat(build): Make git tasks invoke their prerequisites

* feat(build): Make cleanup, license [sic] tasks invoke their prerequisites

  Turns out they don't have any, so this commit just classifies
  their gulp targets according to the established scheme.

* feat(build): Make appengine tasks invoke their prerequisites

  In this case prepareDeployDir will eventually depend on package
  but does not for now.

* feat(build): Have npm scripts run npm ci first where applicable

  Have any npm script that have external effects (e.g. publishing an
  npm package, pushing a new version to appengine, or updating GitHub
  Pages) start by running npm ci to ensure that all dependencies are
  up-to-date with respect to package-lock.json.

  (This is done by npm and not a gulp script because gulp itself
  might need updating.  So might npm, but that is less likely to
  make any difference to what gets published/pushed.)

* chore(build): have tests use package target

  Have the tests just run the package target (with debug flags)
  since that runs the the build target automatically.

* feat(tests): Write Closure Compiler output directly to dist/

  Since they are already UMD-wrapped, have Closure Compiler write
  output chunks directly to RELEASE_DIR, i.e. dist/.

* chore(tests): Use freshly-build files in compressed mode.

  Use the freshly-built build/*_compresssed.js files when bootstrapping
  in compressed mode, rather than using the checked-in files in the
  repository root.

  This helps ensure that compressed and uncompressed mode will be
  testing (as closely as possible) the same code.

  Obsoletes #6218 (though the issues discussed there have not actually
  yet been addressed in this branch).

* chore(build): Write intermediate langfiles to build/msg

  Write the results of create_messages.py to build/msg instead of
  build/msg/js.

* fix(build): Use build/msg/en.js instead of msg/messages.js in tests

  This has no direct effect but fixes a long-standing misdesign
  where we are testing against the input to, rather than the output
  of, the language file processing pipeline.

* feat(demos): Use freshly-built files

  Use the freshly-built dist/*_compresssed.js and build/msg/* files
  rather than using the checked-in files in the repository root.

  This helps ensure that these demos are using the most recent
  version of Blockly (even in the develop branch).

* fix(build): Update appengine deployment to include built files

  Modify the prepareDemos task as follows:

  - Use the git index instead of HEAD, so that most local changes
    will be applied (without copying whatever .gitignored cruft
    might be in the local directory).
  - Run clean and build and then copy build/msg and
    dist/*_compressed.js* to the deploy directory.

  This fixes the problem created by the previous commit, wherein the
  demos relied on built files that were not being deployed to
  appengine.

* fix(build): Update GitHub Pages deployment to include built files

  Modify the updateGithubPages task to run clean and build and
  then git add build/msg dist/*_compressed.js*, so that they will
  be included in the deployed pages.

  This fixes the problem created by the previous^2 commit,
  wherein the demos relied on built files that were not being
  deployed to GitHub Pages.

* chore(build): Remove build products from repository

  Remove *_compressed.js* and msg/js/* from the blockly repository.
  Also remove the now-obsolete checkinBuilt gulp task.

* chore(build): Apply relevant changes to test_tasks.js

  Apply changes made to run_all_tests.sh and check_metadata.sh to
  the corresponding parts of their JS replacements in
  test_tasks.js.

* chore(build): Make updates suggested in PR #6475

  - Remove `clean:builddir` and `clean:releasedir` - `clean`
    is sufficient.
  - Remove duplicate `require` from `appengine_tasks.js`.

* feat(build): Use shorter npm script names

  Since scripts that run build tasks now automatically run their
  prerequisite tasks, the previous naming scheme of task `build`
  running all the `build:subtask`s no longe really makes very
  much sense.

  Additionally, following a chat discussion, there seems to be a
  rough consensus to use "messages" to refer to the .json input
  files, and "langfiles" to the generated .js output files.

  Consequently, simplify npm script names by renaming as follows:

  - "generate:langfiles" -> "messages"
  - "build:langfiles" -> "langfiles"
  - "build:js" -> "tsc"
  - "build:deps" -> "deps"
  - "build:compiled" -> "minify"
  - "build:compressed": delete this synonym for "build:compiled",

  ("minify" was chosen as agnostic to Closure Compiler vs. WebPack.)

* chores(build): Add deprecation notice for old scripts

  To reduce potential confusion/frustration, restore the previous
  npm scripts but have them display a deprecation notice instead
  (note that npm prints the script contents before running it, so
  echo is not needed).

* docs(build): Add comments distinguishing 'messages' from 'langfiles'
2022-11-03 13:15:10 +00:00
Maribeth Bottorff
caf91c82a6 fix: fix pinch to zoom (#6544)
* fix: fix pinch to zoom

* chore: format
2022-10-13 18:05:42 -07:00
Beka Westberg
fe714bb8c7 test: add skipped tests for the procedure map (#6486)
* test: add skipped tests for the procedure map

* chore: format
2022-10-05 13:35:20 -07:00
Beka Westberg
e9920a54e0 feat!: allow blocks to receive their own delete events (#6337)
* feat!: allow blocks to receive their own delete events

* fix: move block tests back into main directory

* chore: add a test for disposing of callers

* chore: add test for delete being received

* chore: add comment about why we have to run the clock twice

* chore: fix whitespace

* chore: fix whitespace

* chore: fix imports in tests

* chore: bump mocha timeout

* chore: bump timeout again?

* chore: eliminate the possibility that tests are actually timing out

* chore: change timeout back

* chore: remove tests that might be the problematic ones

* chore: attempt enabling delete event test

* chore: enable lists tests

* chore: try ternary test as well

* chore: actually add block test files

* chore: enable remaining tests
2022-08-16 15:49:40 -07:00
Christopher Allen
46df7d132d refactor(tests): Revise tests/playgrounds/prepare.js as tests/bootstrap.js to improve support for ES modules and post-bootstrap scripts (#6214)
* refactor(tests): Move and rename prepare.js, blockly.mjs

  Since prepare.js and blockly.mjs are going to be needed for running
  all tests in uncompiled mode (not just the playgrounds), move them
  tests/.  Further, rename prepare.js to bootstrap.js to better reflect
  its purpose.

* feat(tests): Introduce BLOCKLY_BOOTSTRAP_OPTIONS

  Provide a mechanism for web pages that use bootstrap.js to control
  what is loaded and how.

* fix(tests): Use the blockly repository path for all script src= URLs

  Previously the (non-advanced) playground was only correctly loadging
  on localhost because you can put an arbitrary number of "../"s in front
  of a relative URL and it just takes you to the root directory.

* fix(tests): Don't use template literals in bootstrap.js

  This is necessary (but not necessarily sufficient) to be able to
  load the file in IE 11.

* fix(tests): Throw error if attempting to bootstrap in node.js

* feat(tests): Make bootstrap.js more configurable.

* Terminology change: use "compressed" and "uncompressed" to describe
  what Closure Compiler calls "compiled" and "uncompiled", to reduce
  confusion with the compilation that will be done by tsc.

* Get the list of modules to bootstrap (in compressed mode), or
  scripts to load (in compressed mode) from BLOCKLY_BOOTSTRAP_OPTIONS,
  to allow calling scripts to to specify exactly what to load.

* feat(tests): Use a proper quote function

  We need to generate string literals.  Best to use a quote function
  instead of concatenating on quote marks withou escaping.  Copy a
  well-tested one from Code City.

* feat(tests): Support an additionalScripts option

  This is a list of scripts to load (in order) once the required modules
  have been bootstrapped.

  We do this using goog.addDependency to make the first script depend
  on the required modules, then each subsequent script depend on the
  previous one, and then finally goog.bootstrapping the last such script.

* refactor(tests): Remove special handling of msg/messages.js

* refactor(tests): Use additionalScripts for all script loading

  Use additionalScripts option for all script loading in
  playground.html and advanced_playground.html.

* refactor(tests): Use bootstrap instead of uncompressed in Mocha tests

  Use tests/bootstrap.js instead of blockly_uncompressed.js to load
  blockly in uncompressed mode in the Mocha tests.

  This entails adding a new item, despFiles, to BLOCKLY_BOOTSTRAP_OPTIONS,
  to allow tests/deps.mocha.js to be loaded at the appropriate point.

  Mention of blockly_uncompressed.js is removed from
  tests/mocah/.mocharc.js; it's not clear to me what effect the "file:"
  directive in this file might have previously had and I was not able to
  find documentation for it on mochajs.org, but in any case removing it
  appears to have had no ill effect.

* refactor(tests): Use bootstrap instead of uncompressed in generator tests

  This entails adding an additional check in bootstrap so as to load
  uncompressed when loading from a file: URL, since these are not
  localhost URLs - though in fact the generator tests run equally well
  in compressed mode, albeit against (for now) the previously-check-in
  build products rather than the live code.

* refactor(test): Use bootstrap.js in multi_playground.html

  This removes the last use of load_all.js, so remove it.

* chore(tests): Delete blockly_uncompressed.js

  Its function has now been entirely subsumed by tests/bootstrap.js,
  so remove it and update any remaining mentions of it.

  Also fix formatting and positions of some comments in playground.html.

* fix(tests): Rewrite bootstrap sequencing code

  An earlier commit modified the generated <script> to use
  goog.addDependency to trick the debug module loader into loading
  .additionalScripts (via goog.bootstrap), but it turns out there is
  a small problem: scripts like msg/messages.js have undeclared
  dependencies on the Blockly module, and without a call to
  goog.require('Blockly') in them they can end up being run before
  the Blockly module is fully loaded.

  (This problem only occurs when there are ES Modules, rather than
  merely goog.modules, in the mix.)

  Fix this by adding a script, bootstrap_helper.js, to be loaded
  options.requires and any options.additionalScripts that makes an
  explicit call to goog.require for each of option.requires.

  Also refactor the code so that instead of generating a loop which
  calls goog.addDependency, we generate the addDependency calls
  directly.  This makes debugging a bit easer as we can use the browser's
  dev tools to inspect the generated calls in the DOM tree.

* fix(tests): Prevent spurious transpilation warnings

  For some reason when the debug module loader encounters ES modules
  it starts to complain about being unable to transpile some ES202x
  features in other (non-ESM) modules, even though it doesn't normally
  try to transpile those.

  Since uncompressed-mode testing is almost exclusively on modern
  browsers we don't care about transpiling these features, so suppress
  the warnings instead.

* refactor(tests): Rename blockly.mjs to bootstrap_done.mjs; simplify

  Since blockly.mjs is no longer returning just the exports object
  from core/blockly.js (see PR #5995), it might be better named after
  its actual purpose: to wait for bootstrapping to be done.

  Remove all the code that was used to pass the blockly.js exports
  object along from the bootstrap callback to the blockly.mjs export,
  since there's no reason to go to a lot of trouble to set a local
  variable named Blockly to the same value as a global variable named
  Blockly.

  (Something like this may be needed again in future, but certainly in
  a different form.)

* chore(tests): Use freshly-build files in compressed mode.

  Use the freshly-built build/*_compresssed.js files when bootstrapping
  in compressed mode, rather than using the checked-in files in the
  repository root.

  This helps ensure that compressed and uncompressed mode will be
  testing (as closely as possible) the same code.

* chore(tests): Rename BlocklyLoader to blocklyLoader; record compressed

  - Rename the BlocklyLoader global to blocklyLoader (since it is not
    a class constructor).
  - Create it regardless of whether we are bootstrapping in
    uncompressed or loading compressed via <script> tags.
  - Record which we are doing as .compressed, and use this property
    to choose playground background colour.

* chore(tests): Resolve comments for PR #6214

  Mostly documentation changes, but notably renaming blocklyLoader to
  bootstrapInfo.

* Revert "chore(tests): Use freshly-build files in compressed mode."

  This reverts commit de8d356838.
2022-06-15 19:35:01 +01:00