<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[56926] trunk/tests/visual-regression/specs/visual-snapshots.test.js: Build/Test Tools: Migrate Puppeteer tests to Playwright.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/56926">56926</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/56926","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>swissspidy</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2023-10-13 08:11:41 +0000 (Fri, 13 Oct 2023)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Build/Test Tools: Migrate Puppeteer tests to Playwright.
As per the migration plan shared last year, this migrates all browser-based tests in WordPress core to use Playwright.
This includes end-to-end, performance, and visual regression tests.
Props swissspidy, mamaduka, kevin940726, bartkalisz, desrosj, adamsilverstein.
Fixes <a href="https://core.trac.wordpress.org/ticket/59517">#59517</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkgithubworkflowscodingstandardsyml">trunk/.github/workflows/coding-standards.yml</a></li>
<li><a href="#trunkgithubworkflowsendtoendtestsyml">trunk/.github/workflows/end-to-end-tests.yml</a></li>
<li><a href="#trunkgithubworkflowsperformanceyml">trunk/.github/workflows/performance.yml</a></li>
<li><a href="#trunkgithubworkflowsphpunittestsrunyml">trunk/.github/workflows/phpunit-tests-run.yml</a></li>
<li><a href="#trunkgithubworkflowstestcoverageyml">trunk/.github/workflows/test-coverage.yml</a></li>
<li><a href="#trunkgithubworkflowstestnpmyml">trunk/.github/workflows/test-npm.yml</a></li>
<li><a href="#trunkgitignore">trunk/.gitignore</a></li>
<li><a href="#trunkGruntfilejs">trunk/Gruntfile.js</a></li>
<li><a href="#trunkpackagelockjson">trunk/package-lock.json</a></li>
<li><a href="#trunkpackagejson">trunk/package.json</a></li>
<li><a href="#trunktestse2eREADMEmd">trunk/tests/e2e/README.md</a></li>
<li><a href="#trunktestse2especscachecontrolheadersdirectivestestjs">trunk/tests/e2e/specs/cache-control-headers-directives.test.js</a></li>
<li><a href="#trunktestse2especsdashboardtestjs">trunk/tests/e2e/specs/dashboard.test.js</a></li>
<li><a href="#trunktestse2especseditpoststestjs">trunk/tests/e2e/specs/edit-posts.test.js</a></li>
<li><a href="#trunktestse2especsemptytrashrestoretrashedpoststestjs">trunk/tests/e2e/specs/empty-trash-restore-trashed-posts.test.js</a></li>
<li><a href="#trunktestse2especsgutenbergplugintestjs">trunk/tests/e2e/specs/gutenberg-plugin.test.js</a></li>
<li><a href="#trunktestse2especshellotestjs">trunk/tests/e2e/specs/hello.test.js</a></li>
<li><a href="#trunktestse2especsprofileapplicationspasswordstestjs">trunk/tests/e2e/specs/profile/applications-passwords.test.js</a></li>
<li><a href="#trunktestsperformancecompareresultsjs">trunk/tests/performance/compare-results.js</a></li>
<li><a href="#trunktestsperformanceresultsjs">trunk/tests/performance/results.js</a></li>
<li><a href="#trunktestsperformancespecshomeblockthemetestjs">trunk/tests/performance/specs/home-block-theme.test.js</a></li>
<li><a href="#trunktestsperformancespecshomeclassicthemetestjs">trunk/tests/performance/specs/home-classic-theme.test.js</a></li>
<li><a href="#trunktestsperformanceutilsjs">trunk/tests/performance/utils.js</a></li>
<li><a href="#trunktestsvisualregressionREADMEmd">trunk/tests/visual-regression/README.md</a></li>
<li><a href="#trunktestsvisualregressionspecsvisualsnapshotstestjs">trunk/tests/visual-regression/specs/visual-snapshots.test.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestse2econfigglobalsetupjs">trunk/tests/e2e/config/global-setup.js</a></li>
<li><a href="#trunktestse2eplaywrightconfigjs">trunk/tests/e2e/playwright.config.js</a></li>
<li><a href="#trunktestsperformanceconfigglobalsetupjs">trunk/tests/performance/config/global-setup.js</a></li>
<li><a href="#trunktestsperformanceconfigperformancereporterjs">trunk/tests/performance/config/performance-reporter.js</a></li>
<li><a href="#trunktestsperformanceplaywrightconfigjs">trunk/tests/performance/playwright.config.js</a></li>
<li><a href="#trunktestsvisualregressionplaywrightconfigjs">trunk/tests/visual-regression/playwright.config.js</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunktestse2econfigbootstrapjs">trunk/tests/e2e/config/bootstrap.js</a></li>
<li><a href="#trunktestse2ejestconfigjs">trunk/tests/e2e/jest.config.js</a></li>
<li><a href="#trunktestse2eruntestsjs">trunk/tests/e2e/run-tests.js</a></li>
<li><a href="#trunktestsperformanceconfigbootstrapjs">trunk/tests/performance/config/bootstrap.js</a></li>
<li><a href="#trunktestsperformancejestconfigjs">trunk/tests/performance/jest.config.js</a></li>
<li><a href="#trunktestsperformanceruntestsjs">trunk/tests/performance/run-tests.js</a></li>
<li>trunk/tests/visual-regression/config/</li>
<li><a href="#trunktestsvisualregressionjestconfigjs">trunk/tests/visual-regression/jest.config.js</a></li>
<li><a href="#trunktestsvisualregressionruntestsjs">trunk/tests/visual-regression/run-tests.js</a></li>
</ul>
<h3>Property Changed</h3>
<ul>
<li><a href="#trunktestsvisualregressionspecs">trunk/tests/visual-regression/specs/</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkgithubworkflowscodingstandardsyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.github/workflows/coding-standards.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.github/workflows/coding-standards.yml 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/.github/workflows/coding-standards.yml 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -142,8 +142,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> contents: read
</span><span class="cx" style="display: block; padding: 0 10px"> timeout-minutes: 20
</span><span class="cx" style="display: block; padding: 0 10px"> if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- env:
- PUPPETEER_SKIP_DOWNLOAD: ${{ true }}
</del><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> steps:
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Checkout repository
</span></span></pre></div>
<a id="trunkgithubworkflowsendtoendtestsyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.github/workflows/end-to-end-tests.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.github/workflows/end-to-end-tests.yml 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/.github/workflows/end-to-end-tests.yml 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42,11 +42,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> # - Sets up Node.js.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Logs debug information about the GitHub Action runner.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Installs npm dependencies.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ # - Install Playwright browsers.
</ins><span class="cx" style="display: block; padding: 0 10px"> # - Builds WordPress to run from the `build` directory.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Starts the WordPress Docker container.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Logs the running Docker containers.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Logs Docker debug information (about both the Docker installation within the runner and the WordPress container).
</span><span class="cx" style="display: block; padding: 0 10px"> # - Install WordPress within the Docker container.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ # - Install Gutenberg.
</ins><span class="cx" style="display: block; padding: 0 10px"> # - Run the E2E tests.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Ensures version-controlled files are not modified or deleted.
</span><span class="cx" style="display: block; padding: 0 10px"> e2e-tests:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -90,6 +92,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Install npm Dependencies
</span><span class="cx" style="display: block; padding: 0 10px"> run: npm ci
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ - name: Install Playwright browsers
+ run: npx playwright install --with-deps
+
</ins><span class="cx" style="display: block; padding: 0 10px"> - name: Build WordPress
</span><span class="cx" style="display: block; padding: 0 10px"> run: npm run build
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -115,6 +120,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> LOCAL_SCRIPT_DEBUG: ${{ matrix.LOCAL_SCRIPT_DEBUG }}
</span><span class="cx" style="display: block; padding: 0 10px"> run: npm run env:install
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ - name: Install Gutenberg
+ run: npm run env:cli -- plugin install gutenberg --path=/var/www/${{ env.LOCAL_DIR }}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> - name: Run E2E tests
</span><span class="cx" style="display: block; padding: 0 10px"> run: npm run test:e2e
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -129,6 +137,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Ensure version-controlled files are not modified or deleted
</span><span class="cx" style="display: block; padding: 0 10px"> run: git diff --exit-code
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ slack-notifications:
+ name: Slack Notifications
+ uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@trunk
+ permissions:
+ actions: read
+ contents: read
+ needs: [ e2e-tests ]
+ if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }}
+ with:
+ calling_status: ${{ contains( needs.*.result, 'cancelled' ) && 'cancelled' || contains( needs.*.result, 'failure' ) && 'failure' || 'success' }}
+ secrets:
+ SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }}
+ SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }}
+ SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }}
+ SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> failed-workflow:
</span><span class="cx" style="display: block; padding: 0 10px"> name: Failed workflow tasks
</span><span class="cx" style="display: block; padding: 0 10px"> runs-on: ubuntu-latest
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -141,7 +165,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> github.event_name != 'pull_request' &&
</span><span class="cx" style="display: block; padding: 0 10px"> github.run_attempt < 2 &&
</span><span class="cx" style="display: block; padding: 0 10px"> (
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- needs.e2e-tests.result == 'cancelled' || needs.e2e-tests.result == 'failure'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ contains( needs.*.result, 'cancelled' ) ||
+ contains( needs.*.result, 'failure' )
</ins><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> steps:
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Dispatch workflow run
</span></span></pre></div>
<a id="trunkgithubworkflowsperformanceyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.github/workflows/performance.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.github/workflows/performance.yml 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/.github/workflows/performance.yml 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31,10 +31,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> env:
</span><span class="cx" style="display: block; padding: 0 10px"> # Performance testing should be performed in an environment reflecting a standard production environment.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- WP_DEBUG: false
- SCRIPT_DEBUG: false
- SAVEQUERIES : false
- WP_DEVELOPMENT_MODE: ''
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ LOCAL_WP_DEBUG: false
+ LOCAL_SCRIPT_DEBUG: false
+ LOCAL_SAVEQUERIES: false
+ LOCAL_WP_DEVELOPMENT_MODE: "''"
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> # This workflow takes two sets of measurements — one for the current commit,
</span><span class="cx" style="display: block; padding: 0 10px"> # and another against a consistent version that is used as a baseline measurement.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -56,6 +56,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> # - Set up Node.js.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Log debug information.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Install npm dependencies.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ # - Install Playwright browsers.
</ins><span class="cx" style="display: block; padding: 0 10px"> # - Build WordPress.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Start Docker environment.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Log running Docker containers.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -73,6 +74,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> # - Run performance tests (previous/target commit).
</span><span class="cx" style="display: block; padding: 0 10px"> # - Print target performance tests results.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Reset to original commit.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ # - Install npm dependencies.
</ins><span class="cx" style="display: block; padding: 0 10px"> # - Set the environment to the baseline version.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Run baseline performance tests.
</span><span class="cx" style="display: block; padding: 0 10px"> # - Print baseline performance tests results.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -119,6 +121,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Install npm dependencies
</span><span class="cx" style="display: block; padding: 0 10px"> run: npm ci
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ - name: Install Playwright browsers
+ run: npx playwright install --with-deps
+
</ins><span class="cx" style="display: block; padding: 0 10px"> - name: Build WordPress
</span><span class="cx" style="display: block; padding: 0 10px"> run: npm run build
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -182,14 +187,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> run: npm run build
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Run target performance tests (base/previous commit)
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- run: npm run test:performance -- --prefix=before
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ env:
+ TEST_RESULTS_PREFIX: before
+ run: npm run test:performance
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Print target performance tests results
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- run: node ./tests/performance/results.js --prefix=before
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ env:
+ TEST_RESULTS_PREFIX: before
+ run: node ./tests/performance/results.js
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Reset to original commit
</span><span class="cx" style="display: block; padding: 0 10px"> run: git reset --hard $GITHUB_SHA
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ - name: Install npm dependencies
+ run: npm ci
+
</ins><span class="cx" style="display: block; padding: 0 10px"> - name: Set the environment to the baseline version
</span><span class="cx" style="display: block; padding: 0 10px"> run: |
</span><span class="cx" style="display: block; padding: 0 10px"> npm run env:cli -- core update --version=${{ env.BASE_TAG }} --force --path=/var/www/${{ env.LOCAL_DIR }}
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -196,10 +208,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> npm run env:cli -- core version --path=/var/www/${{ env.LOCAL_DIR }}
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Run baseline performance tests
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- run: npm run test:performance -- --prefix=base
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ env:
+ TEST_RESULTS_PREFIX: base
+ run: npm run test:performance
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Print baseline performance tests results
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- run: node ./tests/performance/results.js --prefix=base
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ env:
+ TEST_RESULTS_PREFIX: base
+ run: node ./tests/performance/results.js
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> - name: Compare results with base
</span><span class="cx" style="display: block; padding: 0 10px"> run: node ./tests/performance/compare-results.js ${{ runner.temp }}/summary.md
</span></span></pre></div>
<a id="trunkgithubworkflowsphpunittestsrunyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.github/workflows/phpunit-tests-run.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.github/workflows/phpunit-tests-run.yml 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/.github/workflows/phpunit-tests-run.yml 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -51,7 +51,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> LOCAL_DB_VERSION: ${{ inputs.db-version }}
</span><span class="cx" style="display: block; padding: 0 10px"> LOCAL_PHP_MEMCACHED: ${{ inputs.memcached }}
</span><span class="cx" style="display: block; padding: 0 10px"> PHPUNIT_CONFIG: ${{ inputs.phpunit-config }}
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- PUPPETEER_SKIP_DOWNLOAD: ${{ true }}
</del><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> jobs:
</span><span class="cx" style="display: block; padding: 0 10px"> # Runs the PHPUnit tests for WordPress.
</span></span></pre></div>
<a id="trunkgithubworkflowstestcoverageyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.github/workflows/test-coverage.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.github/workflows/test-coverage.yml 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/.github/workflows/test-coverage.yml 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -29,7 +29,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> permissions: {}
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> env:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- PUPPETEER_SKIP_DOWNLOAD: ${{ true }}
</del><span class="cx" style="display: block; padding: 0 10px"> LOCAL_PHP: '7.4-fpm'
</span><span class="cx" style="display: block; padding: 0 10px"> LOCAL_PHP_XDEBUG: true
</span><span class="cx" style="display: block; padding: 0 10px"> LOCAL_PHP_XDEBUG_MODE: 'coverage'
</span></span></pre></div>
<a id="trunkgithubworkflowstestnpmyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.github/workflows/test-npm.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.github/workflows/test-npm.yml 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/.github/workflows/test-npm.yml 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -37,9 +37,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> # Any needed permissions should be configured at the job level.
</span><span class="cx" style="display: block; padding: 0 10px"> permissions: {}
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-env:
- PUPPETEER_SKIP_DOWNLOAD: ${{ true }}
-
</del><span class="cx" style="display: block; padding: 0 10px"> jobs:
</span><span class="cx" style="display: block; padding: 0 10px"> # Verifies that installing npm dependencies and building WordPress works as expected.
</span><span class="cx" style="display: block; padding: 0 10px"> #
</span></span></pre></div>
<a id="trunkgitignore"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.gitignore</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.gitignore 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/.gitignore 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -100,4 +100,4 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /docker-compose.override.yml
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> # Visual regression test diffs
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tests/visual-regression/specs/__image_snapshots__
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+tests/visual-regression/specs/__snapshots__
</ins></span></pre></div>
<a id="trunkGruntfilejs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/Gruntfile.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/Gruntfile.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/Gruntfile.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -80,7 +80,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // First do `npm install` if package.json has changed.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- installChanged.watchPackage();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// installChanged.watchPackage();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Load tasks.
</span><span class="cx" style="display: block; padding: 0 10px"> require('matchdep').filterDev(['grunt-*', '!grunt-legacy-util']).forEach( grunt.loadNpmTasks );
</span></span></pre></div>
<a id="trunkpackagelockjson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/package-lock.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/package-lock.json 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/package-lock.json 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -106,10 +106,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><span class="cx" style="display: block; padding: 0 10px"> "devDependencies": {
</span><span class="cx" style="display: block; padding: 0 10px"> "@lodder/grunt-postcss": "^3.1.1",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@playwright/test": "1.32.0",
</ins><span class="cx" style="display: block; padding: 0 10px"> "@pmmmwh/react-refresh-webpack-plugin": "0.5.5",
</span><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/babel-preset-default": "7.26.6",
</span><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/dependency-extraction-webpack-plugin": "4.25.6",
</span><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/e2e-test-utils": "10.13.6",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@wordpress/e2e-test-utils-playwright": "0.11.0",
</ins><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/scripts": "26.13.6",
</span><span class="cx" style="display: block; padding: 0 10px"> "autoprefixer": "10.4.16",
</span><span class="cx" style="display: block; padding: 0 10px"> "chalk": "5.3.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3743,6 +3745,25 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "node": ">=8"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "node_modules/@playwright/test": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.32.0.tgz",
+ "integrity": "sha512-zOdGloaF0jeec7hqoLqM5S3L2rR4WxMJs6lgiAeR70JlH7Ml54ZPoIIf3X7cvnKde3Q9jJ/gaxkFh8fYI9s1rg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "playwright-core": "1.32.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "node_modules/@pmmmwh/react-refresh-webpack-plugin": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "0.5.5",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7011,14 +7032,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><span class="cx" style="display: block; padding: 0 10px"> "node_modules/@wordpress/e2e-test-utils-playwright": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "version": "0.10.6",
- "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-0.10.6.tgz",
- "integrity": "sha512-qUIcQTB4lFG6BUVCPtzs4gDeO/9Pzz1Knq3Uvt1QIYojy9Yr6G6c3f3Mudql+HFfiXoj3B3BxGbA4oLSb7bI6w==",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-0.11.0.tgz",
+ "integrity": "sha512-UxDkVvm24FJdi4nkn5+n9XirYxdJ1QDZgnHotdrgGRel8NOvlEOlhmT/xpuAPQrVwo+yynxEKeb1Y2AT6jX9og==",
</ins><span class="cx" style="display: block; padding: 0 10px"> "dev": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "dependencies": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "@wordpress/api-fetch": "^6.39.6",
- "@wordpress/keycodes": "^3.42.6",
- "@wordpress/url": "^3.43.6",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@wordpress/api-fetch": "^6.40.0",
+ "@wordpress/keycodes": "^3.43.0",
+ "@wordpress/url": "^3.44.0",
</ins><span class="cx" style="display: block; padding: 0 10px"> "change-case": "^4.1.2",
</span><span class="cx" style="display: block; padding: 0 10px"> "form-data": "^4.0.0",
</span><span class="cx" style="display: block; padding: 0 10px"> "get-port": "^5.1.1",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7032,6 +7053,79 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "@playwright/test": ">=1"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "node_modules/@wordpress/e2e-test-utils-playwright/node_modules/@wordpress/api-fetch": {
+ "version": "6.40.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-6.40.0.tgz",
+ "integrity": "sha512-sNk6vZW02ldci1EpNIjmm61323x/0n2Ra/cDHuehZf8avOH/OV0zF0dXxttT8M9Fncz+XZDSIHopm76dU3Phug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.16.0",
+ "@wordpress/i18n": "^4.43.0",
+ "@wordpress/url": "^3.44.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@wordpress/e2e-test-utils-playwright/node_modules/@wordpress/hooks": {
+ "version": "3.43.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-3.43.0.tgz",
+ "integrity": "sha512-SHSiyFUEsggihl0pDvY1l72q+fHMDyFHtIR3GCt0uV2ifctvoa/PIYdVwrxpGQaGdNEV25XCZ4kNldqJmfTddw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.16.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@wordpress/e2e-test-utils-playwright/node_modules/@wordpress/i18n": {
+ "version": "4.43.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-4.43.0.tgz",
+ "integrity": "sha512-XHU/vGgI+pgjJU9WzWDHke1u948z8i3OPpKUNdxc/gMcTkKaKM4D8DW1+VMSQHyU6pneP8+ph7EF+1RIehP3lQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.16.0",
+ "@wordpress/hooks": "^3.43.0",
+ "gettext-parser": "^1.3.1",
+ "memize": "^2.1.0",
+ "sprintf-js": "^1.1.1",
+ "tannin": "^1.2.0"
+ },
+ "bin": {
+ "pot-to-php": "tools/pot-to-php.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@wordpress/e2e-test-utils-playwright/node_modules/@wordpress/keycodes": {
+ "version": "3.43.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-3.43.0.tgz",
+ "integrity": "sha512-B6rYPiKFdQTlnJfm93R+usQnjEODUX/K4+hMvY5ZZOinvxe7KyU/xyFGz7gRrS8WmIEYcJowqSmAlGgVs4XwKQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.16.0",
+ "@wordpress/i18n": "^4.43.0",
+ "change-case": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@wordpress/e2e-test-utils-playwright/node_modules/@wordpress/url": {
+ "version": "3.44.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-3.44.0.tgz",
+ "integrity": "sha512-QNtTPFg/cGHTJLOvOtQCvCgn5quFQgJml8A88I05o4dyUH/tc92rb8LNXi0qcVz/z4JPrx2g3+Ki8heYellP4A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.16.0",
+ "remove-accents": "^0.5.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "node_modules/@wordpress/e2e-test-utils-playwright/node_modules/form-data": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "4.0.0",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7956,6 +8050,28 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "react-dom": "^18.0.0"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "node_modules/@wordpress/scripts/node_modules/@wordpress/e2e-test-utils-playwright": {
+ "version": "0.10.6",
+ "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-0.10.6.tgz",
+ "integrity": "sha512-qUIcQTB4lFG6BUVCPtzs4gDeO/9Pzz1Knq3Uvt1QIYojy9Yr6G6c3f3Mudql+HFfiXoj3B3BxGbA4oLSb7bI6w==",
+ "dev": true,
+ "dependencies": {
+ "@wordpress/api-fetch": "^6.39.6",
+ "@wordpress/keycodes": "^3.42.6",
+ "@wordpress/url": "^3.43.6",
+ "change-case": "^4.1.2",
+ "form-data": "^4.0.0",
+ "get-port": "^5.1.1",
+ "lighthouse": "^10.4.0",
+ "mime": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "@playwright/test": ">=1"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "node_modules/@wordpress/scripts/node_modules/ajv": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "8.12.0",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -8099,6 +8215,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "node": ">=8"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "node_modules/@wordpress/scripts/node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "node_modules/@wordpress/scripts/node_modules/glob-parent": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "6.0.2",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -8158,6 +8288,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "node": ">=8"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "node_modules/@wordpress/scripts/node_modules/mime": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "dev": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "node_modules/@wordpress/scripts/node_modules/p-locate": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "4.1.0",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -36729,6 +36871,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@playwright/test": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.32.0.tgz",
+ "integrity": "sha512-zOdGloaF0jeec7hqoLqM5S3L2rR4WxMJs6lgiAeR70JlH7Ml54ZPoIIf3X7cvnKde3Q9jJ/gaxkFh8fYI9s1rg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "fsevents": "2.3.2",
+ "playwright-core": "1.32.0"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "@pmmmwh/react-refresh-webpack-plugin": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "0.5.5",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -39263,14 +39416,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/e2e-test-utils-playwright": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "version": "0.10.6",
- "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-0.10.6.tgz",
- "integrity": "sha512-qUIcQTB4lFG6BUVCPtzs4gDeO/9Pzz1Knq3Uvt1QIYojy9Yr6G6c3f3Mudql+HFfiXoj3B3BxGbA4oLSb7bI6w==",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-0.11.0.tgz",
+ "integrity": "sha512-UxDkVvm24FJdi4nkn5+n9XirYxdJ1QDZgnHotdrgGRel8NOvlEOlhmT/xpuAPQrVwo+yynxEKeb1Y2AT6jX9og==",
</ins><span class="cx" style="display: block; padding: 0 10px"> "dev": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "requires": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "@wordpress/api-fetch": "^6.39.6",
- "@wordpress/keycodes": "^3.42.6",
- "@wordpress/url": "^3.43.6",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@wordpress/api-fetch": "^6.40.0",
+ "@wordpress/keycodes": "^3.43.0",
+ "@wordpress/url": "^3.44.0",
</ins><span class="cx" style="display: block; padding: 0 10px"> "change-case": "^4.1.2",
</span><span class="cx" style="display: block; padding: 0 10px"> "form-data": "^4.0.0",
</span><span class="cx" style="display: block; padding: 0 10px"> "get-port": "^5.1.1",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -39278,6 +39431,61 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "mime": "^3.0.0"
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><span class="cx" style="display: block; padding: 0 10px"> "dependencies": {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@wordpress/api-fetch": {
+ "version": "6.40.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-6.40.0.tgz",
+ "integrity": "sha512-sNk6vZW02ldci1EpNIjmm61323x/0n2Ra/cDHuehZf8avOH/OV0zF0dXxttT8M9Fncz+XZDSIHopm76dU3Phug==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.16.0",
+ "@wordpress/i18n": "^4.43.0",
+ "@wordpress/url": "^3.44.0"
+ }
+ },
+ "@wordpress/hooks": {
+ "version": "3.43.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-3.43.0.tgz",
+ "integrity": "sha512-SHSiyFUEsggihl0pDvY1l72q+fHMDyFHtIR3GCt0uV2ifctvoa/PIYdVwrxpGQaGdNEV25XCZ4kNldqJmfTddw==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.16.0"
+ }
+ },
+ "@wordpress/i18n": {
+ "version": "4.43.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-4.43.0.tgz",
+ "integrity": "sha512-XHU/vGgI+pgjJU9WzWDHke1u948z8i3OPpKUNdxc/gMcTkKaKM4D8DW1+VMSQHyU6pneP8+ph7EF+1RIehP3lQ==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.16.0",
+ "@wordpress/hooks": "^3.43.0",
+ "gettext-parser": "^1.3.1",
+ "memize": "^2.1.0",
+ "sprintf-js": "^1.1.1",
+ "tannin": "^1.2.0"
+ }
+ },
+ "@wordpress/keycodes": {
+ "version": "3.43.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-3.43.0.tgz",
+ "integrity": "sha512-B6rYPiKFdQTlnJfm93R+usQnjEODUX/K4+hMvY5ZZOinvxe7KyU/xyFGz7gRrS8WmIEYcJowqSmAlGgVs4XwKQ==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.16.0",
+ "@wordpress/i18n": "^4.43.0",
+ "change-case": "^4.1.2"
+ }
+ },
+ "@wordpress/url": {
+ "version": "3.44.0",
+ "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-3.44.0.tgz",
+ "integrity": "sha512-QNtTPFg/cGHTJLOvOtQCvCgn5quFQgJml8A88I05o4dyUH/tc92rb8LNXi0qcVz/z4JPrx2g3+Ki8heYellP4A==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.16.0",
+ "remove-accents": "^0.5.0"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "form-data": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "4.0.0",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -39957,6 +40165,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "webpack-dev-server": "^4.4.0"
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><span class="cx" style="display: block; padding: 0 10px"> "dependencies": {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@wordpress/e2e-test-utils-playwright": {
+ "version": "0.10.6",
+ "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-0.10.6.tgz",
+ "integrity": "sha512-qUIcQTB4lFG6BUVCPtzs4gDeO/9Pzz1Knq3Uvt1QIYojy9Yr6G6c3f3Mudql+HFfiXoj3B3BxGbA4oLSb7bI6w==",
+ "dev": true,
+ "requires": {
+ "@wordpress/api-fetch": "^6.39.6",
+ "@wordpress/keycodes": "^3.42.6",
+ "@wordpress/url": "^3.43.6",
+ "change-case": "^4.1.2",
+ "form-data": "^4.0.0",
+ "get-port": "^5.1.1",
+ "lighthouse": "^10.4.0",
+ "mime": "^3.0.0"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "ajv": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "8.12.0",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -40053,6 +40277,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "path-exists": "^4.0.0"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "glob-parent": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "6.0.2",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -40097,6 +40332,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "p-locate": "^4.1.0"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "mime": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "dev": true
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "p-locate": {
</span><span class="cx" style="display: block; padding: 0 10px"> "version": "4.1.0",
</span><span class="cx" style="display: block; padding: 0 10px"> "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
</span></span></pre></div>
<a id="trunkpackagejson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/package.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/package.json 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/package.json 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -25,10 +25,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ],
</span><span class="cx" style="display: block; padding: 0 10px"> "devDependencies": {
</span><span class="cx" style="display: block; padding: 0 10px"> "@lodder/grunt-postcss": "^3.1.1",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@playwright/test": "1.32.0",
</ins><span class="cx" style="display: block; padding: 0 10px"> "@pmmmwh/react-refresh-webpack-plugin": "0.5.5",
</span><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/babel-preset-default": "7.26.6",
</span><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/dependency-extraction-webpack-plugin": "4.25.6",
</span><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/e2e-test-utils": "10.13.6",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "@wordpress/e2e-test-utils-playwright": "0.11.0",
</ins><span class="cx" style="display: block; padding: 0 10px"> "@wordpress/scripts": "26.13.6",
</span><span class="cx" style="display: block; padding: 0 10px"> "autoprefixer": "10.4.16",
</span><span class="cx" style="display: block; padding: 0 10px"> "chalk": "5.3.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -189,10 +191,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "env:cli": "node ./tools/local-env/scripts/docker.js run cli",
</span><span class="cx" style="display: block; padding: 0 10px"> "env:logs": "node ./tools/local-env/scripts/docker.js logs",
</span><span class="cx" style="display: block; padding: 0 10px"> "env:pull": "node ./tools/local-env/scripts/docker.js pull",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "test:performance": "node ./tests/performance/run-tests.js",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "test:performance": "wp-scripts test-playwright --config tests/performance/playwright.config.js",
</ins><span class="cx" style="display: block; padding: 0 10px"> "test:php": "node ./tools/local-env/scripts/docker.js run -T php composer update -W && node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "test:e2e": "node ./tests/e2e/run-tests.js",
- "test:visual": "node ./tests/visual-regression/run-tests.js",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "test:e2e": "wp-scripts test-playwright --config tests/e2e/playwright.config.js",
+ "test:visual": "wp-scripts test-playwright --config tests/visual-regression/playwright.config.js",
</ins><span class="cx" style="display: block; padding: 0 10px"> "sync-gutenberg-packages": "grunt sync-gutenberg-packages",
</span><span class="cx" style="display: block; padding: 0 10px"> "postsync-gutenberg-packages": "grunt wp-packages:sync-stable-blocks && grunt build --dev && grunt build"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestse2eREADMEmd"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/README.md</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/README.md 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/README.md 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5,7 +5,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
## Running the tests
-The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username=admin and password=password.
+The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`.
If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md).
@@ -20,16 +20,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this:
```
-npm run test:e2e -- --wordpress-base-url=http://mycustomurl --wordpress-username=username --wordpress-password=password
+WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e
```
**DO NOT run these tests in an actual production environment, as they will delete all your content.**
-For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode.
+For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode:
```
-npm run test:e2e -- --puppeteer-interactive
+npm run test:e2e -- --ui
```
+[UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience
complete with watch mode.
+All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test.
+
You can also run a single test file separately:
```
@@ -41,6 +44,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">
* Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing
-* Gutenberg e2e-test-utils package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils
+* Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright
-* Puppeteer API docs: https://github.com/puppeteer/puppeteer#readme (the version we are using is indicated in the @wordpress/scripts package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json)
+* Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json)
</span></span></pre></div>
<a id="trunktestse2econfigbootstrapjs"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/e2e/config/bootstrap.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/config/bootstrap.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/config/bootstrap.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,145 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { get } from 'lodash';
-import {
- clearLocalStorage,
- enablePageDialogAccept,
- setBrowserViewport,
-} from '@wordpress/e2e-test-utils';
-
-/**
- * Environment variables
- */
-const { PUPPETEER_TIMEOUT } = process.env;
-
-/**
- * Set of console logging types observed to protect against unexpected yet
- * handled (i.e. not catastrophic) errors or warnings. Each key corresponds
- * to the Puppeteer ConsoleMessage type, its value the corresponding function
- * on the console global object.
- *
- * @type {Object<string,string>}
- */
-const OBSERVED_CONSOLE_MESSAGE_TYPES = {
- warning: 'warn',
- error: 'error',
-};
-
-/**
- * Array of page event tuples of [ eventName, handler ].
- *
- * @type {Array}
- */
-const pageEvents = [];
-
-// The Jest timeout is increased because these tests are a bit slow
-jest.setTimeout( PUPPETEER_TIMEOUT || 100000 );
-
-
-/**
- * Adds an event listener to the page to handle additions of page event
- * handlers, to assure that they are removed at test teardown.
- */
-function capturePageEventsForTearDown() {
- page.on( 'newListener', ( eventName, listener ) => {
- pageEvents.push( [ eventName, listener ] );
- } );
-}
-
-/**
- * Removes all bound page event handlers.
- */
-function removePageEvents() {
- pageEvents.forEach( ( [ eventName, handler ] ) => {
- page.removeListener( eventName, handler );
- } );
-}
-
-/**
- * Adds a page event handler to emit uncaught exception to process if one of
- * the observed console logging types is encountered.
- */
-function observeConsoleLogging() {
- page.on( 'console', ( message ) => {
- const type = message.type();
- if ( ! OBSERVED_CONSOLE_MESSAGE_TYPES.hasOwnProperty( type ) ) {
- return;
- }
-
- let text = message.text();
-
- // An exception is made for _blanket_ deprecation warnings: Those
- // which log regardless of whether a deprecated feature is in use.
- if ( text.includes( 'This is a global warning' ) ) {
- return;
- }
-
- // An exception is made for jQuery migrate console warnings output by
- // the unminified script loaded in development environments.
- if ( text.includes( 'JQMIGRATE' ) ) {
- return;
- }
-
- // Viewing posts on the front end can result in this error, which
- // has nothing to do with Gutenberg.
- if ( text.includes( 'net::ERR_UNKNOWN_URL_SCHEME' ) ) {
- return;
- }
-
- // A bug present in WordPress 5.2 will produce console warnings when
- // loading the Dashicons font. These can be safely ignored, as they do
- // not otherwise regress on application behavior. This logic should be
- // removed once the associated ticket has been closed.
- //
- // See: https://core.trac.wordpress.org/ticket/47183
- if (
- text.startsWith( 'Failed to decode downloaded font:' ) ||
- text.startsWith( 'OTS parsing error:' )
- ) {
- return;
- }
-
- const logFunction = OBSERVED_CONSOLE_MESSAGE_TYPES[ type ];
-
- // As of Puppeteer 1.6.1, `message.text()` wrongly returns an object of
- // type JSHandle for error logging, instead of the expected string.
- //
- // See: https://github.com/GoogleChrome/puppeteer/issues/3397
- //
- // The recommendation there to asynchronously resolve the error value
- // upon a console event may be prone to a race condition with the test
- // completion, leaving a possibility of an error not being surfaced
- // correctly. Instead, the logic here synchronously inspects the
- // internal object shape of the JSHandle to find the error text. If it
- // cannot be found, the default text value is used instead.
- text = get( message.args(), [ 0, '_remoteObject', 'description' ], text );
-
- // Disable reason: We intentionally bubble up the console message
- // which, unless the test explicitly anticipates the logging via
- // @wordpress/jest-console matchers, will cause the intended test
- // failure.
-
- // eslint-disable-next-line no-console
- console[ logFunction ]( text );
- } );
-}
-
-// Before every test suite run, delete all content created by the test. This ensures
-// other posts/comments/etc. aren't dirtying tests and tests don't depend on
-// each other's side-effects.
-beforeAll( async () => {
- capturePageEventsForTearDown();
- enablePageDialogAccept();
- observeConsoleLogging();
- await page.emulateMediaFeatures( [
- { name: 'prefers-reduced-motion', value: 'reduce' },
- ] );
- await setBrowserViewport( 'large' );
-} );
-
-afterEach( async () => {
- await clearLocalStorage();
- await setBrowserViewport( 'large' );
-} );
-
-afterAll( () => {
- removePageEvents();
-} );
</del></span></pre></div>
<a id="trunktestse2econfigglobalsetupjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/e2e/config/global-setup.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/config/global-setup.js (rev 0)
+++ trunk/tests/e2e/config/global-setup.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,43 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { request } from '@playwright/test';
+
+/**
+ * WordPress dependencies
+ */
+import { RequestUtils } from '@wordpress/e2e-test-utils-playwright';
+
+/**
+ *
+ * @param {import('@playwright/test').FullConfig} config
+ * @returns {Promise<void>}
+ */
+async function globalSetup( config ) {
+ const { storageState, baseURL } = config.projects[ 0 ].use;
+ const storageStatePath =
+ typeof storageState === 'string' ? storageState : undefined;
+
+ const requestContext = await request.newContext( {
+ baseURL,
+ } );
+
+ const requestUtils = new RequestUtils( requestContext, {
+ storageStatePath,
+ } );
+
+ // Authenticate and save the storageState to disk.
+ await requestUtils.setupRest();
+
+ // Reset the test environment before running the tests.
+ await Promise.all( [
+ requestUtils.activateTheme( 'twentytwentyone' ),
+ requestUtils.deleteAllPosts(),
+ requestUtils.deleteAllBlocks(),
+ requestUtils.resetPreferences(),
+ ] );
+
+ await requestContext.dispose();
+}
+
+export default globalSetup;
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/e2e/config/global-setup.js
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestse2ejestconfigjs"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/e2e/jest.config.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/jest.config.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/jest.config.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,10 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const config = require( '@wordpress/scripts/config/jest-e2e.config' );
-
-const jestE2EConfig = {
- ...config,
- setupFilesAfterEnv: [
- '<rootDir>/config/bootstrap.js',
- ],
-};
-
-module.exports = jestE2EConfig;
</del></span></pre></div>
<a id="trunktestse2eplaywrightconfigjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/e2e/playwright.config.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/playwright.config.js (rev 0)
+++ trunk/tests/e2e/playwright.config.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,27 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import path from 'node:path';
+import { defineConfig } from '@playwright/test';
+
+/**
+ * WordPress dependencies
+ */
+const baseConfig = require( '@wordpress/scripts/config/playwright.config' );
+
+process.env.WP_ARTIFACTS_PATH ??= path.join( process.cwd(), 'artifacts' );
+process.env.STORAGE_STATE_PATH ??= path.join(
+ process.env.WP_ARTIFACTS_PATH,
+ 'storage-states/admin.json'
+);
+
+const config = defineConfig( {
+ ...baseConfig,
+ globalSetup: require.resolve( './config/global-setup.js' ),
+ webServer: {
+ ...baseConfig.webServer,
+ command: 'npm run env:start',
+ },
+} );
+
+export default config;
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/e2e/playwright.config.js
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestse2eruntestsjs"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/e2e/run-tests.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/run-tests.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/run-tests.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,13 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const dotenv = require( 'dotenv' );
-const dotenv_expand = require( 'dotenv-expand' );
-const { execSync } = require( 'child_process' );
-
-// WP_BASE_URL interpolates LOCAL_PORT, so needs to be parsed by dotenv_expand().
-dotenv_expand.expand( dotenv.config() );
-
-// Run the tests, passing additional arguments through to the test script.
-execSync(
- 'wp-scripts test-e2e --config tests/e2e/jest.config.js ' +
- process.argv.slice( 2 ).join( ' ' ),
- { stdio: 'inherit' }
-);
</del></span></pre></div>
<a id="trunktestse2especscachecontrolheadersdirectivestestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/specs/cache-control-headers-directives.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/specs/cache-control-headers-directives.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/specs/cache-control-headers-directives.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,38 +1,46 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import {
- visitAdminPage,
- createNewPost,
- publishPost,
- trashAllPosts,
- createURL,
- logout,
-} from "@wordpress/e2e-test-utils";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+import { test, expect } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe( 'Cache Control header directives', () => {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Cache Control header directives', () => {
+ test.beforeAll( async ( { requestUtils } ) => {
+ await requestUtils.deleteAllPosts();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- beforeEach( async () => {
- await trashAllPosts();
- } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test(
+ 'No private directive present in cache control when user not logged in.',
+ async ( { browser, admin, editor}
+ ) => {
+ await admin.createNewPost( { title: 'Hello World' } );
+ await editor.publishPost();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'No private directive present in cache control when user not logged in.', async () => {
- await createNewPost( { title: 'Hello World' } );
- await publishPost();
- await logout();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.visitAdminPage( '/' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const response = await page.goto( createURL( '/hello-world/' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Create a new incognito browser context to simulate logged-out state.
+ const context = await browser.newContext();
+ const loggedOutPage = await context.newPage();
+
+ const response = await loggedOutPage.goto( '/hello-world/' );
</ins><span class="cx" style="display: block; padding: 0 10px"> const responseHeaders = response.headers();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Dispose context once it's no longer needed.
+ await context.close();
+
</ins><span class="cx" style="display: block; padding: 0 10px"> expect( responseHeaders ).toEqual( expect.not.objectContaining( { "cache-control": "no-store" } ) );
</span><span class="cx" style="display: block; padding: 0 10px"> expect( responseHeaders ).toEqual( expect.not.objectContaining( { "cache-control": "private" } ) );
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Private directive header present in cache control when logged in.', async () => {
- await visitAdminPage( '/' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test(
+ 'Private directive header present in cache control when logged in.',
+ async ( { page, admin }
+ ) => {
+ await admin.visitAdminPage( '/' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const response = await page.goto( createURL( '/wp-admin' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const response = await page.goto( '/wp-admin' );
</ins><span class="cx" style="display: block; padding: 0 10px"> const responseHeaders = response.headers();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> expect( responseHeaders[ 'cache-control' ] ).toContain( 'no-store' );
</span><span class="cx" style="display: block; padding: 0 10px"> expect( responseHeaders[ 'cache-control' ] ).toContain( 'private' );
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre></div>
<a id="trunktestse2especsdashboardtestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/specs/dashboard.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/specs/dashboard.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/specs/dashboard.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,26 +1,29 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import {
- pressKeyTimes,
- trashAllPosts,
- visitAdminPage,
-} from '@wordpress/e2e-test-utils';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+import { test, expect } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe( 'Quick Draft', () => {
- beforeEach( async () => {
- await trashAllPosts();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Quick Draft', () => {
+ test.beforeEach( async ({ requestUtils }) => {
+ await requestUtils.deleteAllPosts();
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Allows draft to be created with Title and Content', async () => {
- await visitAdminPage( '/' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Allows draft to be created with Title and Content', async ( {
+ admin,
+ page
+ } ) => {
+ await admin.visitAdminPage( '/' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wait for Quick Draft title field to appear and focus it
- const draftTitleField = await page.waitForSelector(
- '#quick-press #title'
- );
- await draftTitleField.focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Wait for Quick Draft title field to appear.
+ const draftTitleField = page.locator(
+ '#quick-press'
+ ).getByRole( 'textbox', { name: 'Title' } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Type in a title.
- await page.keyboard.type( 'Test Draft Title' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect( draftTitleField ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Focus and fill in a title.
+ await draftTitleField.fill( 'Test Draft Title' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Navigate to content field and type in some content
</span><span class="cx" style="display: block; padding: 0 10px"> await page.keyboard.press( 'Tab' );
</span><span class="cx" style="display: block; padding: 0 10px"> await page.keyboard.type( 'Test Draft Content' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30,47 +33,42 @@
</span><span class="cx" style="display: block; padding: 0 10px"> await page.keyboard.press( 'Enter' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Check that new draft appears in Your Recent Drafts section
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const newDraft = await page.waitForSelector( '.drafts .draft-title' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect(
+ page.locator( '.drafts .draft-title' ).first().getByRole( 'link' )
+ ).toHaveText( 'Test Draft Title' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- expect(
- await newDraft.evaluate( ( element ) => element.innerText )
- ).toContain( 'Test Draft Title' );
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Check that new draft appears in Posts page
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await visitAdminPage( '/edit.php' );
- const postsListDraft = await page.waitForSelector(
- '.type-post.status-draft .title'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.visitAdminPage( '/edit.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- expect(
- await postsListDraft.evaluate( ( element ) => element.innerText )
- ).toContain( 'Test Draft Title' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect(
+ page.locator( '.type-post.status-draft .title' ).first()
+ ).toContainText( 'Test Draft Title' );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Allows draft to be created without Title or Content', async () => {
- await visitAdminPage( '/' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Allows draft to be created without Title or Content', async ( {
+ admin,
+ page
+ } ) => {
+ await admin.visitAdminPage( '/' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Wait for Save Draft button to appear and click it
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const saveDraftButton = await page.waitForSelector(
- '#quick-press #save-post'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const saveDraftButton = page.locator(
+ '#quick-press'
+ ).getByRole( 'button', { name: 'Save Draft' } );
+
+ await expect( saveDraftButton ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px"> await saveDraftButton.click();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Check that new draft appears in Your Recent Drafts section
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const newDraft = await page.waitForSelector( '.drafts .draft-title a' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect(
+ page.locator( '.drafts .draft-title' ).first().getByRole( 'link' )
+ ).toHaveText( 'Untitled' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- expect(
- await newDraft.evaluate( ( element ) => element.innerText )
- ).toContain( '(no title)' );
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Check that new draft appears in Posts page
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await visitAdminPage( '/edit.php' );
- const postsListDraft = await page.waitForSelector(
- '.type-post.status-draft .title a'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.visitAdminPage( '/edit.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- expect(
- await postsListDraft.evaluate( ( element ) => element.innerText )
- ).toContain( '(no title)' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect(
+ page.locator( '.type-post.status-draft .title' ).first()
+ ).toContainText( 'Untitled' );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre></div>
<a id="trunktestse2especseditpoststestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/specs/edit-posts.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/specs/edit-posts.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/specs/edit-posts.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,90 +1,93 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import {
- createNewPost,
- pressKeyTimes,
- publishPost,
- trashAllPosts,
- visitAdminPage,
-} from '@wordpress/e2e-test-utils';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+import { test, expect } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe( 'Edit Posts', () => {
- beforeEach( async () => {
- await trashAllPosts();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Edit Posts', () => {
+ test.beforeEach( async ( { requestUtils }) => {
+ await requestUtils.deleteAllPosts();
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'displays a message in the posts table when no posts are present', async () => {
- await visitAdminPage( '/edit.php' );
- const noPostsMessage = await page.$x(
- '//td[text()="No posts found."]'
- );
- expect( noPostsMessage.length ).toBe( 1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'displays a message in the posts table when no posts are present',async ( {
+ admin,
+ page,
+ } ) => {
+ await admin.visitAdminPage( '/edit.php' );
+ await expect(
+ page.getByRole( 'cell', { name: 'No posts found.' } )
+ ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'shows a single post after one is published with the correct title', async () => {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'shows a single post after one is published with the correct title',async ( {
+ admin,
+ editor,
+ page,
+ } ) => {
</ins><span class="cx" style="display: block; padding: 0 10px"> const title = 'Test Title';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await createNewPost( { title } );
- await publishPost();
- await visitAdminPage( '/edit.php' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.createNewPost( { title } );
+ await editor.publishPost();
+ await admin.visitAdminPage( '/edit.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await page.waitForSelector( '#the-list .type-post' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const listTable = page.getByRole( 'table', { name: 'Table ordered by' } );
+ await expect( listTable ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Expect there to be one row in the post list.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const posts = await page.$$( '#the-list .type-post' );
- expect( posts.length ).toBe( 1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const posts = listTable.locator( '.row-title' );
+ await expect( posts ).toHaveCount( 1 );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const [ firstPost ] = posts;
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Expect the title of the post to be correct.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const postTitle = await firstPost.$x(
- `//a[contains(@class, "row-title")][contains(text(), "${ title }")]`
- );
- expect( postTitle.length ).toBe( 1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ expect( posts.first() ).toHaveText( title );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'allows an existing post to be edited using the Edit button', async () => {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'allows an existing post to be edited using the Edit button', async ( {
+ admin,
+ editor,
+ page,
+ } ) => {
</ins><span class="cx" style="display: block; padding: 0 10px"> const title = 'Test Title';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await createNewPost( { title } );
- await publishPost();
- await visitAdminPage( '/edit.php' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.createNewPost( { title } );
+ await editor.publishPost();
+ await admin.visitAdminPage( '/edit.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await page.waitForSelector( '#the-list .type-post' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const listTable = page.getByRole( 'table', { name: 'Table ordered by' } );
+ await expect( listTable ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Click the post title (edit) link
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const [ editLink ] = await page.$x(
- `//a[contains(@class, "row-title")][contains(text(), "${ title }")]`
- );
- await editLink.click();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await listTable.getByRole( 'link', { name: `“${ title }” (Edit)` } ).click();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Wait for the editor iframe to load, and switch to it as the active content frame.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const editorFrame = await page.waitForSelector( 'iframe[name="editor-canvas"]' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await page
+ .frameLocator( '[name=editor-canvas]' )
+ .locator( 'body > *' )
+ .first()
+ .waitFor();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const innerFrame = await editorFrame.contentFrame();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const editorPostTitle = editor.canvas.getByRole( 'textbox', { name: 'Add title' } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Wait for title field to render onscreen.
- await innerFrame.waitForSelector( '.editor-post-title__input' );
-
- // Expect to now be in the editor with the correct post title shown.
- const editorPostTitleInput = await innerFrame.$x(
- `//h1[contains(@class, "editor-post-title__input")][contains(text(), "${ title }")]`
- );
- expect( editorPostTitleInput.length ).toBe( 1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Expect title field to be in the editor with correct title shown.
+ await expect( editorPostTitle ).toBeVisible();
+ await expect( editorPostTitle ).toHaveText( title );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'allows an existing post to be quick edited using the Quick Edit button', async () => {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'allows an existing post to be quick edited using the Quick Edit button', async ( {
+ admin,
+ editor,
+ page,
+ pageUtils
+ } ) => {
</ins><span class="cx" style="display: block; padding: 0 10px"> const title = 'Test Title';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await createNewPost( { title } );
- await publishPost();
- await visitAdminPage( '/edit.php' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.createNewPost( { title } );
+ await editor.publishPost();
+ await admin.visitAdminPage( '/edit.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await page.waitForSelector( '#the-list .type-post' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const listTable = page.getByRole( 'table', { name: 'Table ordered by' } );
+ await expect( listTable ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Focus on the post title link.
- const [ editLink ] = await page.$x(
- `//a[contains(@class, "row-title")][contains(text(), "${ title }")]`
- );
- await editLink.focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // // Focus on the post title link.
+ await listTable.getByRole( 'link', { name: `“${ title }” (Edit)` } ).focus();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Tab to the Quick Edit button and press Enter to quick edit.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await pressKeyTimes( 'Tab', 2 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await pageUtils.pressKeys( 'Tab', { times: 2 } )
</ins><span class="cx" style="display: block; padding: 0 10px"> await page.keyboard.press( 'Enter' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Type in the currently focused (title) field to modify the title, testing that focus is moved to the input.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -91,47 +94,42 @@
</span><span class="cx" style="display: block; padding: 0 10px"> await page.keyboard.type( ' Edited' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Update the post.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await page.click( '.button.save' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await page.getByRole( 'button', { name: 'Update' } ).click();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Wait for the quick edit button to reappear.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await page.waitForSelector( 'button.editinline', { visible: true } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect( page.getByRole( 'button', { name: 'Quick Edit' } ) ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Expect there to be one row in the post list.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const posts = await page.$$( '#the-list tr.type-post' );
- expect( posts.length ).toBe( 1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const posts = listTable.locator( '.row-title' );
+ await expect( posts ).toHaveCount( 1 );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const [ firstPost ] = posts;
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Expect the title of the post to be correct.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const postTitle = await firstPost.$x(
- `//a[contains(@class, "row-title")][contains(text(), "${ title } Edited")]`
- );
- expect( postTitle.length ).toBe( 1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ expect( posts.first() ).toHaveText( `${ title } Edited` );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'allows an existing post to be deleted using the Trash button', async () => {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ test( 'allows an existing post to be deleted using the Trash button', async ( {
+ admin,
+ editor,
+ page,
+ pageUtils
+ } ) => {
</ins><span class="cx" style="display: block; padding: 0 10px"> const title = 'Test Title';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await createNewPost( { title } );
- await publishPost();
- await visitAdminPage( '/edit.php' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.createNewPost( { title } );
+ await editor.publishPost();
+ await admin.visitAdminPage( '/edit.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await page.waitForSelector( '#the-list .type-post' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const listTable = page.getByRole( 'table', { name: 'Table ordered by' } );
+ await expect( listTable ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Focus on the post title link.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const [ editLink ] = await page.$x(
- `//a[contains(@class, "row-title")][contains(text(), "${ title }")]`
- );
- await editLink.focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await listTable.getByRole( 'link', { name: `“${ title }” (Edit)` } ).focus();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Tab to the Trash button and press Enter to delete the post.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await pressKeyTimes( 'Tab', 3 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await pageUtils.pressKeys( 'Tab', { times: 3 } )
</ins><span class="cx" style="display: block; padding: 0 10px"> await page.keyboard.press( 'Enter' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const noPostsMessage = await page.waitForSelector(
- '#the-list .no-items td'
- );
-
- expect(
- await noPostsMessage.evaluate( ( element ) => element.innerText )
- ).toBe( 'No posts found.' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect(
+ page.getByRole( 'cell', { name: 'No posts found.' } )
+ ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre></div>
<a id="trunktestse2especsemptytrashrestoretrashedpoststestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/specs/empty-trash-restore-trashed-posts.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/specs/empty-trash-restore-trashed-posts.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/specs/empty-trash-restore-trashed-posts.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,72 +1,55 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import {
- visitAdminPage,
- createNewPost,
- trashAllPosts,
- publishPost,
-} from "@wordpress/e2e-test-utils";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+import { test, expect } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const POST_TITLE = "Test Title";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const POST_TITLE = 'Test Title';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe("Empty Trash", () => {
- async function createPost(title) {
- // Create a Post
- await createNewPost({ title });
- await publishPost();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Empty Trash', () => {
+ test.beforeEach( async ( { requestUtils } ) => {
+ await requestUtils.deleteAllPosts();
+ });
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- afterEach(async () => {
- await trashAllPosts();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test('Empty Trash', async ({ admin, editor, page }) => {
+ await admin.createNewPost( { title: POST_TITLE } );
+ await editor.publishPost();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it("Empty Trash", async () => {
- await createPost(POST_TITLE);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.visitAdminPage( '/edit.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await visitAdminPage("/edit.php");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const listTable = page.getByRole( 'table', { name: 'Table ordered by' } );
+ await expect( listTable ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move post to trash
- await page.hover(`[aria-label^="“${POST_TITLE}”"]`);
- await page.click(`[aria-label='Move “${POST_TITLE}” to the Trash']`);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move post to trash
+ await listTable.getByRole( 'link', { name: `“${ POST_TITLE }” (Edit)` } ).hover();
+ await listTable.getByRole( 'link', { name: `Move “${POST_TITLE}” to the Trash` } ).click();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Empty trash
- const trashTab = await page.waitForXPath('//h2[text()="Filter posts list"]/following-sibling::ul//a[contains(text(), "Trash")]');
- await Promise.all([
- trashTab.click(),
- page.waitForNavigation(),
- ]);
- const deleteAllButton = await page.waitForSelector('input[value="Empty Trash"]');
- await Promise.all([
- deleteAllButton.click(),
- page.waitForNavigation(),
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Empty trash
+ await page.getByRole( 'link', { name: 'Trash' } ).click();
+ await page.getByRole( 'button', { name: 'Empty Trash' } ).first().click();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const messageElement = await page.waitForSelector("#message");
- const message = await messageElement.evaluate((node) => node.innerText);
- // Until we have `deleteAllPosts`, the number of posts being deleted could be dynamic.
- expect(message).toMatch(/\d+ posts? permanently deleted\./);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect( page.locator( '#message' ) ).toContainText( '1 post permanently deleted.' );
+ } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it("Restore trash post", async () => {
- await createPost(POST_TITLE);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test('Restore trash post', async ( { admin, editor, page }) => {
+ await admin.createNewPost( { title: POST_TITLE } );
+ await editor.publishPost();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await visitAdminPage("/edit.php");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await admin.visitAdminPage( '/edit.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Move one post to trash.
- await page.hover(`[aria-label^="“${POST_TITLE}”"]`);
- await page.click(`[aria-label='Move “${POST_TITLE}” to the Trash']`);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const listTable = page.getByRole( 'table', { name: 'Table ordered by' } );
+ await expect( listTable ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Remove post from trash.
- const trashTab = await page.waitForXPath('//h2[text()="Filter posts list"]/following-sibling::ul//a[contains(text(), "Trash")]');
- await Promise.all([
- trashTab.click(),
- page.waitForNavigation(),
- ]);
- const [postTitle] = await page.$x(`//*[text()="${POST_TITLE}"]`);
- await postTitle.hover();
- await page.click(`[aria-label="Restore “${POST_TITLE}” from the Trash"]`);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Move post to trash
+ await listTable.getByRole( 'link', { name: `“${ POST_TITLE }” (Edit)` } ).hover();
+ await listTable.getByRole( 'link', { name: `Move “${POST_TITLE}” to the Trash` } ).click();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // Expect for success message for trashed post.
- const messageElement = await page.waitForSelector("#message");
- const message = await messageElement.evaluate((element) => element.innerText);
- expect(message).toContain("1 post restored from the Trash.");
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await page.getByRole( 'link', { name: 'Trash' } ).click();
+
+ // Remove post from trash.
+ await listTable.getByRole( 'cell' ).filter( { hasText: POST_TITLE } ).hover();
+ await listTable.getByRole( 'link', { name: `Restore “${POST_TITLE}” from the Trash` } ).click();
+
+ // Expect for success message for restored post.
+ await expect( page.locator( '#message' ) ).toContainText( '1 post restored from the Trash.' );
+ } );
+} );
</ins></span></pre></div>
<a id="trunktestse2especsgutenbergplugintestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/specs/gutenberg-plugin.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/specs/gutenberg-plugin.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/specs/gutenberg-plugin.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,26 +1,48 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import {
- activatePlugin,
- deactivatePlugin,
- installPlugin,
- uninstallPlugin,
-} from '@wordpress/e2e-test-utils';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+import { test, expect } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe( 'Gutenberg plugin', () => {
- beforeAll( async () => {
- await installPlugin( 'gutenberg' );
- } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Gutenberg plugin', () => {
+ // Increasing timeout to 5 minutes because potential plugin install could take longer.
+ test.setTimeout( 300_000 );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- afterAll( async () => {
- await uninstallPlugin( 'gutenberg' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test.beforeAll( async ( { requestUtils } ) => {
+ // Install Gutenberg plugin if it's not yet installed.
+ const pluginsMap = await requestUtils.getPluginsMap();
+ if ( ! pluginsMap.gutenberg ) {
+ await requestUtils.rest( {
+ method: 'POST',
+ path: 'wp/v2/plugins?slug=gutenberg',
+ } );
+ }
+
+ // Refetch installed plugin details. It avoids stale values when the test installs the plugin.
+ await requestUtils.getPluginsMap( /* forceRefetch */ true );
+ await requestUtils.deactivatePlugin( 'gutenberg' );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'should activate', async () => {
- await activatePlugin( 'gutenberg' );
- /*
- * If plugin activation fails, it will time out and throw an error,
- * since the activatePlugin helper is looking for a `.deactivate` link
- * which is only there if activation succeeds.
- */
- await deactivatePlugin( 'gutenberg' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'should activate', async ( { requestUtils }) => {
+ let plugin = await requestUtils.rest( {
+ path: 'wp/v2/plugins/gutenberg/gutenberg',
+ } );
+
+ expect( plugin.status ).toBe( 'inactive' );
+
+ await requestUtils.activatePlugin( 'gutenberg' );
+
+ plugin = await requestUtils.rest( {
+ path: 'wp/v2/plugins/gutenberg/gutenberg',
+ } );
+
+ expect( plugin.status ).toBe( 'active' );
+
+ await requestUtils.deactivatePlugin( 'gutenberg' );
+
+ plugin = await requestUtils.rest( {
+ path: 'wp/v2/plugins/gutenberg/gutenberg',
+ } );
+
+ expect( plugin.status ).toBe( 'inactive' );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre></div>
<a id="trunktestse2especshellotestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/specs/hello.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/specs/hello.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/specs/hello.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,11 +1,13 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { visitAdminPage } from '@wordpress/e2e-test-utils';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+import { test, expect } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe( 'Hello World', () => {
- it( 'Should load properly', async () => {
- await visitAdminPage( '/' );
- const nodes = await page.$x(
- '//h2[contains(text(), "Welcome to WordPress!")]'
- );
- expect( nodes.length ).not.toEqual( 0 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Hello World', () => {
+ test( 'Should load properly', async ( { admin, page }) => {
+ await admin.visitAdminPage( '/' );
+ await expect(
+ page.getByRole('heading', { name: 'Welcome to WordPress', level: 2 })
+ ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre></div>
<a id="trunktestse2especsprofileapplicationspasswordstestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/specs/profile/applications-passwords.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/specs/profile/applications-passwords.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/e2e/specs/profile/applications-passwords.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,138 +1,133 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import {
- visitAdminPage,
- __experimentalRest as rest,
-} from "@wordpress/e2e-test-utils";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+import { test, expect } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-async function getResponseForApplicationPassword() {
- return await rest({
- method: "GET",
- path: "/wp/v2/users/me/application-passwords",
- });
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const TEST_APPLICATION_NAME = 'Test Application';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-async function createApplicationPassword(applicationName) {
- await visitAdminPage("profile.php");
- await page.waitForSelector("#new_application_password_name");
- await page.type("#new_application_password_name", applicationName);
- await page.click("#do_new_application_password");
-
- await page.waitForSelector("#application-passwords-section .notice");
-}
-
-async function createApplicationPasswordWithApi(applicationName) {
- await rest({
- method: "POST",
- path: "/wp/v2/users/me/application-passwords",
- data: {
- name: applicationName,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Manage applications passwords', () => {
+ test.use( {
+ applicationPasswords: async ( { requestUtils, admin, page }, use ) => {
+ await use( new ApplicationPasswords( { requestUtils, admin, page } ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- });
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-async function revokeAllApplicationPasswordsWithApi() {
- await rest({
- method: "DELETE",
- path: `/wp/v2/users/me/application-passwords`,
- });
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test.beforeEach(async ( { applicationPasswords } ) => {
+ await applicationPasswords.delete();
+ } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe("Manage applications passwords", () => {
- const TEST_APPLICATION_NAME = "Test Application";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test('should correctly create a new application password', async ( {
+ page,
+ applicationPasswords
+ } ) => {
+ await applicationPasswords.create();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- beforeEach(async () => {
- await revokeAllApplicationPasswordsWithApi();
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const [ app ] = await applicationPasswords.get();
+ expect( app['name']).toBe( TEST_APPLICATION_NAME );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it("should correctly create a new application password", async () => {
- await createApplicationPassword(TEST_APPLICATION_NAME);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const successMessage = page.getByRole( 'alert' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const response = await getResponseForApplicationPassword();
- expect(response[0]["name"]).toBe(TEST_APPLICATION_NAME);
-
- const successMessage = await page.waitForSelector(
- "#application-passwords-section .notice-success"
- );
- expect(
- await successMessage.evaluate((element) => element.innerText)
- ).toContain(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect( successMessage ).toHaveClass( /notice-success/ );
+ await expect(
+ successMessage
+ ).toContainText(
</ins><span class="cx" style="display: block; padding: 0 10px"> `Your new password for ${TEST_APPLICATION_NAME} is: \n\nBe sure to save this in a safe location. You will not be able to retrieve it.`
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it("should not allow to create two applications passwords with the same name", async () => {
- await createApplicationPassword(TEST_APPLICATION_NAME);
- await createApplicationPassword(TEST_APPLICATION_NAME);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test('should not allow to create two applications passwords with the same name', async ( {
+ page,
+ applicationPasswords
+ } ) => {
+ await applicationPasswords.create();
+ await applicationPasswords.create();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const errorMessage = await page.waitForSelector(
- "#application-passwords-section .notice-error"
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const errorMessage = page.getByRole( 'alert' );
+
+ await expect( errorMessage ).toHaveClass( /notice-error/ );
+ await expect(
+ errorMessage
+ ).toContainText(
+ 'Each application name should be unique.'
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
- expect(
- await errorMessage.evaluate((element) => element.textContent)
- ).toContain("Each application name should be unique.");
</del><span class="cx" style="display: block; padding: 0 10px"> });
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it("should correctly revoke a single application password", async () => {
- await createApplicationPassword(TEST_APPLICATION_NAME);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'should correctly revoke a single application password', async ( {
+ page,
+ applicationPasswords
+ } ) => {
+ await applicationPasswords.create();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const revokeApplicationButton = await page.waitForSelector(
- ".application-passwords-user tr button.delete"
- );
-
- const revocationDialogPromise = new Promise((resolve) => {
- page.once("dialog", resolve);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const revokeButton = page.getByRole( 'button', { name: `Revoke "${ TEST_APPLICATION_NAME }"` } );
+ await expect( revokeButton ).toBeVisible();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await Promise.all([
- revocationDialogPromise,
- revokeApplicationButton.click(),
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Revoke password.
+ page.on( 'dialog', ( dialog ) => dialog.accept() );
+ await revokeButton.click();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const successMessage = await page.waitForSelector(
- "#application-passwords-section .notice-success"
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await expect(
+ page.getByRole( 'alert' )
+ ).toContainText(
+ 'Application password revoked.'
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- expect(
- await successMessage.evaluate((element) => element.textContent)
- ).toContain("Application password revoked.");
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const response = await getResponseForApplicationPassword();
- expect(response).toEqual([]);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const response = await applicationPasswords.get();
+ expect( response ).toEqual([]);
+ } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it("should correctly revoke all the application passwords", async () => {
- await createApplicationPassword(TEST_APPLICATION_NAME);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'should correctly revoke all the application passwords', async ( {
+ page,
+ applicationPasswords
+ } ) => {
+ await applicationPasswords.create();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const revokeAllApplicationPasswordsButton = await page.waitForSelector(
- "#revoke-all-application-passwords"
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const revokeAllButton = page.getByRole( 'button', { name: 'Revoke all application passwords' } );
+ await expect( revokeAllButton ).toBeVisible();
+
+ // Confirms revoking action.
+ page.on( 'dialog', ( dialog ) => dialog.accept() );
+ await revokeAllButton.click();
+
+ await expect(
+ page.getByRole( 'alert' )
+ ).toContainText(
+ 'All application passwords revoked.'
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const revocationDialogPromise = new Promise((resolve) => {
- page.once("dialog", resolve);
- });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const response = await applicationPasswords.get();
+ expect( response ).toEqual([]);
+ } );
+} );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await Promise.all([
- revocationDialogPromise,
- revokeAllApplicationPasswordsButton.click(),
- ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+class ApplicationPasswords {
+ constructor( { requestUtils, page, admin }) {
+ this.requestUtils = requestUtils;
+ this.page = page;
+ this.admin = admin;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /**
- * This is commented out because we're using enablePageDialogAccept
- * which is overly aggressive and no way to temporary disable it either.
- */
- // await dialog.accept();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ async create(applicationName = TEST_APPLICATION_NAME) {
+ await this.admin.visitAdminPage( '/profile.php' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- await page.waitForSelector(
- "#application-passwords-section .notice-success"
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const newPasswordField = this.page.getByRole( 'textbox', { name: 'New Application Password Name' } );
+ await expect( newPasswordField ).toBeVisible();
+ await newPasswordField.fill( applicationName );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const successMessage = await page.waitForSelector(
- "#application-passwords-section .notice-success"
- );
- expect(
- await successMessage.evaluate((element) => element.textContent)
- ).toContain("All application passwords revoked.");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ await this.page.getByRole( 'button', { name: 'Add New Application Password' } ).click();
+ await expect( this.page.getByRole( 'alert' ) ).toBeVisible();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const response = await getResponseForApplicationPassword();
- expect(response).toEqual([]);
- });
-});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ async get() {
+ return this.requestUtils.rest( {
+ method: 'GET',
+ path: '/wp/v2/users/me/application-passwords',
+ } );
+ }
+
+ async delete() {
+ await this.requestUtils.rest( {
+ method: 'DELETE',
+ path: '/wp/v2/users/me/application-passwords',
+ } );
+ }
+}
</ins></span></pre></div>
<a id="trunktestsperformancecompareresultsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/performance/compare-results.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/compare-results.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/performance/compare-results.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3,8 +3,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * External dependencies.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const fs = require( 'fs' );
-const path = require( 'path' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const fs = require( 'node:fs' );
+const path = require( 'node:path' );
+
+/**
+ * Internal dependencies
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> const { median } = require( './utils' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -23,18 +27,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // The current commit's results.
</span><span class="cx" style="display: block; padding: 0 10px"> const testResults = Object.fromEntries(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- testSuites.map( ( key ) => [
- key,
- parseFile( `${ key }.test.results.json` ),
- ] )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ testSuites
+ .filter( ( key ) => fs.existsSync( `${ key }.test.results.json` ) )
+ .map( ( key ) => [ key, parseFile( `${ key }.test.results.json` ) ] )
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // The previous commit's results.
</span><span class="cx" style="display: block; padding: 0 10px"> const prevResults = Object.fromEntries(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- testSuites.map( ( key ) => [
- key,
- parseFile( `before-${ key }.test.results.json` ),
- ] )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ testSuites
+ .filter( ( key ) => fs.existsSync( `before-${ key }.test.results.json` ) )
+ .map( ( key ) => [ key, parseFile( `before-${ key }.test.results.json` ) ] )
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> const args = process.argv.slice( 2 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -127,8 +129,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> console.log( 'Note: Due to the nature of how GitHub Actions work, some variance in the results is expected.\n' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> for ( const key of testSuites ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const current = testResults[ key ];
- const prev = prevResults[ key ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const current = testResults[ key ] || {};
+ const prev = prevResults[ key ] || {};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> const title = ( key.charAt( 0 ).toUpperCase() + key.slice( 1 ) ).replace(
</span><span class="cx" style="display: block; padding: 0 10px"> /-+/g,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -152,14 +154,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- summaryMarkdown += `## ${ title }\n\n`;
- summaryMarkdown += `${ formatAsMarkdownTable( rows ) }\n`;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( rows.length > 0 ) {
+ summaryMarkdown += `## ${ title }\n\n`;
+ summaryMarkdown += `${ formatAsMarkdownTable( rows ) }\n`;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- console.log( title );
- console.table( rows );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ console.log( title );
+ console.table( rows );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-fs.writeFileSync(
- summaryFile,
- summaryMarkdown
-);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+if ( summaryFile ) {
+ fs.writeFileSync(
+ summaryFile,
+ summaryMarkdown
+ );
+}
</ins></span></pre></div>
<a id="trunktestsperformanceconfigbootstrapjs"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/performance/config/bootstrap.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/config/bootstrap.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/performance/config/bootstrap.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,41 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * WordPress dependencies.
- */
-import {
- clearLocalStorage,
- enablePageDialogAccept,
- setBrowserViewport,
-} from '@wordpress/e2e-test-utils';
-
-/**
- * Timeout, in seconds, that the test should be allowed to run.
- *
- * @type {string|undefined}
- */
-const PUPPETEER_TIMEOUT = process.env.PUPPETEER_TIMEOUT;
-
-// The Jest timeout is increased because these tests are a bit slow.
-jest.setTimeout( PUPPETEER_TIMEOUT || 100000 );
-
-async function setupBrowser() {
- await clearLocalStorage();
- await setBrowserViewport( 'large' );
-}
-
-/*
- * Before every test suite run, delete all content created by the test. This ensures
- * other posts/comments/etc. aren't dirtying tests and tests don't depend on
- * each other's side-effects.
- */
-beforeAll( async () => {
- enablePageDialogAccept();
-
- await setBrowserViewport( 'large' );
- await page.emulateMediaFeatures( [
- { name: 'prefers-reduced-motion', value: 'reduce' },
- ] );
-} );
-
-afterEach( async () => {
- await setupBrowser();
-} );
</del></span></pre></div>
<a id="trunktestsperformanceconfigglobalsetupjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/performance/config/global-setup.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/config/global-setup.js (rev 0)
+++ trunk/tests/performance/config/global-setup.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,40 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { request } from '@playwright/test';
+
+/**
+ * WordPress dependencies
+ */
+import { RequestUtils } from '@wordpress/e2e-test-utils-playwright';
+
+/**
+ *
+ * @param {import('@playwright/test').FullConfig} config
+ * @returns {Promise<void>}
+ */
+async function globalSetup( config ) {
+ const { storageState, baseURL } = config.projects[ 0 ].use;
+ const storageStatePath =
+ typeof storageState === 'string' ? storageState : undefined;
+
+ const requestContext = await request.newContext( {
+ baseURL,
+ } );
+
+ const requestUtils = new RequestUtils( requestContext, {
+ storageStatePath,
+ } );
+
+ // Authenticate and save the storageState to disk.
+ await requestUtils.setupRest();
+
+ // Reset the test environment before running the tests.
+ await Promise.all( [
+ requestUtils.activateTheme( 'twentytwentyone' ),
+ ] );
+
+ await requestContext.dispose();
+}
+
+export default globalSetup;
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/performance/config/global-setup.js
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsperformanceconfigperformancereporterjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/performance/config/performance-reporter.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/config/performance-reporter.js (rev 0)
+++ trunk/tests/performance/config/performance-reporter.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,38 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { join, dirname, basename } from 'node:path';
+import { writeFileSync } from 'node:fs';
+
+/**
+ * Internal dependencies
+ */
+import { getResultsFilename } from '../utils';
+
+/**
+ * @implements {import('@playwright/test/reporter').Reporter}
+ */
+class PerformanceReporter {
+ /**
+ *
+ * @param {import('@playwright/test/reporter').TestCase} test
+ * @param {import('@playwright/test/reporter').TestResult} result
+ */
+ onTestEnd( test, result ) {
+ const performanceResults = result.attachments.find(
+ ( attachment ) => attachment.name === 'results'
+ );
+
+ if ( performanceResults?.body ) {
+ writeFileSync(
+ join(
+ dirname( test.location.file ),
+ getResultsFilename( basename( test.location.file, '.js' ) )
+ ),
+ performanceResults.body.toString( 'utf-8' )
+ );
+ }
+ }
+}
+
+export default PerformanceReporter;
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/performance/config/performance-reporter.js
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsperformancejestconfigjs"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/performance/jest.config.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/jest.config.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/performance/jest.config.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,14 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const config = require( '@wordpress/scripts/config/jest-e2e.config' );
-
-const jestE2EConfig = {
- ...config,
- setupFilesAfterEnv: [
- '<rootDir>/config/bootstrap.js',
- ],
- globals: {
- // Number of requests to run per test.
- TEST_RUNS: 20,
- }
-};
-
-module.exports = jestE2EConfig;
</del></span></pre></div>
<a id="trunktestsperformanceplaywrightconfigjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/performance/playwright.config.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/playwright.config.js (rev 0)
+++ trunk/tests/performance/playwright.config.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,42 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import path from 'node:path';
+import { defineConfig } from '@playwright/test';
+
+/**
+ * WordPress dependencies
+ */
+import baseConfig from '@wordpress/scripts/config/playwright.config';
+
+process.env.WP_ARTIFACTS_PATH ??= path.join( process.cwd(), 'artifacts' );
+process.env.STORAGE_STATE_PATH ??= path.join(
+ process.env.WP_ARTIFACTS_PATH,
+ 'storage-states/admin.json'
+);
+process.env.TEST_RUNS ??= '20';
+
+const config = defineConfig( {
+ ...baseConfig,
+ globalSetup: require.resolve( './config/global-setup.js' ),
+ reporter: process.env.CI
+ ? './config/performance-reporter.js'
+ : [ [ 'list' ], [ './config/performance-reporter.js' ] ],
+ forbidOnly: !! process.env.CI,
+ workers: 1,
+ retries: 0,
+ timeout: parseInt( process.env.TIMEOUT || '', 10 ) || 600_000, // Defaults to 10 minutes.
+ // Don't report slow test "files", as we will be running our tests in serial.
+ reportSlowTests: null,
+ webServer: {
+ ...baseConfig.webServer,
+ command: 'npm run env:start',
+ },
+ use: {
+ ...baseConfig.use,
+ video: 'off',
+ },
+} );
+
+export default config;
+
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/performance/playwright.config.js
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsperformanceresultsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/performance/results.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/results.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/performance/results.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3,8 +3,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * External dependencies.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const fs = require( 'fs' );
-const { join } = require( 'path' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const fs = require( 'node:fs' );
+const { join } = require( 'node:path' );
</ins><span class="cx" style="display: block; padding: 0 10px"> const { median, getResultsFilename } = require( './utils' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> const testSuites = [
</span></span></pre></div>
<a id="trunktestsperformanceruntestsjs"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/performance/run-tests.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/run-tests.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/performance/run-tests.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,16 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * External dependencies.
- */
-const dotenv = require( 'dotenv' );
-const dotenv_expand = require( 'dotenv-expand' );
-const { execSync } = require( 'child_process' );
-
-// WP_BASE_URL interpolates LOCAL_PORT, so needs to be parsed by dotenv_expand().
-dotenv_expand.expand( dotenv.config() );
-
-// Run the tests, passing additional arguments through to the test script.
-execSync(
- 'wp-scripts test-e2e --config tests/performance/jest.config.js ' +
- process.argv.slice( 2 ).join( ' ' ),
- { stdio: 'inherit' }
-);
</del></span></pre></div>
<a id="trunktestsperformancespecshomeblockthemetestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/performance/specs/home-block-theme.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/specs/home-block-theme.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/performance/specs/home-block-theme.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,67 +1,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * External dependencies.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * WordPress dependencies
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const { basename, join } = require( 'path' );
-const { writeFileSync } = require( 'fs' );
-const {
- getResultsFilename,
- getTimeToFirstByte,
- getLargestContentfulPaint,
-} = require( './../utils' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { test } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * WordPress dependencies.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Internal dependencies
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { activateTheme, createURL } from '@wordpress/e2e-test-utils';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { camelCaseDashes } from '../utils';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe( 'Server Timing - Twenty Twenty Three', () => {
- const results = {
- wpBeforeTemplate: [],
- wpTemplate: [],
- wpTotal: [],
- timeToFirstByte: [],
- largestContentfulPaint: [],
- lcpMinusTtfb: [],
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const results = {
+ timeToFirstByte: [],
+ largestContentfulPaint: [],
+ lcpMinusTtfb: [],
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- beforeAll( async () => {
- await activateTheme( 'twentytwentythree' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Front End - Twenty Twenty Three', () => {
+ test.use( {
+ storageState: {}, // User will be logged out.
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- afterAll( async () => {
- const resultsFilename = getResultsFilename(
- basename( __filename, '.js' )
- );
- writeFileSync(
- join( __dirname, resultsFilename ),
- JSON.stringify( results, null, 2 )
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test.beforeAll( async ( { requestUtils } ) => {
+ await requestUtils.activateTheme( 'twentytwentythree' );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Server Timing Metrics', async () => {
- let i = TEST_RUNS;
- while ( i-- ) {
- await page.goto( createURL( '/' ) );
- const navigationTimingJson = await page.evaluate( () =>
- JSON.stringify( performance.getEntriesByType( 'navigation' ) )
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test.afterAll( async ( { requestUtils }, testInfo ) => {
+ await testInfo.attach( 'results', {
+ body: JSON.stringify( results, null, 2 ),
+ contentType: 'application/json',
+ } );
+ await requestUtils.activateTheme( 'twentytwentyone' );
+ } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const [ navigationTiming ] = JSON.parse( navigationTimingJson );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const iterations = Number( process.env.TEST_RUNS );
+ for ( let i = 1; i <= iterations; i++ ) {
+ test( `Measure load time metrics (${ i } of ${ iterations })`, async ( {
+ page,
+ metrics,
+ } ) => {
+ await page.goto( '/' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- results.wpBeforeTemplate.push(
- navigationTiming.serverTiming[ 0 ].duration
- );
- results.wpTemplate.push(
- navigationTiming.serverTiming[ 1 ].duration
- );
- results.wpTotal.push( navigationTiming.serverTiming[ 2 ].duration );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const serverTiming = await metrics.getServerTiming();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const ttfb = await getTimeToFirstByte();
- const lcp = await getLargestContentfulPaint();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for ( const [key, value] of Object.entries( serverTiming ) ) {
+ results[ camelCaseDashes( key ) ] ??= [];
+ results[ camelCaseDashes( key ) ].push( value );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const ttfb = await metrics.getTimeToFirstByte();
+ const lcp = await metrics.getLargestContentfulPaint();
+
+ results.largestContentfulPaint.push( lcp );
</ins><span class="cx" style="display: block; padding: 0 10px"> results.timeToFirstByte.push( ttfb );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- results.largestContentfulPaint.push( lcp );
</del><span class="cx" style="display: block; padding: 0 10px"> results.lcpMinusTtfb.push( lcp - ttfb );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- }
- } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre></div>
<a id="trunktestsperformancespecshomeclassicthemetestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/performance/specs/home-classic-theme.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/specs/home-classic-theme.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/performance/specs/home-classic-theme.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,71 +1,56 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * External dependencies.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * WordPress dependencies
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const { basename, join } = require( 'path' );
-const { writeFileSync } = require( 'fs' );
-const { exec } = require( 'child_process' );
-const {
- getResultsFilename,
- getTimeToFirstByte,
- getLargestContentfulPaint,
-} = require( './../utils' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { test } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * WordPress dependencies.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Internal dependencies
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { activateTheme, createURL } from '@wordpress/e2e-test-utils';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { camelCaseDashes } from '../utils';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-describe( 'Server Timing - Twenty Twenty One', () => {
- const results = {
- wpBeforeTemplate: [],
- wpTemplate: [],
- wpTotal: [],
- timeToFirstByte: [],
- largestContentfulPaint: [],
- lcpMinusTtfb: [],
- };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const results = {
+ timeToFirstByte: [],
+ largestContentfulPaint: [],
+ lcpMinusTtfb: [],
+};
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- beforeAll( async () => {
- await activateTheme( 'twentytwentyone' );
- await exec(
- 'npm run env:cli -- menu location assign all-pages primary'
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Front End - Twenty Twenty One', () => {
+ test.use( {
+ storageState: {}, // User will be logged out.
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- afterAll( async () => {
- const resultsFilename = getResultsFilename(
- basename( __filename, '.js' )
- );
- writeFileSync(
- join( __dirname, resultsFilename ),
- JSON.stringify( results, null, 2 )
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test.beforeAll( async ( { requestUtils } ) => {
+ await requestUtils.activateTheme( 'twentytwentyone' );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Server Timing Metrics', async () => {
- let i = TEST_RUNS;
- while ( i-- ) {
- await page.goto( createURL( '/' ) );
- const navigationTimingJson = await page.evaluate( () =>
- JSON.stringify( performance.getEntriesByType( 'navigation' ) )
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test.afterAll( async ( {}, testInfo ) => {
+ await testInfo.attach( 'results', {
+ body: JSON.stringify( results, null, 2 ),
+ contentType: 'application/json',
+ } );
+ } );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const [ navigationTiming ] = JSON.parse( navigationTimingJson );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const iterations = Number( process.env.TEST_RUNS );
+ for ( let i = 1; i <= iterations; i++ ) {
+ test( `Measure load time metrics (${ i } of ${ iterations })`, async ( {
+ page,
+ metrics,
+ } ) => {
+ await page.goto( '/' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- results.wpBeforeTemplate.push(
- navigationTiming.serverTiming[ 0 ].duration
- );
- results.wpTemplate.push(
- navigationTiming.serverTiming[ 1 ].duration
- );
- results.wpTotal.push( navigationTiming.serverTiming[ 2 ].duration );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const serverTiming = await metrics.getServerTiming();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const ttfb = await getTimeToFirstByte();
- const lcp = await getLargestContentfulPaint();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for (const [key, value] of Object.entries( serverTiming ) ) {
+ results[ camelCaseDashes( key ) ] ??= [];
+ results[ camelCaseDashes( key ) ].push( value );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const ttfb = await metrics.getTimeToFirstByte();
+ const lcp = await metrics.getLargestContentfulPaint();
+
+ results.largestContentfulPaint.push( lcp );
</ins><span class="cx" style="display: block; padding: 0 10px"> results.timeToFirstByte.push( ttfb );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- results.largestContentfulPaint.push( lcp );
</del><span class="cx" style="display: block; padding: 0 10px"> results.lcpMinusTtfb.push( lcp - ttfb );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- }
- } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre></div>
<a id="trunktestsperformanceutilsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/performance/utils.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/performance/utils.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/performance/utils.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16,63 +16,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Gets the result file name.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param {string} File name.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param {string} fileName File name.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @return {string} Result file name.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> function getResultsFilename( fileName ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const prefixArg = process.argv.find( ( arg ) =>
- arg.startsWith( '--prefix' )
- );
- const fileNamePrefix = prefixArg ? `${ prefixArg.split( '=' )[ 1 ] }-` : '';
- const resultsFilename = fileNamePrefix + fileName + '.results.json';
- return resultsFilename;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const prefix = process.env.TEST_RESULTS_PREFIX;
+ const fileNamePrefix = prefix ? `${ prefix.split( '=' )[ 1 ] }-` : '';
+ return `${fileNamePrefix + fileName}.results.json`;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Returns time to first byte (TTFB) using the Navigation Timing API.
- *
- * @see https://web.dev/ttfb/#measure-ttfb-in-javascript
- *
- * @return {Promise<number>}
- */
-async function getTimeToFirstByte() {
- return page.evaluate( () => {
- const { responseStart, startTime } =
- performance.getEntriesByType( 'navigation' )[ 0 ];
- return responseStart - startTime;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function camelCaseDashes( str ) {
+ return str.replace( /-([a-z])/g, function( g ) {
+ return g[ 1 ].toUpperCase();
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Returns the Largest Contentful Paint (LCP) value using the dedicated API.
- *
- * @see https://w3c.github.io/largest-contentful-paint/
- * @see https://web.dev/lcp/#measure-lcp-in-javascript
- *
- * @return {Promise<number>}
- */
-async function getLargestContentfulPaint() {
- return page.evaluate(
- () =>
- new Promise( ( resolve ) => {
- new PerformanceObserver( ( entryList ) => {
- const entries = entryList.getEntries();
- // The last entry is the largest contentful paint.
- const largestPaintEntry = entries.at( -1 );
-
- resolve( largestPaintEntry?.startTime || 0 );
- } ).observe( {
- type: 'largest-contentful-paint',
- buffered: true,
- } );
- } )
- );
-}
-
</del><span class="cx" style="display: block; padding: 0 10px"> module.exports = {
</span><span class="cx" style="display: block; padding: 0 10px"> median,
</span><span class="cx" style="display: block; padding: 0 10px"> getResultsFilename,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- getTimeToFirstByte,
- getLargestContentfulPaint,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ camelCaseDashes,
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span></span></pre></div>
<a id="trunktestsvisualregressionREADMEmd"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/visual-regression/README.md</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/visual-regression/README.md 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/visual-regression/README.md 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,6 +1,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> # Visual Regression Tests in WordPress Core
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-These tests make use of Jest and Puppeteer, with a setup very similar to that of the e2e tests, together with [jest-image-snapshot](https://github.com/americanexpress/jest-image-snapshot) for generating the visual diffs.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+These tests make use of Playwright, with a setup very similar to that of the e2e tests.
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> ## How to Run the Tests Locally
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7,5 +7,5 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 1. Check out trunk.
</span><span class="cx" style="display: block; padding: 0 10px"> 2. Run `npm run test:visual` to generate some base snapshots.
</span><span class="cx" style="display: block; padding: 0 10px"> 3. Check out the feature branch to be tested.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-4. Run `npm run test:visual` again. If any tests fail, the diff images can be found in `tests/visual-regression/specs/__image_snapshots__/__diff_output__`.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+4. Run `npm run test:visual` again. If any tests fail, the diff images can be found in `artifacts/`
</ins><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunktestsvisualregressionjestconfigjs"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/visual-regression/jest.config.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/visual-regression/jest.config.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/visual-regression/jest.config.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,8 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const config = require( '@wordpress/scripts/config/jest-e2e.config' );
-
-const jestVisualRegressionConfig = {
- ...config,
- setupFilesAfterEnv: [ '<rootDir>/config/bootstrap.js' ],
-};
-
-module.exports = jestVisualRegressionConfig;
</del></span></pre></div>
<a id="trunktestsvisualregressionplaywrightconfigjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/visual-regression/playwright.config.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/visual-regression/playwright.config.js (rev 0)
+++ trunk/tests/visual-regression/playwright.config.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,27 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import path from 'node:path';
+import { defineConfig } from '@playwright/test';
+
+/**
+ * WordPress dependencies
+ */
+const baseConfig = require( '@wordpress/scripts/config/playwright.config' );
+
+process.env.WP_ARTIFACTS_PATH ??= path.join( process.cwd(), 'artifacts' );
+process.env.STORAGE_STATE_PATH ??= path.join(
+ process.env.WP_ARTIFACTS_PATH,
+ 'storage-states/admin.json'
+);
+
+const config = defineConfig( {
+ ...baseConfig,
+ globalSetup: undefined,
+ webServer: {
+ ...baseConfig.webServer,
+ command: 'npm run env:start',
+ },
+} );
+
+export default config;
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/tests/visual-regression/playwright.config.js
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunktestsvisualregressionruntestsjs"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tests/visual-regression/run-tests.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/visual-regression/run-tests.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/visual-regression/run-tests.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,13 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-const dotenv = require( 'dotenv' );
-const dotenv_expand = require( 'dotenv-expand' );
-const { execSync } = require( 'child_process' );
-
-// WP_BASE_URL interpolates LOCAL_PORT, so needs to be parsed by dotenv_expand().
-dotenv_expand.expand( dotenv.config() );
-
-// Run the tests, passing additional arguments through to the test script.
-execSync(
- 'wp-scripts test-e2e --config tests/visual-regression/jest.config.js ' +
- process.argv.slice( 2 ).join( ' ' ),
- { stdio: 'inherit' }
-);
</del><span class="cx" style="display: block; padding: 0 10px">Index: trunk/tests/visual-regression/specs
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk/tests/visual-regression/specs 2023-10-12 23:39:05 UTC (rev 56925)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk/tests/visual-regression/specs 2023-10-13 08:11:41 UTC (rev 56926)
</ins></span></pre></div>
<a id="trunktestsvisualregressionspecs"></a>
<div class="propset"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Property changes: trunk/tests/visual-regression/specs</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnignore"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: svn:ignore</h4></div>
<del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-__image_snapshots__
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+__snapshots__
</ins><a id="trunktestsvisualregressionspecsvisualsnapshotstestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/visual-regression/specs/visual-snapshots.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/visual-regression/specs/visual-snapshots.test.js 2023-10-12 23:39:05 UTC (rev 56925)
+++ trunk/tests/visual-regression/specs/visual-snapshots.test.js 2023-10-13 08:11:41 UTC (rev 56926)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,222 +1,166 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-import { visitAdminPage } from '@wordpress/e2e-test-utils';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import { test, expect } from '@wordpress/e2e-test-utils-playwright';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagescreenshotoptions for more available options.
-const screenshotOptions = {
- fullPage: true,
-};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const elementsToHide = [
+ '#footer-upgrade',
+ '#wp-admin-bar-root-default',
+ '#toplevel_page_gutenberg'
+];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-async function hideElementVisibility( elements ) {
- for ( let i = 0; i < elements.length; i++ ) {
- const elementOnPage = await page.$( elements[ i ] );
- if ( elementOnPage ) {
- await elementOnPage.evaluate( ( el ) => {
- el.style.visibility = 'hidden';
- } );
- }
- }
- await page.waitFor( 1000 );
-}
-
-async function removeElementFromLayout( elements ) {
- for ( let i = 0; i < elements.length; i++ ) {
- const elementOnPage = await page.$( elements[ i ] );
- if ( elementOnPage ) {
- await elementOnPage.evaluate( ( el ) => {
- el.style.visibility = 'hidden';
- } );
- }
- }
- await page.waitFor( 1000 );
-}
-
-const elementsToHide = [ '#footer-upgrade', '#wp-admin-bar-root-default' ];
-
-const elementsToRemove = [ '#toplevel_page_gutenberg' ];
-
-describe( 'Admin Visual Snapshots', () => {
- beforeAll( async () => {
- await page.setViewport( {
- width: 1000,
- height: 750,
- } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+test.describe( 'Admin Visual Snapshots', () => {
+ test( 'All Posts', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/edit.php' );
+ await expect( page ).toHaveScreenshot( 'All Posts.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'All Posts', async () => {
- await visitAdminPage( '/edit.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Categories', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/edit-tags.php', 'taxonomy=category' );
+ await expect( page ).toHaveScreenshot( 'Categories.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Categories', async () => {
- await visitAdminPage( '/edit-tags.php', 'taxonomy=category' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Tags', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/edit-tags.php', 'taxonomy=post_tag' );
+ await expect( page ).toHaveScreenshot( 'Tags.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Tags', async () => {
- await visitAdminPage( '/edit-tags.php', 'taxonomy=post_tag' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Media Library', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/upload.php' );
+ await expect( page ).toHaveScreenshot( 'Media Library.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Media Library', async () => {
- await visitAdminPage( '/upload.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Add New Media', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/media-new.php' );
+ await expect( page ).toHaveScreenshot( 'Add New Media.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Add New Media', async () => {
- await visitAdminPage( '/media-new.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'All Pages', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/edit.php', 'post_type=page' );
+ await expect( page ).toHaveScreenshot( 'All Pages.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'All Pages', async () => {
- await visitAdminPage( '/edit.php', 'post_type=page' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Comments', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/edit-comments.php' );
+ await expect( page ).toHaveScreenshot( 'Comments.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Comments', async () => {
- await visitAdminPage( '/edit-comments.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Widgets', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/widgets.php' );
+ await expect( page ).toHaveScreenshot( 'Widgets.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Widgets', async () => {
- await visitAdminPage( '/widgets.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Menus', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/nav-menus.php' );
+ await expect( page ).toHaveScreenshot( 'Menus.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Menus', async () => {
- await visitAdminPage( '/nav-menus.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Plugins', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/plugins.php' );
+ await expect( page ).toHaveScreenshot( 'Plugins.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Plugins', async () => {
- await visitAdminPage( '/plugins.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'All Users', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/users.php' );
+ await expect( page ).toHaveScreenshot( 'All Users.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'All Users', async () => {
- await visitAdminPage( '/users.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Add New User', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/user-new.php' );
+ await expect( page ).toHaveScreenshot( 'Add New User.png', {
+ mask: [
+ ...elementsToHide,
+ '.password-input-wrapper'
+ ].map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Add New User', async () => {
- await visitAdminPage( '/user-new.php' );
- await hideElementVisibility( [
- ...elementsToHide,
- '.password-input-wrapper',
- ] );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Your Profile', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/profile.php' );
+ await expect( page ).toHaveScreenshot( 'Your Profile.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Your Profile', async () => {
- await visitAdminPage( '/profile.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Available Tools', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/tools.php' );
+ await expect( page ).toHaveScreenshot( 'Available Tools.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Available Tools', async () => {
- await visitAdminPage( '/tools.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Import', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/import.php' );
+ await expect( page ).toHaveScreenshot( 'Import.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Import', async () => {
- await visitAdminPage( '/import.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Export', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/export.php' );
+ await expect( page ).toHaveScreenshot( 'Export.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Export', async () => {
- await visitAdminPage( '/export.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Export Personal Data', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/export-personal-data.php' );
+ await expect( page ).toHaveScreenshot( 'Export Personal Data.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Export Personal Data', async () => {
- await visitAdminPage( '/export-personal-data.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Erase Personal Data', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/erase-personal-data.php' );
+ await expect( page ).toHaveScreenshot( 'Erase Personal Data.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Erase Personal Data', async () => {
- await visitAdminPage( '/erase-personal-data.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Reading Settings', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/options-reading.php' );
+ await expect( page ).toHaveScreenshot( 'Reading Settings.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Reading Settings', async () => {
- await visitAdminPage( '/options-reading.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Discussion Settings', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/options-discussion.php' );
+ await expect( page ).toHaveScreenshot( 'Discussion Settings.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Discussion Settings', async () => {
- await visitAdminPage( '/options-discussion.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Media Settings', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/options-media.php' );
+ await expect( page ).toHaveScreenshot( 'Media Settings.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- it( 'Media Settings', async () => {
- await visitAdminPage( '/options-media.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test( 'Privacy Settings', async ({ admin, page }) => {
+ await admin.visitAdminPage( '/options-privacy.php' );
+ await expect( page ).toHaveScreenshot( 'Privacy Settings.png', {
+ mask: elementsToHide.map( ( selector ) => page.locator( selector ) ),
+ });
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
- it( 'Privacy Settings', async () => {
- await visitAdminPage( '/options-privacy.php' );
- await hideElementVisibility( elementsToHide );
- await removeElementFromLayout( elementsToRemove );
- const image = await page.screenshot( screenshotOptions );
- expect( image ).toMatchImageSnapshot();
- } );
</del><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre>
</div>
</div>
</body>
</html>