55const { test, expect } = require ( './fixtures' ) ;
66
77const PLUGIN_SLUG = 'secure-custom-fields' ;
8- const TEST_PLUGIN_SLUG = 'scf-test-setup-post-types' ;
98const FIELD_GROUP_LABEL = 'Product Details' ;
109const TEXT_FIELD_LABEL = 'Product Name' ;
11- const TEXTAREA_FIELD_LABEL = 'Product Description' ;
1210const IMAGE_FIELD_LABEL = 'Product Image' ;
13- const URL_FIELD_LABEL = 'Product Link' ;
14- const POST_TYPE = 'product' ;
1511
1612test . describe ( 'Block Bindings in Site Editor' , ( ) => {
1713 test . beforeAll ( async ( { requestUtils } : any ) => {
1814 await requestUtils . activatePlugin ( PLUGIN_SLUG ) ;
19- await requestUtils . activatePlugin ( TEST_PLUGIN_SLUG ) ;
2015 } ) ;
2116
2217 test . afterAll ( async ( { requestUtils } ) => {
23- await requestUtils . deactivatePlugin ( TEST_PLUGIN_SLUG ) ;
2418 await requestUtils . deactivatePlugin ( PLUGIN_SLUG ) ;
2519 await requestUtils . deleteAllPosts ( ) ;
2620 } ) ;
@@ -29,282 +23,87 @@ test.describe( 'Block Bindings in Site Editor', () => {
2923 page,
3024 admin,
3125 } ) => {
32- // Create a field group
26+ // Navigate to Field Groups and create new.
3327 await admin . visitAdminPage ( 'edit.php' , 'post_type=acf-field-group' ) ;
34- await page . click ( 'a.acf-btn:has-text("Add New")' ) ;
28+ const addNewButton = page . locator ( 'a.acf-btn:has-text("Add New")' ) ;
29+ await addNewButton . click ( ) ;
3530
36- // Fill field group title
31+ // Fill field group title.
32+ await page . waitForSelector ( '#title' ) ;
3733 await page . fill ( '#title' , FIELD_GROUP_LABEL ) ;
3834
39- // Add text field
35+ // Add text field.
4036 const fieldLabel = page . locator (
4137 'input[id^="acf_fields-field_"][id$="-label"]'
4238 ) ;
4339 await fieldLabel . fill ( TEXT_FIELD_LABEL ) ;
40+ // The field name is generated automatically.
4441
45- // Set field type
42+ // Select field type as text (it's default, but let's be explicit).
4643 const fieldType = page . locator (
4744 'select[id^="acf_fields-field_"][id$="-type"]'
4845 ) ;
4946 await fieldType . selectOption ( 'text' ) ;
5047
51- // Show in REST API
52- await page . check ( 'input[name*="[show_in_rest]"]' ) ;
48+ // Select Group Settings > Enable REST API
49+ const groupSettingsTab = page . getByRole ( 'link' , { name : 'Group Settings' } ) ;
50+ await groupSettingsTab . click ( ) ;
5351
54- // Set location to product post type
55- const locationSelect = page . locator (
56- 'select[data-name="param"]'
57- ) ;
58- await locationSelect . selectOption ( 'post_type' ) ;
52+ // Enable Show in REST API
53+ const showInRestCheckbox = page . locator ( '#acf_field_group-show_in_rest' ) ;
54+ await showInRestCheckbox . check ( { force : true } ) ;
5955
60- const locationValue = page . locator (
61- 'select[data-name="value"]'
56+ // Submit form.
57+ const publishButton = page . locator (
58+ 'button.acf-btn.acf-publish[type="submit"]'
6259 ) ;
63- await locationValue . selectOption ( POST_TYPE ) ;
64-
65- // Publish field group
66- await page . click ( 'button.acf-btn.acf-publish[type="submit"]' ) ;
60+ await publishButton . click ( ) ;
6761
68- // Wait for success message
69- await page . waitForSelector ( '.updated.notice' ) ;
62+ // Verify success message.
63+ const successNotice = page . locator ( '.updated.notice' ) ;
64+ await expect ( successNotice ) . toBeVisible ( ) ;
65+ await expect ( successNotice ) . toContainText ( 'Field group published' ) ;
7066
7167 // Navigate to site editor
72- await admin . visitAdminPage ( 'site-editor.php' ) ;
73-
74- // Wait for site editor to load
75- await page . waitForSelector ( '.edit-site-header' ) ;
76-
77- // Create or edit a template for the product post type
78- // This part will depend on the actual site editor implementation
79- // For now, we'll test that the REST API endpoint returns the fields
80- const response = await page . evaluate ( async ( ) => {
81- const res = await fetch ( '/wp-json/wp/v2/types/product?context=edit' ) ;
82- return res . json ( ) ;
83- } ) ;
84-
85- expect ( response ) . toHaveProperty ( 'scf_field_groups' ) ;
86- expect ( response . scf_field_groups ) . toBeInstanceOf ( Array ) ;
87- expect ( response . scf_field_groups . length ) . toBeGreaterThan ( 0 ) ;
88-
89- const fieldGroup = response . scf_field_groups [ 0 ] ;
90- expect ( fieldGroup ) . toHaveProperty ( 'title' , FIELD_GROUP_LABEL ) ;
91- expect ( fieldGroup . fields ) . toBeInstanceOf ( Array ) ;
92- expect ( fieldGroup . fields [ 0 ] ) . toHaveProperty ( 'label' , TEXT_FIELD_LABEL ) ;
93- expect ( fieldGroup . fields [ 0 ] ) . toHaveProperty ( 'type' , 'text' ) ;
94- } ) ;
95-
96- test ( 'should bind image field to image block in site editor' , async ( {
97- page,
98- admin,
99- } ) => {
100- // Create a field group with image field
101- await admin . visitAdminPage ( 'edit.php' , 'post_type=acf-field-group' ) ;
102- await page . click ( 'a.acf-btn:has-text("Add New")' ) ;
103-
104- await page . fill ( '#title' , 'Product Images' ) ;
105-
106- const fieldLabel = page . locator (
107- 'input[id^="acf_fields-field_"][id$="-label"]'
108- ) ;
109- await fieldLabel . fill ( IMAGE_FIELD_LABEL ) ;
110-
111- const fieldType = page . locator (
112- 'select[id^="acf_fields-field_"][id$="-type"]'
113- ) ;
114- await fieldType . selectOption ( 'image' ) ;
115-
116- // Show in REST API
117- await page . check ( 'input[name*="[show_in_rest]"]' ) ;
118-
119- // Set location
120- const locationSelect = page . locator (
121- 'select[data-name="param"]'
122- ) ;
123- await locationSelect . selectOption ( 'post_type' ) ;
124-
125- const locationValue = page . locator (
126- 'select[data-name="value"]'
127- ) ;
128- await locationValue . selectOption ( POST_TYPE ) ;
129-
130- // Publish field group
131- await page . click ( 'button.acf-btn.acf-publish[type="submit"]' ) ;
132-
133- await page . waitForSelector ( '.updated.notice' ) ;
134-
135- // Verify field is available via REST API
136- const response = await page . evaluate ( async ( ) => {
137- const res = await fetch ( '/wp-json/wp/v2/types/product?context=edit' ) ;
138- return res . json ( ) ;
139- } ) ;
140-
141- const imageField = response . scf_field_groups
142- . flatMap ( ( group ) => group . fields )
143- . find ( ( field ) => field . label === IMAGE_FIELD_LABEL ) ;
144-
145- expect ( imageField ) . toBeDefined ( ) ;
146- expect ( imageField . type ) . toBe ( 'image' ) ;
147- } ) ;
148-
149- test ( 'should retrieve field groups for custom post type via REST API' , async ( {
150- page,
151- admin,
152- } ) => {
153- // Create a comprehensive field group
154- await admin . visitAdminPage ( 'edit.php' , 'post_type=acf-field-group' ) ;
155- await page . click ( 'a.acf-btn:has-text("Add New")' ) ;
156-
157- await page . fill ( '#title' , 'Complete Product Fields' ) ;
68+ await admin . visitAdminPage ( 'site-editor.php?p=%2Fwp_template%2Ftwentytwentyfive%2F%2Fsingle&canvas=edit' ) ;
15869
159- // Add multiple field types
160- const fields = [
161- { label : 'Name' , type : 'text' } ,
162- { label : 'Description' , type : 'textarea' } ,
163- { label : 'Price' , type : 'number' } ,
164- { label : 'Featured Image' , type : 'image' } ,
165- { label : 'External URL' , type : 'url' } ,
166- ] ;
70+ // Wait for the site editor to load - wait for the iframe or editor container
71+ await page . waitForSelector ( 'iframe[name="editor-canvas"]' , { timeout : 10000 } ) ;
72+ await page . waitForTimeout ( 2000 ) ; // Give the editor a moment to fully load
16773
168- for ( let i = 0 ; i < fields . length ; i ++ ) {
169- if ( i > 0 ) {
170- // Click add field button for additional fields
171- await page . click ( 'a.acf-button-add:has-text("Add Field")' ) ;
172- }
74+ // Get the iframe and work within it
75+ const frameLocator = page . frameLocator ( 'iframe[name="editor-canvas"]' ) ;
76+
77+ // Click on the content block within the iframe
78+ const contentBlock = frameLocator . locator ( '[data-type="core/post-content"]' ) . first ( ) ;
79+ await contentBlock . click ( ) ;
17380
174- const fieldLabelInput = page . locator (
175- `input[id^="acf_fields-field_"][id$="-label"]`
176- ) . nth ( i ) ;
177- await fieldLabelInput . fill ( fields [ i ] . label ) ;
81+ // Press Enter to add a new paragraph block
82+ await page . keyboard . press ( 'Enter' ) ;
17883
179- const fieldTypeSelect = page . locator (
180- `select[id^="acf_fields-field_"][id$="-type"]`
181- ) . nth ( i ) ;
182- await fieldTypeSelect . selectOption ( fields [ i ] . type ) ;
84+ // Wait for the newly created empty paragraph block
85+ await frameLocator . locator ( '[data-type="core/paragraph"][data-empty="true"]' ) . waitFor ( { timeout : 5000 } ) ;
18386
184- // Show in REST API
185- const restCheckbox = page . locator (
186- 'input[name*="[show_in_rest]"]'
187- ) . nth ( i ) ;
188- await restCheckbox . check ( ) ;
189- }
87+ // Click on the empty paragraph block to select it
88+ const emptyParagraph = frameLocator . locator ( '[data-type="core/paragraph"][data-empty="true"]' ) ;
89+ await emptyParagraph . click ( ) ;
19090
191- // Set location
192- const locationSelect = page . locator (
193- 'select[data-name="param"]'
194- ) ;
195- await locationSelect . selectOption ( 'post_type' ) ;
196-
197- const locationValue = page . locator (
198- 'select[data-name="value"]'
199- ) ;
200- await locationValue . selectOption ( POST_TYPE ) ;
201-
202- // Publish field group
203- await page . click ( 'button.acf-btn.acf-publish[type="submit"]' ) ;
204-
205- await page . waitForSelector ( '.updated.notice' ) ;
206-
207- // Test REST API response
208- const response = await page . evaluate ( async ( ) => {
209- const res = await fetch ( '/wp-json/wp/v2/types/product?context=edit' ) ;
210- return res . json ( ) ;
211- } ) ;
212-
213- expect ( response . scf_field_groups ) . toBeInstanceOf ( Array ) ;
214-
215- const fieldGroup = response . scf_field_groups . find (
216- ( group ) => group . title === 'Complete Product Fields'
217- ) ;
218-
219- expect ( fieldGroup ) . toBeDefined ( ) ;
220- expect ( fieldGroup . fields . length ) . toBe ( fields . length ) ;
221-
222- fields . forEach ( ( field , index ) => {
223- expect ( fieldGroup . fields [ index ] . label ) . toBe ( field . label ) ;
224- expect ( fieldGroup . fields [ index ] . type ) . toBe ( field . type ) ;
225- } ) ;
226- } ) ;
227-
228- test ( 'should filter post types by source parameter' , async ( {
229- page,
230- } ) => {
231- // Test core source
232- const coreResponse = await page . evaluate ( async ( ) => {
233- const res = await fetch ( '/wp-json/wp/v2/types?source=core' ) ;
234- return res . json ( ) ;
235- } ) ;
236-
237- expect ( coreResponse ) . toHaveProperty ( 'post' ) ;
238- expect ( coreResponse ) . toHaveProperty ( 'page' ) ;
239- expect ( coreResponse ) . not . toHaveProperty ( 'product' ) ;
240-
241- // Test other source (should include custom post types)
242- const otherResponse = await page . evaluate ( async ( ) => {
243- const res = await fetch ( '/wp-json/wp/v2/types?source=other' ) ;
244- return res . json ( ) ;
245- } ) ;
246-
247- // Custom post types should be in 'other'
248- expect ( Object . keys ( otherResponse ) . length ) . toBeGreaterThanOrEqual ( 0 ) ;
249- } ) ;
91+ // Wait for the "Connect to a field" panel to appear in the block inspector
92+ await page . waitForSelector ( 'input[id^="components-form-token-input-combobox-control-"]' , { timeout : 5000 } ) ;
25093
251- test ( 'should handle bindings with show_in_rest enabled' , async ( {
252- page,
253- admin,
254- requestUtils,
255- } ) => {
256- // Create a field group with show_in_rest enabled
257- await admin . visitAdminPage ( 'edit.php' , 'post_type=acf-field-group' ) ;
258- await page . click ( 'a.acf-btn:has-text("Add New")' ) ;
259-
260- await page . fill ( '#title' , 'REST Enabled Fields' ) ;
261-
262- const fieldLabel = page . locator (
263- 'input[id^="acf_fields-field_"][id$="-label"]'
264- ) ;
265- await fieldLabel . fill ( 'REST Field' ) ;
266-
267- const fieldType = page . locator (
268- 'select[id^="acf_fields-field_"][id$="-type"]'
269- ) ;
270- await fieldType . selectOption ( 'text' ) ;
271-
272- // Enable show in REST API
273- await page . check ( 'input[name*="[show_in_rest]"]' ) ;
274-
275- // Set location
276- const locationSelect = page . locator (
277- 'select[data-name="param"]'
278- ) ;
279- await locationSelect . selectOption ( 'post_type' ) ;
280-
281- const locationValue = page . locator (
282- 'select[data-name="value"]'
283- ) ;
284- await locationValue . selectOption ( 'post' ) ;
94+ // Click on the combobox input to open suggestions
95+ const comboboxInput = page . locator ( 'input[id^="components-form-token-input-combobox-control-"]' ) . first ( ) ;
96+ await comboboxInput . click ( ) ;
28597
286- // Publish
287- await page . click ( 'button.acf-btn.acf-publish[type="submit"]' ) ;
288- await page . waitForSelector ( '.updated.notice' ) ;
98+ // Wait for suggestions to appear
99+ await page . waitForSelector ( 'ul[id^="components-form-token-suggestions-combobox-control-"]' , { timeout : 5000 } ) ;
289100
290- // Create a post with the field
291- const post = await requestUtils . createPost ( {
292- title : 'Test Post' ,
293- status : 'publish' ,
294- acf : {
295- rest_field : 'Test value' ,
296- } ,
297- } ) ;
101+ // Select "Product Name" from the dropdown
102+ await page . getByRole ( 'option' , { name : 'Product Name' } ) . click ( ) ;
298103
299- // Verify field is accessible via REST API
300- const response = await page . evaluate ( async ( postId ) => {
301- const res = await fetch (
302- `/wp-json/wp/v2/posts/${ postId } ?context=edit`
303- ) ;
304- return res . json ( ) ;
305- } , post . id ) ;
104+ // Verify the paragraph block now contains "Product Name"
105+ const boundParagraph = frameLocator . locator ( '[data-type="core/paragraph"]:has-text("Product Name")' ) ;
106+ await expect ( boundParagraph ) . toBeVisible ( ) ;
306107
307- expect ( response ) . toHaveProperty ( 'acf' ) ;
308- expect ( response . acf ) . toHaveProperty ( 'rest_field' ) ;
309108 } ) ;
310109} ) ;
0 commit comments