Skip to content

Commit cf4c7ee

Browse files
authored
Merge pull request #560 from wpengine/previews-e2e-tests
test(previews): Add e2e tests to cover ACF integration
2 parents 3a13e6d + 6147cec commit cf4c7ee

File tree

3 files changed

+265
-20
lines changed

3 files changed

+265
-20
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import { expect, test } from "@wordpress/e2e-test-utils-playwright";
2+
import { HWP_SLUG, TEST_PREVIEW_URL } from "../constants";
3+
import {
4+
createACFPostType,
5+
getSettingsField,
6+
goToPluginPage,
7+
installACF,
8+
resetPluginSettings,
9+
saveChanges,
10+
switchToTab,
11+
uninstallACF,
12+
} from "../utils";
13+
14+
test.describe("HWP Previews ACF Integration Test", () => {
15+
const acfPostTypes = [
16+
{
17+
key: "book",
18+
pluralLabel: "Books",
19+
singularLabel: "Book",
20+
},
21+
];
22+
23+
test.beforeAll(async ({ requestUtils }) => {
24+
await requestUtils.resetPreferences();
25+
});
26+
27+
test.beforeEach(async ({ admin, page, requestUtils }) => {
28+
await resetPluginSettings(admin);
29+
await requestUtils.activatePlugin(HWP_SLUG);
30+
await installACF(admin, page);
31+
});
32+
33+
test.afterEach(async ({ admin, page }) => {
34+
await uninstallACF(admin, page);
35+
});
36+
37+
test("ACF custom post types appear in HWP Previews settings", async ({
38+
page,
39+
admin,
40+
}) => {
41+
// Create custom post types via ACF
42+
for (const postType of acfPostTypes) {
43+
await createACFPostType(admin, page, postType);
44+
}
45+
46+
// Navigate to HWP Previews settings
47+
await goToPluginPage(admin);
48+
49+
// Verify each ACF custom post type appears as a tab in settings
50+
for (const postType of acfPostTypes) {
51+
const tabLink = page
52+
.locator("#wpbody-content")
53+
.getByRole("link", { name: postType.pluralLabel });
54+
55+
await expect(tabLink).toBeVisible();
56+
57+
// Click on the tab to verify settings fields are present
58+
await switchToTab(page, postType.pluralLabel);
59+
60+
// Verify settings fields exist for this custom post type
61+
const enabledCheckbox = getSettingsField(postType.key).enabledCheckbox;
62+
const previewUrlInput = getSettingsField(postType.key).previewUrlInput;
63+
const iframeCheckbox = getSettingsField(postType.key).iframeCheckbox;
64+
65+
await expect(page.locator(enabledCheckbox)).toBeVisible();
66+
await expect(page.locator(previewUrlInput)).toBeVisible();
67+
await expect(page.locator(iframeCheckbox)).toBeVisible();
68+
}
69+
});
70+
71+
test("ACF custom post types use HWP preview logic correctly", async ({
72+
page,
73+
admin,
74+
requestUtils,
75+
}) => {
76+
// Create a custom post type
77+
const testPostType = acfPostTypes[0]; // book
78+
await createACFPostType(admin, page, testPostType);
79+
80+
// Configure HWP Previews for the custom post type
81+
await goToPluginPage(admin);
82+
83+
await switchToTab(page, testPostType.pluralLabel);
84+
await page
85+
.locator(getSettingsField(testPostType.key).enabledCheckbox)
86+
.check();
87+
await page
88+
.locator(getSettingsField(testPostType.key).previewUrlInput)
89+
.fill(TEST_PREVIEW_URL);
90+
await saveChanges(page);
91+
92+
// Create a post of the custom post type using REST API
93+
const customPost = await requestUtils.rest({
94+
method: "POST",
95+
path: `/wp/v2/${testPostType.key}`,
96+
data: {
97+
title: `Test ${testPostType.singularLabel}`,
98+
content: `Test content for ${testPostType.singularLabel}`,
99+
status: "draft",
100+
},
101+
});
102+
103+
// Navigate to the custom post type list
104+
await admin.visitAdminPage(`/edit.php?post_type=${testPostType.key}`);
105+
106+
// Verify preview link uses HWP preview URL
107+
await expect(
108+
page.locator(`#post-${customPost.id} .view a`, {
109+
hasText: "Preview",
110+
exact: true,
111+
})
112+
).toHaveAttribute("href", TEST_PREVIEW_URL);
113+
114+
// Delete the post to not interfere with other tests
115+
await requestUtils.rest({
116+
method: "DELETE",
117+
path: `/wp/v2/${testPostType.key}/${customPost.id}`,
118+
data: {
119+
force: true,
120+
},
121+
});
122+
});
123+
124+
test("ACF custom post types with iframe preview enabled", async ({
125+
page,
126+
admin,
127+
requestUtils,
128+
}) => {
129+
// Create custom post type
130+
const testPostType = acfPostTypes[0]; // book
131+
await createACFPostType(admin, page, testPostType);
132+
133+
await goToPluginPage(admin);
134+
135+
await switchToTab(page, testPostType.pluralLabel);
136+
await page
137+
.locator(getSettingsField(testPostType.key).enabledCheckbox)
138+
.check();
139+
await page
140+
.locator(getSettingsField(testPostType.key).iframeCheckbox)
141+
.check();
142+
await page
143+
.locator(getSettingsField(testPostType.key).previewUrlInput)
144+
.fill(TEST_PREVIEW_URL);
145+
await saveChanges(page);
146+
147+
// Create a post of the custom post type
148+
const customPost = await requestUtils.rest({
149+
method: "POST",
150+
path: `/wp/v2/${testPostType.key}`,
151+
data: {
152+
title: `Test ${testPostType.singularLabel}`,
153+
content: `Test content for ${testPostType.singularLabel}`,
154+
status: "draft",
155+
},
156+
});
157+
158+
// Navigate to the custom post type list and click preview
159+
await admin.visitAdminPage(`/edit.php?post_type=${testPostType.key}`);
160+
const previewLink = page.locator(`#post-${customPost.id} .view a`, {
161+
hasText: "Preview",
162+
exact: true,
163+
});
164+
await previewLink.focus();
165+
await previewLink.click();
166+
await page.waitForLoadState("domcontentloaded");
167+
168+
// Verify iframe is present with correct URL
169+
const iframe = page.locator("iframe.headless-preview-frame");
170+
await expect(iframe).toHaveAttribute("src", TEST_PREVIEW_URL);
171+
172+
// Delete the post to not interfere with other tests
173+
await requestUtils.rest({
174+
method: "DELETE",
175+
path: `/wp/v2/${testPostType.key}/${customPost.id}`,
176+
data: {
177+
force: true,
178+
},
179+
});
180+
});
181+
});

plugins/hwp-previews/tests/e2e/utils.js

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export async function goToPluginPage(admin) {
4242

4343
export async function resetPluginSettings(admin) {
4444
await admin.visitAdminPage(
45-
"/options-general.php?page=hwp-previews&reset=true",
45+
"/options-general.php?page=hwp-previews&reset=true"
4646
);
4747
}
4848

@@ -51,7 +51,7 @@ export async function installFaust(admin, page) {
5151
const activateSelector = '.activate-now[data-slug="faustwp"]';
5252

5353
await admin.visitAdminPage(
54-
"/plugin-install.php?s=faust&tab=search&type=term",
54+
"/plugin-install.php?s=faust&tab=search&type=term"
5555
);
5656

5757
const installButton = page.locator(installSelector);
@@ -72,3 +72,85 @@ export async function uninstallFaust(admin, page) {
7272
await page.locator("a#deactivate-faustwp").click();
7373
await page.locator("a#delete-faustwp").click();
7474
}
75+
76+
export async function installACF(admin, page) {
77+
const installSelector = '.install-now[data-slug="advanced-custom-fields"]';
78+
const activateSelector = '.activate-now[data-slug="advanced-custom-fields"]';
79+
80+
await admin.visitAdminPage(
81+
"/plugin-install.php?s=advanced-custom-fields&tab=search&type=term"
82+
);
83+
84+
const installButton = page.locator(installSelector);
85+
86+
if (await installButton.isVisible()) {
87+
await installButton.click();
88+
await page.waitForSelector(activateSelector, { timeout: 1000 * 90 });
89+
await page.locator(activateSelector).click();
90+
} else {
91+
await page.locator(activateSelector).click();
92+
}
93+
}
94+
95+
export async function uninstallACF(admin, page) {
96+
// First, delete all ACF custom post types to clean up
97+
await admin.visitAdminPage("/edit.php?post_type=acf-post-type");
98+
99+
// Check if there are any post types to delete
100+
const postTypeRows = await page
101+
.locator(".wp-list-table tbody tr:not(.no-items)")
102+
.count();
103+
104+
if (postTypeRows > 0) {
105+
// Select all post types using the checkbox
106+
await page.locator("#cb-select-all-1").check();
107+
108+
// Select "Move to Trash" from bulk actions dropdown
109+
await page.locator("#bulk-action-selector-bottom").selectOption("trash");
110+
111+
// Click Apply button
112+
await page.locator("#doaction2").click();
113+
114+
// Wait for the bulk action to complete
115+
await page.waitForLoadState("networkidle");
116+
}
117+
118+
// Now uninstall the plugin
119+
page.on("dialog", (dialog) => dialog.accept());
120+
121+
await admin.visitAdminPage("/plugins.php");
122+
await page.locator("a#deactivate-advanced-custom-fields").click();
123+
await page.locator("a#delete-advanced-custom-fields").click();
124+
}
125+
126+
export async function createACFPostType(admin, page, postTypeConfig) {
127+
// Navigate to ACF Post Types page
128+
await admin.visitAdminPage("/edit.php?post_type=acf-post-type");
129+
130+
// Click "Add New" button in the ACF header
131+
await page.getByRole("link", { name: "Add New", exact: true }).click();
132+
133+
// Wait for the form to load
134+
await page.waitForSelector('input[name="acf_post_type[labels][name]"]');
135+
136+
// Fill in the singular label first (this auto-generates the key)
137+
await page
138+
.locator('input[name="acf_post_type[labels][singular_name]"]')
139+
.fill(postTypeConfig.singularLabel);
140+
141+
// Clear and fill in the post type key to ensure it's correct
142+
const postTypeKeyInput = page.locator(
143+
'input[name="acf_post_type[post_type]"]'
144+
);
145+
await postTypeKeyInput.clear();
146+
await postTypeKeyInput.fill(postTypeConfig.key);
147+
148+
// Fill in the plural label
149+
await page
150+
.locator('input[name="acf_post_type[labels][name]"]')
151+
.fill(postTypeConfig.pluralLabel);
152+
153+
// Save the post type using the form submit button
154+
await page.getByRole("button", { name: "Save Changes" }).click();
155+
await page.waitForSelector(".notice.notice-success", { timeout: 10000 });
156+
}

pnpm-lock.yaml

Lines changed: 0 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)