Skip to content

Commit 5aa5925

Browse files
committed
Refine Your Playgrounds overlay for autosaves
1 parent 570e4f7 commit 5aa5925

14 files changed

Lines changed: 1161 additions & 291 deletions

File tree

packages/playground/website/playwright/e2e/blueprints.spec.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,13 @@ test('?blueprint-url=... should work with simple blueprints', async ({
114114
browserName === 'webkit',
115115
'This test is flaky in WebKit. It seems like a GitHub CI issue rather than an actual flakiness since it is reliable locally.'
116116
);
117-
await website.goto('/');
118-
const websiteUrl = page.url();
119-
const blueprintUrl = encodeURIComponent(
120-
`${websiteUrl}test-fixtures/blueprint/blueprint-simple.json`
117+
await website.goto('./?storage=temp');
118+
const websiteUrl = new URL(
119+
'test-fixtures/blueprint/blueprint-simple.json',
120+
page.url()
121121
);
122-
await website.goto(`/?blueprint-url=${blueprintUrl}`);
122+
const blueprintUrl = encodeURIComponent(websiteUrl.href);
123+
await website.goto(`./?storage=temp&blueprint-url=${blueprintUrl}`);
123124
await expect(wordpress.locator('body')).toContainText(
124125
'PREFACE TO PYGMALION'
125126
);
@@ -130,11 +131,11 @@ test('?blueprint-url=... should accept data URLs', async ({
130131
website,
131132
wordpress,
132133
}) => {
133-
await website.goto('/');
134+
await website.goto('./?storage=temp');
134135
const blueprintUrl = encodeURIComponent(
135136
`data:application/json;base64,eyJsYW5kaW5nUGFnZSI6Ii9weWdtYWxpb24udHh0Iiwic3RlcHMiOlt7InN0ZXAiOiJ3cml0ZUZpbGUiLCJwYXRoIjoiL3dvcmRwcmVzcy9weWdtYWxpb24udHh0IiwiZGF0YSI6IlBSRUZBQ0UgVE8gUFlHTUFMSU9OIn1dfQ==`
136137
);
137-
await website.goto(`/?blueprint-url=${blueprintUrl}`);
138+
await website.goto(`./?storage=temp&blueprint-url=${blueprintUrl}`);
138139
await expect(wordpress.locator('body')).toContainText(
139140
'PREFACE TO PYGMALION'
140141
);
@@ -145,12 +146,13 @@ test('?blueprint-url=... should work with ZIP bundles', async ({
145146
website,
146147
wordpress,
147148
}) => {
148-
await website.goto('/');
149-
const websiteUrl = page.url();
150-
const blueprintUrl = encodeURIComponent(
151-
`${websiteUrl}test-fixtures/blueprint/blueprint.zip`
149+
await website.goto('./?storage=temp');
150+
const websiteUrl = new URL(
151+
'test-fixtures/blueprint/blueprint.zip',
152+
page.url()
152153
);
153-
await website.goto(`/?blueprint-url=${blueprintUrl}`);
154+
const blueprintUrl = encodeURIComponent(websiteUrl.href);
155+
await website.goto(`./?storage=temp&blueprint-url=${blueprintUrl}`);
154156
await expect(wordpress.locator('body')).toContainText(
155157
'PREFACE TO PYGMALION'
156158
);
@@ -161,12 +163,13 @@ test('?blueprint-url=... should work with JSON blueprints referring bundled reso
161163
website,
162164
wordpress,
163165
}) => {
164-
await website.goto('/');
165-
const websiteUrl = page.url();
166-
const blueprintUrl = encodeURIComponent(
167-
`${websiteUrl}test-fixtures/blueprint/blueprint-with-bundled-resources.json`
166+
await website.goto('./?storage=temp');
167+
const websiteUrl = new URL(
168+
'test-fixtures/blueprint/blueprint-with-bundled-resources.json',
169+
page.url()
168170
);
169-
await website.goto(`/?blueprint-url=${blueprintUrl}`);
171+
const blueprintUrl = encodeURIComponent(websiteUrl.href);
172+
await website.goto(`./?storage=temp&blueprint-url=${blueprintUrl}`);
170173
await expect(wordpress.locator('body')).toContainText(
171174
'PREFACE TO PYGMALION'
172175
);

packages/playground/website/playwright/e2e/client-side-media.spec.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ test('Post editor should be cross-origin isolated with SharedArrayBuffer availab
6868
website,
6969
wordpress,
7070
}) => {
71-
await website.goto(`./#${JSON.stringify(clientSideMediaBlueprint)}`);
71+
await website.goto(
72+
`./?storage=temp#${JSON.stringify(clientSideMediaBlueprint)}`
73+
);
7274

7375
// Wait for the block editor to fully load. The editor header is visible in both
7476
// fullscreen and non-fullscreen modes.
@@ -96,7 +98,9 @@ test('Gutenberg should report client-side media processing as enabled', async ({
9698
website,
9799
wordpress,
98100
}) => {
99-
await website.goto(`./#${JSON.stringify(clientSideMediaBlueprint)}`);
101+
await website.goto(
102+
`./?storage=temp#${JSON.stringify(clientSideMediaBlueprint)}`
103+
);
100104

101105
await expect(
102106
wordpress.locator('.edit-post-header, .editor-header')

packages/playground/website/playwright/e2e/deployment.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const url = new URL(`http://localhost:${port}`);
1515
// disable auto-login, the old Playground build encounters
1616
// a boot error.
1717
url.searchParams.set('login', 'no');
18+
url.searchParams.set('storage', 'temp');
1819
// Specify the theme so we can assert against expected default content.
1920
// This theme is also what the reference screenshots are based on.
2021
url.searchParams.set('theme', 'twentytwentyfour');

packages/playground/website/playwright/e2e/error-handling.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ test('should show download error modal when a resource download fails', async ({
4444
// fetches the zip from downloads.wordpress.org via the CORS
4545
// proxy, triggering the resource-download-failed error through
4646
// the normal pipeline.
47-
await page.goto('./?plugin=hello-dolly');
47+
await page.goto('./?storage=temp&plugin=hello-dolly');
4848

4949
const title = page.getByText('Could not download required files');
5050
await expect(title).toBeVisible();

packages/playground/website/playwright/e2e/opfs.spec.ts

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ test('should switch between sites', async ({ website, browserName }) => {
9696
await website.ensureSiteManagerIsOpen();
9797

9898
// Save the temporary site using the modal
99-
await saveSiteViaModal(website.page);
99+
const firstSiteName = 'Switching Test Site';
100+
await saveSiteViaModal(website.page, { customName: firstSiteName });
100101

101102
await expect(website.page.getByLabel('Playground title')).not.toContainText(
102103
'Unsaved Playground',
@@ -105,19 +106,46 @@ test('should switch between sites', async ({ website, browserName }) => {
105106
timeout: 90000,
106107
}
107108
);
109+
await expect(website.page.getByLabel('Playground title')).toContainText(
110+
firstSiteName
111+
);
108112

109113
// Open the saved playgrounds overlay to switch sites
110114
await website.openSavedPlaygroundsOverlay();
111115

112-
// Click on Temporary Playground in the overlay's site list
116+
// Start another saved Playground, then switch back to the first one.
117+
await website.page.getByRole('button', { name: 'New Playground' }).click();
118+
await website.waitForNestedIframes();
119+
await website.ensureSiteManagerIsOpen();
120+
121+
await expect(website.page.getByLabel('Playground title')).not.toContainText(
122+
firstSiteName
123+
);
124+
await expect(
125+
website.page.getByText('Autosaved in this browser')
126+
).toBeVisible({ timeout: 120000 });
127+
await expect
128+
.poll(() =>
129+
website.page.evaluate(() => {
130+
const activeSite = (window as any).playgroundSites
131+
.list()
132+
.find((site: any) => site.isActive);
133+
return activeSite
134+
? `${activeSite.storage}:${activeSite.persistence}`
135+
: null;
136+
})
137+
)
138+
.toBe('opfs:autosave');
139+
140+
await website.openSavedPlaygroundsOverlay();
113141
await website.page
114142
.locator('[class*="siteRowContent"]')
115-
.filter({ hasText: 'Unsaved Playground' })
143+
.filter({ hasText: firstSiteName })
116144
.click();
145+
await website.ensureSiteManagerIsOpen();
117146

118-
// The overlay closes and site manager opens with the selected site
119147
await expect(website.page.getByLabel('Playground title')).toContainText(
120-
'Unsaved Playground'
148+
firstSiteName
121149
);
122150
});
123151

@@ -169,11 +197,9 @@ test('should preserve PHP constants when saving a temporary site to OPFS', async
169197
// Open the saved playgrounds overlay to switch sites
170198
await website.openSavedPlaygroundsOverlay();
171199

172-
// Switch to Temporary Playground
173-
await website.page
174-
.locator('[class*="siteRowContent"]')
175-
.filter({ hasText: 'Unsaved Playground' })
176-
.click();
200+
// Create another Playground, then switch back.
201+
await website.page.getByRole('button', { name: 'New Playground' }).click();
202+
await website.waitForNestedIframes();
177203

178204
// Open the overlay again to switch back to the stored site
179205
await website.openSavedPlaygroundsOverlay();
@@ -471,7 +497,7 @@ test('should display OPFS storage option as selected by default', async ({
471497
await dialog.getByRole('button', { name: 'Cancel' }).click();
472498
});
473499

474-
test('should import ZIP into temporary site when a saved site exists', async ({
500+
test('should import ZIP into a new saved site when a saved site exists', async ({
475501
website,
476502
wordpress,
477503
browserName,
@@ -536,12 +562,14 @@ test('should import ZIP into temporary site when a saved site exists', async ({
536562
buffer: zipBuffer,
537563
});
538564

539-
// The import should switch us to a temporary playground.
540-
// Wait for the site title to show "Temporary Playground"
541-
await expect(website.page.getByLabel('Playground title')).toContainText(
542-
'Unsaved Playground',
565+
// The import should switch us to a new saved Playground by default.
566+
await expect(website.page.getByLabel('Playground title')).not.toContainText(
567+
savedSiteName,
543568
{ timeout: 30000 }
544569
);
570+
await expect(website.page.getByLabel('Playground title')).not.toContainText(
571+
'Unsaved Playground'
572+
);
545573

546574
// Now verify the saved site still has the original content.
547575
// Open the saved playgrounds overlay and switch to the saved site
@@ -551,16 +579,17 @@ test('should import ZIP into temporary site when a saved site exists', async ({
551579
.locator('[class*="siteRowContent"]')
552580
.filter({ hasText: savedSiteName })
553581
.click();
582+
await website.ensureSiteManagerIsOpen();
554583

555584
// Wait for the saved site to load - this verifies the saved site wasn't overwritten
556-
// by the ZIP import (which went to a temporary site instead)
585+
// by the ZIP import (which went to a new saved site instead)
557586
await expect(website.page.getByLabel('Playground title')).toContainText(
558587
savedSiteName,
559588
{ timeout: 30000 }
560589
);
561590
});
562591

563-
test('should create temporary site when importing ZIP while on a saved site with no existing temporary site', async ({
592+
test('should create a saved site when importing ZIP while on a saved site with no existing temporary site', async ({
564593
website,
565594
wordpress,
566595
browserName,
@@ -618,14 +647,10 @@ test('should create temporary site when importing ZIP while on a saved site with
618647
// Open the saved playgrounds overlay
619648
await website.openSavedPlaygroundsOverlay();
620649

621-
// Verify there's no "Temporary Playground" in the list initially
622-
// (the temporary site row should show but clicking it would create one)
623-
const tempPlaygroundRow = website.page
624-
.locator('[class*="siteRowContent"]')
625-
.filter({ hasText: 'Unsaved Playground' });
626-
627-
// The row exists but it's for creating a new temporary playground
628-
await expect(tempPlaygroundRow).toBeVisible();
650+
const importZipButton = website.page.getByRole('button', {
651+
name: 'Import a .zip',
652+
});
653+
await expect(importZipButton).toBeVisible();
629654

630655
// Create a test ZIP
631656
const importedMarker = 'FRESH_IMPORT_MARKER_BBBBB';
@@ -648,12 +673,14 @@ test('should create temporary site when importing ZIP while on a saved site with
648673
buffer: zipBuffer,
649674
});
650675

651-
// The import should trigger creation of a new temporary site.
652-
// Wait for the site title to show "Temporary Playground"
653-
await expect(website.page.getByLabel('Playground title')).toContainText(
654-
'Unsaved Playground',
676+
// The import should trigger creation of a new saved site by default.
677+
await expect(website.page.getByLabel('Playground title')).not.toContainText(
678+
savedSiteName,
655679
{ timeout: 30000 }
656680
);
681+
await expect(website.page.getByLabel('Playground title')).not.toContainText(
682+
'Unsaved Playground'
683+
);
657684

658685
// Verify the saved site is still intact by switching to it
659686
await website.openSavedPlaygroundsOverlay();
@@ -662,9 +689,10 @@ test('should create temporary site when importing ZIP while on a saved site with
662689
.locator('[class*="siteRowContent"]')
663690
.filter({ hasText: savedSiteName })
664691
.click();
692+
await website.ensureSiteManagerIsOpen();
665693

666694
// Wait for the saved site to load - this verifies the saved site wasn't overwritten
667-
// by the ZIP import (which went to a temporary site instead)
695+
// by the ZIP import (which went to a new saved site instead)
668696
await expect(website.page.getByLabel('Playground title')).toContainText(
669697
savedSiteName,
670698
{ timeout: 30000 }

packages/playground/website/playwright/e2e/shutdown-loopback-prefetch.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ add_action( 'shutdown', function() {
7272
// Navigate without waiting for nested iframes. We only need the boot
7373
// process to run prefetchUpdateChecks(); we don't need wp-admin to render.
7474
await website.page.goto(
75-
`./?networking=yes&url=/wp-admin/#${JSON.stringify(blueprint)}`
75+
`./?storage=temp&networking=yes&url=/wp-admin/#${JSON.stringify(blueprint)}`
7676
);
7777

7878
// Wait for the playground client to be available (set before prefetch runs).
@@ -114,7 +114,8 @@ echo (string) get_option('${optName}', '');
114114
expect(parsed.kind).toBe('wp_error');
115115
if (parsed.kind === 'wp_error') {
116116
expect(parsed.code).toBe('http_request_block');
117-
expect(parsed.message).toBe('Loopback requests are not to be pre-fetched');
117+
expect(parsed.message).toBe(
118+
'Loopback requests are not to be pre-fetched'
119+
);
118120
}
119121
});
120-

0 commit comments

Comments
 (0)