Skip to content

Commit a840671

Browse files
committed
Tests: Add PHPUnit tests for field type classes with abstract base
1 parent f7cf76b commit a840671

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+6911
-99
lines changed

tests/php/bootstrap.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313

1414
// Load our plugin.
1515
require dirname( dirname( __DIR__ ) ) . '/secure-custom-fields.php';
16+
17+
// Load abstract test base classes.
18+
require_once __DIR__ . '/includes/fields/abstract-class-acf-field-test.php';
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
/**
3+
* Abstract base test class for ACF field types.
4+
*
5+
* @package wordpress/secure-custom-fields
6+
* @group fields
7+
*/
8+
9+
use WorDBless\BaseTestCase;
10+
11+
/**
12+
* Abstract base test class providing common functionality for ACF field tests.
13+
*/
14+
abstract class Abstract_ACF_Field_Test extends BaseTestCase {
15+
16+
/**
17+
* Test post ID.
18+
*
19+
* @var int
20+
*/
21+
protected $post_id;
22+
23+
/**
24+
* Field instance.
25+
*
26+
* @var acf_field
27+
*/
28+
protected $field_instance;
29+
30+
/**
31+
* Get the field type for this test class.
32+
*
33+
* @return string The field type identifier.
34+
*/
35+
abstract protected function get_field_type();
36+
37+
/**
38+
* Get a base field configuration with optional overrides.
39+
*
40+
* @param array $overrides Optional field configuration overrides.
41+
* @return array The field configuration array.
42+
*/
43+
abstract protected function get_field( $overrides = array() );
44+
45+
/**
46+
* Get the include path(s) for the field class.
47+
*
48+
* Override this method to provide custom include paths.
49+
* By default, derives the path from the field type name.
50+
*
51+
* Note: Field filenames are NOT consistent - some use underscores
52+
* (e.g., 'true_false', 'color_picker'), others use hyphens
53+
* (e.g., 'button-group', 'flexible-content'). This method handles
54+
* the known inconsistencies.
55+
*
56+
* @return string|array Include path(s) relative to ACF plugin directory.
57+
*/
58+
protected function get_field_include_path() {
59+
$type = $this->get_field_type();
60+
61+
// These fields use hyphens in filenames but underscores in type names.
62+
$hyphen_fields = array(
63+
'button_group',
64+
'flexible_content',
65+
'google_map',
66+
'nav_menu',
67+
);
68+
69+
if ( in_array( $type, $hyphen_fields, true ) ) {
70+
$filename = str_replace( '_', '-', $type );
71+
} else {
72+
$filename = $type;
73+
}
74+
75+
return "includes/fields/class-acf-field-{$filename}.php";
76+
}
77+
78+
/**
79+
* Set up the test case.
80+
*/
81+
public function set_up() {
82+
parent::set_up();
83+
84+
// Load the field class file(s).
85+
$paths = $this->get_field_include_path();
86+
$paths = is_array( $paths ) ? $paths : array( $paths );
87+
foreach ( $paths as $path ) {
88+
acf_include( $path );
89+
}
90+
91+
// Create a test post.
92+
$this->post_id = wp_insert_post(
93+
array(
94+
'post_title' => 'Test Post',
95+
'post_status' => 'publish',
96+
'post_type' => 'post',
97+
)
98+
);
99+
100+
// Get the field instance.
101+
$this->field_instance = acf_get_field_type( $this->get_field_type() );
102+
}
103+
104+
/**
105+
* Clean up after each test.
106+
*/
107+
public function tear_down() {
108+
if ( $this->post_id ) {
109+
wp_delete_post( $this->post_id, true );
110+
}
111+
parent::tear_down();
112+
}
113+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/**
3+
* Tests for the Accordion field type.
4+
*
5+
* @package wordpress/secure-custom-fields
6+
* @group fields
7+
*/
8+
9+
/**
10+
* Tests for acf_field_accordion.
11+
*
12+
* Note: Accordion is a layout-only field with no data storage.
13+
* Tests focus on load_field behavior and REST schema.
14+
*/
15+
class Test_ACF_Field_Accordion extends Abstract_ACF_Field_Test {
16+
17+
/**
18+
* Get the field type name.
19+
*
20+
* @return string
21+
*/
22+
protected function get_field_type() {
23+
return 'accordion';
24+
}
25+
26+
/**
27+
* Get a base accordion field configuration.
28+
*
29+
* @param array $overrides Optional overrides.
30+
* @return array
31+
*/
32+
protected function get_field( $overrides = array() ) {
33+
return array_merge(
34+
array(
35+
'key' => 'field_accordion_test',
36+
'name' => 'test_accordion',
37+
'type' => 'accordion',
38+
'label' => 'Test Accordion',
39+
'open' => 0,
40+
'multi_expand' => 0,
41+
'endpoint' => 0,
42+
),
43+
$overrides
44+
);
45+
}
46+
47+
/**
48+
* Test load_field removes name to avoid caching issues.
49+
*/
50+
public function test_load_field_removes_name() {
51+
$field = $this->get_field( array( 'name' => 'my_accordion' ) );
52+
53+
$loaded = $this->field_instance->load_field( $field );
54+
55+
$this->assertEmpty( $loaded['name'] );
56+
}
57+
58+
/**
59+
* Test load_field sets required to 0.
60+
*/
61+
public function test_load_field_sets_required_zero() {
62+
$field = $this->get_field( array( 'required' => 1 ) );
63+
64+
$loaded = $this->field_instance->load_field( $field );
65+
66+
$this->assertEquals( 0, $loaded['required'] );
67+
}
68+
69+
/**
70+
* Test load_field sets value to false.
71+
*/
72+
public function test_load_field_sets_value_false() {
73+
$field = $this->get_field();
74+
75+
$loaded = $this->field_instance->load_field( $field );
76+
77+
$this->assertFalse( $loaded['value'] );
78+
}
79+
80+
/**
81+
* Test get_rest_schema returns null type for layout field.
82+
*/
83+
public function test_get_rest_schema_returns_null_type() {
84+
$field = $this->get_field();
85+
86+
$schema = $this->field_instance->get_rest_schema( $field );
87+
88+
$this->assertIsArray( $schema );
89+
$this->assertContains( 'null', $schema['type'] );
90+
}
91+
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
<?php
2+
/**
3+
* Tests for the Button Group field type.
4+
*
5+
* @package wordpress/secure-custom-fields
6+
* @group fields
7+
*/
8+
9+
/**
10+
* Tests for acf_field_button_group.
11+
*/
12+
class Test_ACF_Field_Button_Group extends Abstract_ACF_Field_Test {
13+
/**
14+
* Get the field type name.
15+
*
16+
* @return string
17+
*/
18+
protected function get_field_type() {
19+
return 'button_group';
20+
}
21+
22+
/**
23+
* Get the include path(s) for the field class.
24+
*
25+
* Button Group depends on Radio which depends on Select.
26+
*
27+
* @return array
28+
*/
29+
protected function get_field_include_path() {
30+
return array(
31+
'includes/fields/class-acf-field-select.php',
32+
'includes/fields/class-acf-field-radio.php',
33+
'includes/fields/class-acf-field-button-group.php',
34+
);
35+
}
36+
37+
/**
38+
* Button Group field instance.
39+
*
40+
* @var acf_field_button_group
41+
*/
42+
protected $field_instance;
43+
44+
/**
45+
* Get a base button group field configuration.
46+
*
47+
* @param array $overrides Optional overrides.
48+
* @return array
49+
*/
50+
protected function get_field( $overrides = array() ) {
51+
return array_merge(
52+
array(
53+
'key' => 'field_button_group_test',
54+
'name' => 'test_button_group',
55+
'type' => 'button_group',
56+
'label' => 'Test Button Group',
57+
'required' => 0,
58+
'return_format' => 'value',
59+
'choices' => array(
60+
'left' => 'Left',
61+
'center' => 'Center',
62+
'right' => 'Right',
63+
),
64+
'allow_null' => 0,
65+
'layout' => 'horizontal',
66+
),
67+
$overrides
68+
);
69+
}
70+
71+
72+
/**
73+
* Test format_value with value return format.
74+
*/
75+
public function test_format_value_value_format() {
76+
$field = $this->get_field( array( 'return_format' => 'value' ) );
77+
78+
$result = $this->field_instance->format_value( 'left', $this->post_id, $field );
79+
80+
$this->assertEquals( 'left', $result );
81+
}
82+
83+
/**
84+
* Test format_value with label return format.
85+
*/
86+
public function test_format_value_label_format() {
87+
$field = $this->get_field( array( 'return_format' => 'label' ) );
88+
89+
$result = $this->field_instance->format_value( 'center', $this->post_id, $field );
90+
91+
$this->assertEquals( 'Center', $result );
92+
}
93+
94+
/**
95+
* Test format_value with array return format.
96+
*/
97+
public function test_format_value_array_format() {
98+
$field = $this->get_field( array( 'return_format' => 'array' ) );
99+
100+
$result = $this->field_instance->format_value( 'right', $this->post_id, $field );
101+
102+
$this->assertIsArray( $result );
103+
$this->assertArrayHasKey( 'value', $result );
104+
$this->assertArrayHasKey( 'label', $result );
105+
$this->assertEquals( 'right', $result['value'] );
106+
$this->assertEquals( 'Right', $result['label'] );
107+
}
108+
109+
/**
110+
* Test format_value returns empty string for empty.
111+
*/
112+
public function test_format_value_empty() {
113+
$field = $this->get_field();
114+
115+
$result = $this->field_instance->format_value( '', $this->post_id, $field );
116+
117+
$this->assertSame( '', $result );
118+
}
119+
120+
/**
121+
* Test format_value_for_rest returns the raw value.
122+
*
123+
* Note: Button group doesn't override format_value_for_rest, so it inherits
124+
* the base class behavior which returns the raw value unchanged.
125+
* The return_format setting only affects format_value, not REST output.
126+
*/
127+
public function test_format_value_for_rest() {
128+
$field = $this->get_field( array( 'return_format' => 'value' ) );
129+
130+
$rest_result = $this->field_instance->format_value_for_rest( 'left', $this->post_id, $field );
131+
132+
// REST returns raw value, not formatted value.
133+
$this->assertEquals( 'left', $rest_result );
134+
}
135+
136+
/**
137+
* Test get_rest_schema returns valid schema.
138+
*/
139+
public function test_get_rest_schema() {
140+
$field = $this->get_field();
141+
142+
$schema = $this->field_instance->get_rest_schema( $field );
143+
144+
$this->assertIsArray( $schema );
145+
$this->assertContains( 'string', $schema['type'] );
146+
}
147+
148+
/**
149+
* Test load_value returns stored value.
150+
*/
151+
public function test_load_value() {
152+
$field = $this->get_field();
153+
154+
$result = $this->field_instance->load_value( 'right', $this->post_id, $field );
155+
156+
$this->assertEquals( 'right', $result );
157+
}
158+
159+
/**
160+
* Test allow_null option.
161+
*/
162+
public function test_allow_null() {
163+
$field = $this->get_field( array( 'allow_null' => 1 ) );
164+
165+
$result = $this->field_instance->format_value( '', $this->post_id, $field );
166+
167+
$this->assertSame( '', $result );
168+
}
169+
170+
/**
171+
* Test format_value with unknown choice returns value.
172+
*/
173+
public function test_format_value_unknown_choice() {
174+
$field = $this->get_field( array( 'return_format' => 'label' ) );
175+
176+
$result = $this->field_instance->format_value( 'unknown', $this->post_id, $field );
177+
178+
// Unknown choices should return the value itself.
179+
$this->assertEquals( 'unknown', $result );
180+
}
181+
}

0 commit comments

Comments
 (0)