Skip to content

Commit 9ac293d

Browse files
committed
prep build 3/25
2 parents 8a645cf + 884f384 commit 9ac293d

File tree

53 files changed

+2343
-738
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2343
-738
lines changed

backport-changelog/7.0/11325.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://github.com/WordPress/wordpress-develop/pull/11325
2+
3+
* https://github.com/WordPress/gutenberg/pull/76779

backport-changelog/7.1/11272.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
https://github.com/WordPress/wordpress-develop/pull/11272
22

33
* https://github.com/WordPress/gutenberg/pull/76573
4+
* https://github.com/WordPress/gutenberg/pull/76734
5+
* https://github.com/WordPress/gutenberg/pull/76622

changelog.txt

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
== Changelog ==
22

3-
= 22.8.0-rc.1 =
3+
= 22.8.0 =
44

55
## Changelog
66

@@ -87,8 +87,6 @@
8787
- Add a limit for the default provider. ([76437](https://github.com/WordPress/gutenberg/pull/76437))
8888

8989
#### Content Guidelines
90-
- Add block guidelines management. ([76187](https://github.com/WordPress/gutenberg/pull/76187))
91-
- Guidelines: Add actions for Import, Export and Revisions of guidelines. ([76155](https://github.com/WordPress/gutenberg/pull/76155))
9290
- Rename route and use the right `Notice` component. ([76427](https://github.com/WordPress/gutenberg/pull/76427))
9391

9492
#### Block Editor
@@ -275,11 +273,6 @@ high loading priority. ([76302](https://github.com/WordPress/gutenberg/pull/7630
275273
- Sync some post list changes with Extensible Site Editor. ([76243](https://github.com/WordPress/gutenberg/pull/76243))
276274

277275

278-
279-
#### Content Guidelines
280-
- Add UX for site, copy, image, and additional guidelines. ([75420](https://github.com/WordPress/gutenberg/pull/75420))
281-
282-
283276
### Documentation
284277

285278
- Add Client-Side Navigation documentation to manifest and table of contents.
@@ -391,7 +384,6 @@ The following PRs were merged by first-time contributors:
391384

392385

393386
- @apermo: Fix: Use add_filter() for get_block_type_variations hook. ([76297](https://github.com/WordPress/gutenberg/pull/76297))
394-
- @aswasif007: Content Guidelines: Add UX for site, copy, image, and additional guidelines. ([75420](https://github.com/WordPress/gutenberg/pull/75420))
395387
- @chubes4: API Fetch: Respect caller-provided Content-Type in httpV1 middleware. ([76285](https://github.com/WordPress/gutenberg/pull/76285))
396388
- @iamchughmayank: Guidelines: Add actions for Import, Export and Revisions of guidelines. ([76155](https://github.com/WordPress/gutenberg/pull/76155))
397389
- @kannan-ravi: Add word-break property to visually hidden styles to prevent screen reader issues. ([75539](https://github.com/WordPress/gutenberg/pull/75539))
@@ -407,6 +399,8 @@ The following contributors merged PRs in this release:
407399
@aaronrobertshaw @adamsilverstein @aduth @alecgeatches @alexstine @Aljullu @andrewserong @annezazu @apermo @aswasif007 @CGastrell @chriszarate @chubes4 @ciampo @Copons @dabowman @desrosj @dhasilva @dlind1 @ellatrix @enejb @getdave @gigitux @gziolo @hbhalodia @huzaifaalmesbah @iamchughmayank @im3dabasia @ingeniumed @jameskoster @jasmussen @jeryj @jorgefilipecosta @jsnajdr @juanmaguitar @kannan-ravi @kraftbj @MaggieCabrera @Mamaduka @manzoorwanijk @markusfoo @mattgrshaw @maxschmeling @mcsf @mikachan @mikejolley @mirka @Mustafabharmal @ntsekouras @oandregal @ockham @pkevan @ramonjd @retrofox @sagarjadhav @scruffian @sgomes @shekharnwagh @shimotmk @simison @smithjw1 @t-hamano @talldan @westonruter @wwahammy @youknowriad @yuliyan
408400

409401

402+
403+
410404
= 22.7.1 =
411405

412406
## Changelog

docs/contributors/code/e2e/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ It's slow to set states manually before or after tests, especially when they're
7979

8080
### Avoid global variables
8181

82-
Previously in our Jest + Puppeteer E2E tests, `page` and `browser` are exposed as global variables. This makes it harder to work with when we have multiple pages/tabs in the same test, or if we want to run multiple tests in parallel. `@playwright/test` has the concept of [fixtures](https://playwright.dev/docs/test-fixtures) which allows us to inject `page`, `browser`, and other parameters into the tests.
82+
In the previous E2E setup, `page` and `browser` were global variables, which made working with multiple pages or parallel tests harder.
83+
84+
`@playwright/test` uses fixtures to inject `page`, `browser`, and other parameters into tests.
8385

8486
### Make explicit assertions
8587

docs/contributors/code/testing-overview.md

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,7 @@ There is an ongoing effort to add integration tests to the native mobile project
506506

507507
## End-to-end testing
508508

509-
Most existing End-to-end tests currently use [Puppeteer](https://github.com/puppeteer/puppeteer) as a headless Chromium driver to run the tests in `packages/e2e-tests`, and are otherwise still run by a [Jest](https://jestjs.io/) test runner.
510-
511-
There's an ongoing [project](https://github.com/WordPress/gutenberg/issues/38851) to migrate them from Puppeteer to Playwright. **It's recommended to write new e2e tests in Playwright whenever possible**. The sections below mostly apply to the old Jest + Puppeteer framework. See the dedicated [guide](/docs/contributors/code/e2e/README.md) if you're writing tests with Playwright.
509+
End-to-end tests use [Playwright](https://playwright.dev/) as the testing framework. See the dedicated [End-to-End Testing guide](/docs/contributors/code/e2e/README.md) for best practices and detailed instructions.
512510

513511
### Using wp-env
514512

@@ -521,46 +519,14 @@ npm run test:e2e
521519
or interactively
522520
523521
```bash
524-
npm run test:e2e:watch
525-
```
526-
527-
Sometimes it's useful to observe the browser while running tests. Then, use this command:
528-
529-
```bash
530-
npm run test:e2e:watch -- --puppeteer-interactive
531-
```
532-
533-
You can control the speed of execution with `--puppeteer-slowmo`:
534-
535-
```bash
536-
npm run test:e2e:watch -- --puppeteer-interactive --puppeteer-slowmo=200
537-
```
538-
539-
You can additionally have the devtools automatically open for interactive debugging in the browser:
540-
541-
```bash
542-
npm run test:e2e:watch -- --puppeteer-devtools
543-
```
544-
545-
### Using alternate environment
546-
547-
If using a different setup than `wp-env`, you first need to symlink the e2e test plugins to your test site, from your site's plugins directory run:
548-
549-
```bash
550-
ln -s gutenberg/packages/e2e-tests/plugins/* .
551-
```
552-
553-
Then to run the tests, specify the base URL, username, and passwords for your site. For example, if your test site is at `http://wp.test`, use:
554-
555-
```bash
556-
WP_BASE_URL=http://wp.test npm run test:e2e -- --wordpress-username=admin --wordpress-password=password
522+
npm run test:e2e -- --ui
557523
```
558524
559525
### Scenario testing
560526
561527
If you find that end-to-end tests pass when run locally, but fail in GitHub Actions, you may be able to isolate a CPU- or network-bound race condition by simulating a slow CPU or network:
562528
563-
```
529+
```bash
564530
THROTTLE_CPU=4 npm run test:e2e
565531
```
566532

docs/explanations/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
- [Modularity and WordPress Packages](/docs/explanations/architecture/modularity.md).
88
- [Block Editor Performance](/docs/explanations/architecture/performance.md).
99
- What are the design decisions behind the Data Module?
10-
- [Why is Puppeteer the tool of choice for end-to-end tests?](/docs/explanations/architecture/automated-testing.md)
10+
- [Why is Playwright the tool of choice for end-to-end tests?](/docs/explanations/architecture/automated-testing.md)
1111
- [What’s the difference between the different editor packages? What’s the purpose of each package?](/docs/explanations/architecture/modularity.md#whats-the-difference-between-the-different-editor-packages-whats-the-purpose-of-each-package)
1212
- [Template and template parts flows](/docs/explanations/architecture/full-site-editing-templates.md)

docs/explanations/architecture/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ Let’s look at the big picture and the architectural and UX principles of the b
1515

1616
- [Modularity and WordPress Packages](/docs/explanations/architecture/modularity.md).
1717
- [Understand the repository folder structure](/docs/contributors/folder-structure.md).
18-
- **Outdated!** [Why is Puppeteer the tool of choice for end-to-end tests?](/docs/explanations/architecture/automated-testing.md).
18+
- [Why is Playwright the tool of choice for end-to-end tests?](/docs/explanations/architecture/automated-testing.md).
19+
Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
# Automated Testing
22

3-
## Why is Puppeteer the tool of choice for end-to-end tests?
3+
## Why is Playwright the tool of choice for end-to-end tests?
44

5-
There exists a rich ecosystem of tooling available for web-based end-to-end automated testing. Thus, it's a common question: "Why does Gutenberg use [Puppeteer](https://developers.google.com/web/tools/puppeteer/) instead of ([Cypress](https://cypress.io/), [Selenium](https://www.selenium.dev/), [Playwright](https://github.com/microsoft/playwright), etc)?". Given some historical unreliability of the build results associated with end-to-end tests, it's especially natural to weigh this question in considering whether our tools are providing more value than the effort required in maintaining them. While we should always be comfortable in reevaluating earlier decisions, there were and continue to be many reasons that Puppeteer is the best compromise of the options available for end-to-end testing.
5+
There exists a rich ecosystem of tooling available for web-based end-to-end automated testing. Gutenberg uses [Playwright](https://playwright.dev/) as its end-to-end testing framework. The project previously used [Puppeteer](https://pptr.dev/) but has since fully migrated to Playwright. Here are the reasons Playwright was chosen:
66

7-
These include:
7+
- **Multi-browser support**. Playwright supports Chromium, Firefox, and WebKit out of the box, providing broader browser coverage compared to Puppeteer's Chrome-only approach.
8+
- **Built-in test runner**. `@playwright/test` provides a powerful test runner with parallel execution, [fixtures](https://playwright.dev/docs/test-fixtures), and auto-waiting, reducing flakiness and improving developer experience.
9+
- **Auto-waiting and web-first assertions**. Playwright automatically waits for elements to be actionable before performing actions, reducing the need for manual `waitFor*` calls while still surfacing legitimate performance issues that affect users.
10+
- **Better debugging tools**. Playwright offers a [trace viewer](https://playwright.dev/docs/trace-viewer), [UI mode](https://playwright.dev/docs/test-ui-mode), and a built-in [inspector](https://playwright.dev/docs/debug#playwright-inspector) for step-by-step debugging.
11+
- **Fixtures over global variables**. Playwright's fixture model injects `page`, `browser`, and other parameters into tests, making it easier to work with multiple pages or tabs and to run tests in parallel.
12+
- **Page Object Model**. Playwright encourages the [Page Object Model](https://playwright.dev/docs/pom) pattern for reusable utility functions, improving test readability and maintainability.
813

9-
- **Interoperability with existing testing framework**. Puppeteer is "just" a tool for controlling a Chrome browser, and makes no assumptions about how it's integrated into a testing environment. While this requires some additional effort in ensuring the test environment is available, it also allows for cohesion in how it integrates with an existing setup. Gutenberg is able to consistently use Jest for both unit testing and end-to-end testing. This is contrasted with other solutions like Cypress, which provide their own testing framework and assertion library as part of an all-in-one solution.
10-
- **An expressive but predictable API**. Puppeteer strikes a nice balance between low-level access to browser behavior, while retaining an expressive API for issuing and awaiting responses to those commands using modern JavaScript [`async` and `await` syntax](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await). This is contrasted with other solutions, which either don't support or leverage native language async functionality, don't expose direct access to the browser, or leverage custom domain-specific language syntaxes for expressing browser commands and assertions. The fact that Puppeteer largely targets the Chrome browser is non-ideal in how it does not provide full browser coverage. On the other hand, the limited set of browser targets offers more consistent results and stronger guarantees about how code is evaluated in the browser environment.
11-
- **Surfacing bugs, not obscuring them**. Many alternative solutions offer options to automatically await settled network requests or asynchronous appearance of elements on the page. While this can serve as a convenience in accounting for unpredictable delays, it can also unknowingly cause oversight of legitimate user-facing issues. For example, if an element will only appear on the page after some network request or computation has completed, it may be easy to overlook that these delays can cause unpredictable and frustrating behavior for users ([example](https://github.com/WordPress/gutenberg/pull/11287)). Given that developers often test on high-end hardware and stable network connections, consideration of resiliency on low-end hardware or spotty network availability is not always on the forefront of one's considerations. Puppeteer forces us to acknowledge these delays with explicit `waitFor*` expressions, putting us in much greater alignment with the real-world experience of an end-user.
12-
- **Debugging**. It's important that in that case that a test fails, there should be straight-forward means to diagnose and resolve the issue. While its offerings are rather simplistic relative to the competition, Puppeteer does expose options to run tests as "headful" (with the browser visible) and with delayed actions. Combined with the fact that it interoperates well with native language / runtime features (e.g. debugger statements or breakpoints), this provides developers with sufficient debugging access.
13-
14-
For more context, refer to the following resources:
15-
16-
- [Testing Overview: End-to-End Testing](/docs/contributors/code/testing-overview.md#end-to-end-testing)
17-
- [Testing: Experiment with Puppeteer for E2E testing](https://github.com/WordPress/gutenberg/pull/5618)
18-
- In early iterations, the contributing team opted to use Cypress for end-to-end testing. This pull request outlines problems with the approach, and proposed the initial transition to Puppeteer.
19-
- [JavaScript Chat Summary: January 28, 2020](https://make.wordpress.org/core/2020/02/04/javascript-chat-summary-january-28-2020/)
20-
- Playwright is a new offering created by many of the original contributors to Puppeteer. It offers increased browser coverage and improved reliability of tests. While still early in development at the time of this writing, there has been some interest in evaluating it for future use as an end-to-end testing solution.
14+
For more details on writing end-to-end tests, see the [End-to-End Testing guide](/docs/contributors/code/e2e/README.md).

lib/compat/wordpress-7.0/class-wp-sync-post-meta-storage.php

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ class WP_Sync_Post_Meta_Storage implements WP_Sync_Storage {
3232
* @since 7.0.0
3333
* @var string
3434
*/
35-
const AWARENESS_META_KEY = 'wp_sync_awareness';
35+
const AWARENESS_META_KEY = 'wp_sync_awareness_state';
3636

3737
/**
3838
* Meta key for sync updates.
3939
*
4040
* @since 7.0.0
4141
* @var string
4242
*/
43-
const SYNC_UPDATE_META_KEY = 'wp_sync_update';
43+
const SYNC_UPDATE_META_KEY = 'wp_sync_update_data';
4444

4545
/**
4646
* Cache of cursors by room.
@@ -71,36 +71,68 @@ class WP_Sync_Post_Meta_Storage implements WP_Sync_Storage {
7171
*
7272
* @since 7.0.0
7373
*
74+
* @global wpdb $wpdb WordPress database abstraction object.
75+
*
7476
* @param string $room Room identifier.
7577
* @param mixed $update Sync update.
7678
* @return bool True on success, false on failure.
7779
*/
7880
public function add_update( string $room, $update ): bool {
81+
global $wpdb;
82+
7983
$post_id = $this->get_storage_post_id( $room );
8084
if ( null === $post_id ) {
8185
return false;
8286
}
8387

84-
$meta_id = add_post_meta( $post_id, self::SYNC_UPDATE_META_KEY, $update, false );
85-
86-
return (bool) $meta_id;
88+
// Use direct database operation to avoid cache invalidation performed by
89+
// post meta functions (`wp_cache_set_posts_last_changed()` and direct
90+
// `wp_cache_delete()` calls).
91+
return (bool) $wpdb->insert(
92+
$wpdb->postmeta,
93+
array(
94+
'post_id' => $post_id,
95+
'meta_key' => self::SYNC_UPDATE_META_KEY,
96+
'meta_value' => wp_json_encode( $update ),
97+
),
98+
array( '%d', '%s', '%s' )
99+
);
87100
}
88101

89102
/**
90103
* Gets awareness state for a given room.
91104
*
92105
* @since 7.0.0
93106
*
107+
* @global wpdb $wpdb WordPress database abstraction object.
108+
*
94109
* @param string $room Room identifier.
95110
* @return array<int, mixed> Awareness state.
96111
*/
97112
public function get_awareness_state( string $room ): array {
113+
global $wpdb;
114+
98115
$post_id = $this->get_storage_post_id( $room );
99116
if ( null === $post_id ) {
100117
return array();
101118
}
102119

103-
$awareness = get_post_meta( $post_id, self::AWARENESS_META_KEY, true );
120+
// Use direct database operation to avoid updating the post meta cache.
121+
// ORDER BY meta_id DESC ensures the latest row wins if duplicates exist
122+
// from a past race condition in set_awareness_state().
123+
$meta_value = $wpdb->get_var(
124+
$wpdb->prepare(
125+
"SELECT meta_value FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s ORDER BY meta_id DESC LIMIT 1",
126+
$post_id,
127+
self::AWARENESS_META_KEY
128+
)
129+
);
130+
131+
if ( null === $meta_value ) {
132+
return array();
133+
}
134+
135+
$awareness = json_decode( $meta_value, true );
104136

105137
if ( ! is_array( $awareness ) ) {
106138
return array();
@@ -114,19 +146,54 @@ public function get_awareness_state( string $room ): array {
114146
*
115147
* @since 7.0.0
116148
*
149+
* @global wpdb $wpdb WordPress database abstraction object.
150+
*
117151
* @param string $room Room identifier.
118152
* @param array<int, mixed> $awareness Serializable awareness state.
119153
* @return bool True on success, false on failure.
120154
*/
121155
public function set_awareness_state( string $room, array $awareness ): bool {
156+
global $wpdb;
157+
122158
$post_id = $this->get_storage_post_id( $room );
123159
if ( null === $post_id ) {
124160
return false;
125161
}
126162

127-
// update_post_meta returns false if the value is the same as the existing value.
128-
update_post_meta( $post_id, self::AWARENESS_META_KEY, $awareness );
129-
return true;
163+
// Use direct database operation to avoid cache invalidation performed by
164+
// post meta functions (`wp_cache_set_posts_last_changed()` and direct
165+
// `wp_cache_delete()` calls).
166+
//
167+
// If two concurrent requests both see no row and both INSERT, the
168+
// duplicate is harmless: get_awareness_state() reads the latest row
169+
// (ORDER BY meta_id DESC).
170+
$meta_id = $wpdb->get_var(
171+
$wpdb->prepare(
172+
"SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s ORDER BY meta_id DESC LIMIT 1",
173+
$post_id,
174+
self::AWARENESS_META_KEY
175+
)
176+
);
177+
178+
if ( $meta_id ) {
179+
return (bool) $wpdb->update(
180+
$wpdb->postmeta,
181+
array( 'meta_value' => wp_json_encode( $awareness ) ),
182+
array( 'meta_id' => $meta_id ),
183+
array( '%s' ),
184+
array( '%d' )
185+
);
186+
}
187+
188+
return (bool) $wpdb->insert(
189+
$wpdb->postmeta,
190+
array(
191+
'post_id' => $post_id,
192+
'meta_key' => self::AWARENESS_META_KEY,
193+
'meta_value' => wp_json_encode( $awareness ),
194+
),
195+
array( '%d', '%s', '%s' )
196+
);
130197
}
131198

132199
/**
@@ -170,6 +237,8 @@ private function get_storage_post_id( string $room ): ?int {
170237
'post_status' => 'publish',
171238
'name' => $room_hash,
172239
'fields' => 'ids',
240+
'orderby' => 'ID',
241+
'order' => 'ASC',
173242
)
174243
);
175244

@@ -220,6 +289,8 @@ public function get_update_count( string $room ): int {
220289
*
221290
* @since 7.0.0
222291
*
292+
* @global wpdb $wpdb WordPress database abstraction object.
293+
*
223294
* @param string $room Room identifier.
224295
* @param int $cursor Return updates after this cursor (meta_id).
225296
* @return array<int, mixed> Sync updates.
@@ -269,7 +340,10 @@ public function get_updates_after_cursor( string $room, int $cursor ): array {
269340

270341
$updates = array();
271342
foreach ( $rows as $row ) {
272-
$updates[] = maybe_unserialize( $row->meta_value );
343+
$decoded = json_decode( $row->meta_value, true );
344+
if ( null !== $decoded ) {
345+
$updates[] = $decoded;
346+
}
273347
}
274348

275349
return $updates;
@@ -280,6 +354,8 @@ public function get_updates_after_cursor( string $room, int $cursor ): array {
280354
*
281355
* @since 7.0.0
282356
*
357+
* @global wpdb $wpdb WordPress database abstraction object.
358+
*
283359
* @param string $room Room identifier.
284360
* @param int $cursor Remove updates with meta_id < this cursor.
285361
* @return bool True on success, false on failure.

0 commit comments

Comments
 (0)