Skip to content

Commit 4b1c987

Browse files
authored
Testing: Add repeater e2e test. (#134)
1 parent 2f899c6 commit 4b1c987

File tree

3 files changed

+258
-1
lines changed

3 files changed

+258
-1
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
5+
6+
const PLUGIN_SLUG = 'secure-custom-fields';
7+
const TEST_PLUGIN_SLUG = 'scf-test-plugin-get-repeater-field';
8+
const FIELD_GROUP_LABEL = 'Movie Repeater Details';
9+
const REPEATER_FIELD_LABEL = 'Actors';
10+
11+
test.describe( 'Field Type > Repeater', () => {
12+
test.beforeAll( async ( { requestUtils } ) => {
13+
await requestUtils.activatePlugin( PLUGIN_SLUG );
14+
await requestUtils.activatePlugin( TEST_PLUGIN_SLUG );
15+
} );
16+
17+
test.afterAll( async ( { requestUtils } ) => {
18+
await requestUtils.deactivatePlugin( PLUGIN_SLUG );
19+
await requestUtils.deactivatePlugin( TEST_PLUGIN_SLUG );
20+
await requestUtils.deleteAllPosts();
21+
} );
22+
23+
test.beforeEach( async ( { page, admin } ) => {
24+
await deleteFieldGroups( page, admin );
25+
} );
26+
27+
test( 'should create a repeater field with subfields and verify it in admin', async ( {
28+
page,
29+
admin,
30+
editor,
31+
requestUtils,
32+
} ) => {
33+
// Navigate to Field Groups and create new.
34+
await admin.visitAdminPage( 'edit.php', 'post_type=acf-field-group' );
35+
const addNewButton = page.locator( 'a.acf-btn:has-text("Add New")' );
36+
await addNewButton.click();
37+
38+
// Fill field group title.
39+
await page.waitForSelector( '#title' );
40+
await page.fill( '#title', FIELD_GROUP_LABEL );
41+
42+
// Add repeater field
43+
const fieldType = page.locator(
44+
'select[id^="acf_fields-field_"][id$="-type"]'
45+
);
46+
await fieldType.selectOption( 'repeater' );
47+
48+
// Set repeater field label
49+
const fieldLabel = page.locator(
50+
'input[id^="acf_fields-field_"][id$="-label"]'
51+
);
52+
await fieldLabel.fill( REPEATER_FIELD_LABEL );
53+
54+
// Find and click the "Add Field" button inside the repeater's sub fields section
55+
const addSubFieldButton = page.locator('.acf-field-setting-sub_fields a.add-first-field')
56+
await addSubFieldButton.click();
57+
58+
// Wait for the subfield to be added and set properties
59+
const subFieldLabel = page.locator(
60+
'.acf-field-object.acf-field-object-text input.field-label'
61+
).last();
62+
await subFieldLabel.waitFor();
63+
await subFieldLabel.fill( 'Actor Name' );
64+
65+
// Add another subfield
66+
const addAnotherSubFieldButton = page.locator(
67+
'.acf-field-setting-sub_fields .acf-is-subfields a.add-field.acf-btn-secondary'
68+
);
69+
await addAnotherSubFieldButton.click();
70+
71+
// Wait for the second subfield to be added
72+
const secondSubFieldLabel = page.locator(
73+
'.acf-field-object.acf-field-object-text input.field-label'
74+
).last();
75+
await secondSubFieldLabel.waitFor();
76+
await secondSubFieldLabel.fill( 'Actor Email' );
77+
78+
// Change the second subfield type from text to email
79+
const secondSubFieldType = page.locator(
80+
'.acf-field-object'
81+
).last().locator('select.field-type');
82+
await secondSubFieldType.selectOption('email');
83+
84+
// Submit form
85+
const publishButton = page.locator(
86+
'button.acf-btn.acf-publish[type="submit"]'
87+
);
88+
await publishButton.click();
89+
90+
// Verify success message.
91+
const successNotice = page.locator( '.updated.notice' );
92+
await expect( successNotice ).toBeVisible();
93+
await expect( successNotice ).toContainText( 'Field group published' );
94+
95+
// Verify field group appears in the list.
96+
await admin.visitAdminPage( 'edit.php', 'post_type=acf-field-group' );
97+
const fieldGroupRow = page.locator(
98+
`tr:has-text("${ FIELD_GROUP_LABEL }")`
99+
);
100+
await expect( fieldGroupRow ).toBeVisible();
101+
102+
// Create a new post
103+
const post = await requestUtils.createPost( {
104+
title: 'Movie with Actors',
105+
status: 'draft',
106+
showWelcomeGuide: false,
107+
} );
108+
109+
// Navigate to edit post page
110+
await admin.editPost( post.id );
111+
112+
// Add a repeater row - using the correct selector matching the actual DOM element
113+
const addRowButton = page.locator(
114+
'a.acf-button.acf-repeater-add-row[data-event="add-row"]'
115+
);
116+
await addRowButton.click();
117+
118+
// Fill in the fields in the repeater
119+
const actorNameField = page.locator(
120+
'.acf-field[data-name="actor_name"] input[type="text"]'
121+
).first();
122+
await actorNameField.fill( 'Morgan Freeman' );
123+
124+
const characterEmailField = page.locator(
125+
'.acf-field[data-name="actor_email"] input[type="email"]'
126+
).first();
127+
await characterEmailField.fill( 'red@shawshank.com' );
128+
129+
// Add another row
130+
await addRowButton.click();
131+
132+
// Fill in the second row
133+
const actorNameField2 = page.locator(
134+
'.acf-field[data-name="actor_name"] input[type="text"]'
135+
).nth(1);
136+
await actorNameField2.fill( 'Tim Robbins' );
137+
138+
const characterEmailField2 = page.locator(
139+
'.acf-field[data-name="actor_email"] input[type="email"]'
140+
).nth(1);
141+
await characterEmailField2.fill( 'andy@shawshank.com' );
142+
143+
// Verify the movie title is displayed
144+
const previewPage = await editor.openPreviewPage();
145+
146+
// Check for repeater field output
147+
const actorsList = previewPage.locator('#scf-test-actors');
148+
await expect(actorsList).toBeVisible();
149+
150+
// Check the heading
151+
await expect(actorsList.locator('h3')).toContainText('Movie Cast');
152+
// Verify the first actor's information
153+
const firstActorItem = actorsList.locator('li').nth(0);
154+
await expect(firstActorItem.locator('.actor-name')).toContainText('Actor: Morgan Freeman');
155+
await expect(firstActorItem.locator('.actor-email')).toContainText('Email: red@shawshank.com');
156+
157+
// Verify the second actor's information
158+
const secondActorItem = actorsList.locator('li').nth(1);
159+
await expect(secondActorItem.locator('.actor-name')).toContainText('Actor: Tim Robbins');
160+
await expect(secondActorItem.locator('.actor-email')).toContainText('Email: andy@shawshank.com');
161+
162+
// Close the preview tab
163+
await previewPage.close();
164+
} );
165+
} );
166+
167+
/**
168+
* Helper function to delete the field group
169+
*/
170+
async function deleteFieldGroups( page, admin ) {
171+
await admin.visitAdminPage( 'edit.php', 'post_type=acf-field-group' );
172+
173+
// Find and select the field group row
174+
const allFieldGroupsCheckbox = page.locator( 'input#cb-select-all-1' );
175+
176+
if ( await allFieldGroupsCheckbox.isVisible() ) {
177+
await allFieldGroupsCheckbox.check();
178+
// Use bulk actions to trash the field group
179+
await page.selectOption( '#bulk-action-selector-bottom', 'trash' );
180+
await page.click( '#doaction2' );
181+
182+
// Verify deletion success message
183+
const deleteMessage = page.locator( '.updated.notice' );
184+
await expect( deleteMessage ).toBeVisible( { timeout: 5000 } );
185+
await expect( deleteMessage ).toContainText( 'moved to the Trash' );
186+
187+
await emptyTrash( page, admin );
188+
}
189+
}
190+
191+
/**
192+
* Helper function to empty trash
193+
*/
194+
async function emptyTrash( page, admin ) {
195+
await admin.visitAdminPage(
196+
'edit.php',
197+
'post_status=trash&post_type=acf-field-group'
198+
);
199+
const emptyTrashButton = page.locator(
200+
'.tablenav.bottom input[name="delete_all"][value="Empty Trash"]'
201+
);
202+
await emptyTrashButton.waitFor( { state: 'visible' } );
203+
await emptyTrashButton.click();
204+
205+
// Verify success notice
206+
const successNotice = page.locator( '.notice.updated p' );
207+
await expect( successNotice ).toBeVisible();
208+
await expect( successNotice ).toHaveText( /permanently deleted/ );
209+
}

tests/e2e/field-type-text-with-scf-block.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ test.describe( 'Field Type > Text', () => {
107107
await page.click('body', { position: { x: 0, y: 0 } });
108108

109109
// Let's also make sure we give the editor a moment to save the field data.
110-
await page.waitForTimeout(200);
110+
await page.waitForTimeout(500);
111111

112112
const previewPage = await editor.openPreviewPage();
113113

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
/**
3+
* Plugin Name: SCF Test Plugin, Get Repeater Field
4+
* Plugin URI: https://github.com/WordPress/secure-custom-fields
5+
* Author: SCF Team
6+
*
7+
* @package scf-test-plugins
8+
*/
9+
10+
/**
11+
* Add repeater field data to the end of content
12+
*/
13+
function scf_add_get_field_at_the_end() {
14+
$output = '';
15+
16+
// Check if we have the 'actors' repeater field
17+
if ( have_rows( 'actors' ) ) {
18+
$output .= '<div id="scf-test-actors" class="actors-list">';
19+
$output .= '<h3>Movie Cast</h3>';
20+
$output .= '<ul>';
21+
22+
// Loop through rows
23+
while ( have_rows( 'actors' ) ) {
24+
the_row();
25+
26+
// Get subfields
27+
$actor_name = get_sub_field( 'actor_name' );
28+
$actor_email = get_sub_field( 'actor_email' );
29+
30+
// Sanitize values
31+
$actor_name = is_string( $actor_name ) ? sanitize_text_field( $actor_name ) : '';
32+
$actor_email = is_string( $actor_email ) ? sanitize_email( $actor_email ) : '';
33+
34+
$output .= '<li>';
35+
$output .= '<span class="actor-name">Actor: ' . $actor_name . '</span><br>';
36+
$output .= '<span class="actor-email">Email: ' . $actor_email . '</span>';
37+
$output .= '</li>';
38+
}
39+
40+
$output .= '</ul>';
41+
$output .= '</div>';
42+
}
43+
44+
// Add the repeater data to the end of the content
45+
return $output;
46+
}
47+
48+
add_filter( 'the_content', 'scf_add_get_field_at_the_end' );

0 commit comments

Comments
 (0)