Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions tests/php/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@

// Load our plugin.
require dirname( dirname( __DIR__ ) ) . '/secure-custom-fields.php';

// Load abstract test base classes.
require_once __DIR__ . '/includes/fields/abstract-class-acf-field-test.php';
113 changes: 113 additions & 0 deletions tests/php/includes/fields/abstract-class-acf-field-test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php
/**
* Abstract base test class for ACF field types.
*
* @package wordpress/secure-custom-fields
* @group fields
*/

use WorDBless\BaseTestCase;

/**
* Abstract base test class providing common functionality for ACF field tests.
*/
abstract class Abstract_ACF_Field_Test extends BaseTestCase {

/**
* Test post ID.
*
* @var int
*/
protected $post_id;

/**
* Field instance.
*
* @var acf_field
*/
protected $field_instance;

/**
* Get the field type for this test class.
*
* @return string The field type identifier.
*/
abstract protected function get_field_type();

/**
* Get a base field configuration with optional overrides.
*
* @param array $overrides Optional field configuration overrides.
* @return array The field configuration array.
*/
abstract protected function get_field( $overrides = array() );

/**
* Get the include path(s) for the field class.
*
* Override this method to provide custom include paths.
* By default, derives the path from the field type name.
*
* Note: Field filenames are NOT consistent - some use underscores
* (e.g., 'true_false', 'color_picker'), others use hyphens
* (e.g., 'button-group', 'flexible-content'). This method handles
* the known inconsistencies.
*
* @return string|array Include path(s) relative to ACF plugin directory.
*/
protected function get_field_include_path() {
$type = $this->get_field_type();

// These fields use hyphens in filenames but underscores in type names.
$hyphen_fields = array(
'button_group',
'flexible_content',
'google_map',
'nav_menu',
);

if ( in_array( $type, $hyphen_fields, true ) ) {
$filename = str_replace( '_', '-', $type );
} else {
$filename = $type;
}

return "includes/fields/class-acf-field-{$filename}.php";
}

/**
* Set up the test case.
*/
public function set_up() {
parent::set_up();

// Load the field class file(s).
$paths = $this->get_field_include_path();
$paths = is_array( $paths ) ? $paths : array( $paths );
foreach ( $paths as $path ) {
acf_include( $path );
}

// Create a test post.
$this->post_id = wp_insert_post(
array(
'post_title' => 'Test Post',
'post_status' => 'publish',
'post_type' => 'post',
)
);

// Get the field instance.
$this->field_instance = acf_get_field_type( $this->get_field_type() );
}

/**
* Clean up after each test.
*/
public function tear_down() {
if ( $this->post_id ) {
wp_delete_post( $this->post_id, true );
}
parent::tear_down();
}
}
91 changes: 91 additions & 0 deletions tests/php/includes/fields/test-class-acf-field-accordion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php
/**
* Tests for the Accordion field type.
*
* @package wordpress/secure-custom-fields
* @group fields
*/

/**
* Tests for acf_field_accordion.
*
* Note: Accordion is a layout-only field with no data storage.
* Tests focus on load_field behavior and REST schema.
*/
class Test_ACF_Field_Accordion extends Abstract_ACF_Field_Test {

/**
* Get the field type name.
*
* @return string
*/
protected function get_field_type() {
return 'accordion';
}

/**
* Get a base accordion field configuration.
*
* @param array $overrides Optional overrides.
* @return array
*/
protected function get_field( $overrides = array() ) {
return array_merge(
array(
'key' => 'field_accordion_test',
'name' => 'test_accordion',
'type' => 'accordion',
'label' => 'Test Accordion',
'open' => 0,
'multi_expand' => 0,
'endpoint' => 0,
),
$overrides
);
}

/**
* Test load_field removes name to avoid caching issues.
*/
public function test_load_field_removes_name() {
$field = $this->get_field( array( 'name' => 'my_accordion' ) );

$loaded = $this->field_instance->load_field( $field );

$this->assertEmpty( $loaded['name'] );
}

/**
* Test load_field sets required to 0.
*/
public function test_load_field_sets_required_zero() {
$field = $this->get_field( array( 'required' => 1 ) );

$loaded = $this->field_instance->load_field( $field );

$this->assertEquals( 0, $loaded['required'] );
}

/**
* Test load_field sets value to false.
*/
public function test_load_field_sets_value_false() {
$field = $this->get_field();

$loaded = $this->field_instance->load_field( $field );

$this->assertFalse( $loaded['value'] );
}

/**
* Test get_rest_schema returns null type for layout field.
*/
public function test_get_rest_schema_returns_null_type() {
$field = $this->get_field();

$schema = $this->field_instance->get_rest_schema( $field );

$this->assertIsArray( $schema );
$this->assertContains( 'null', $schema['type'] );
}
}
181 changes: 181 additions & 0 deletions tests/php/includes/fields/test-class-acf-field-button-group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
<?php
/**
* Tests for the Button Group field type.
*
* @package wordpress/secure-custom-fields
* @group fields
*/

/**
* Tests for acf_field_button_group.
*/
class Test_ACF_Field_Button_Group extends Abstract_ACF_Field_Test {
/**
* Get the field type name.
*
* @return string
*/
protected function get_field_type() {
return 'button_group';
}

/**
* Get the include path(s) for the field class.
*
* Button Group depends on Radio which depends on Select.
*
* @return array
*/
protected function get_field_include_path() {
return array(
'includes/fields/class-acf-field-select.php',
'includes/fields/class-acf-field-radio.php',
'includes/fields/class-acf-field-button-group.php',
);
}

/**
* Button Group field instance.
*
* @var acf_field_button_group
*/
protected $field_instance;

/**
* Get a base button group field configuration.
*
* @param array $overrides Optional overrides.
* @return array
*/
protected function get_field( $overrides = array() ) {
return array_merge(
array(
'key' => 'field_button_group_test',
'name' => 'test_button_group',
'type' => 'button_group',
'label' => 'Test Button Group',
'required' => 0,
'return_format' => 'value',
'choices' => array(
'left' => 'Left',
'center' => 'Center',
'right' => 'Right',
),
'allow_null' => 0,
'layout' => 'horizontal',
),
$overrides
);
}


/**
* Test format_value with value return format.
*/
public function test_format_value_value_format() {
$field = $this->get_field( array( 'return_format' => 'value' ) );

$result = $this->field_instance->format_value( 'left', $this->post_id, $field );

$this->assertEquals( 'left', $result );
}

/**
* Test format_value with label return format.
*/
public function test_format_value_label_format() {
$field = $this->get_field( array( 'return_format' => 'label' ) );

$result = $this->field_instance->format_value( 'center', $this->post_id, $field );

$this->assertEquals( 'Center', $result );
}

/**
* Test format_value with array return format.
*/
public function test_format_value_array_format() {
$field = $this->get_field( array( 'return_format' => 'array' ) );

$result = $this->field_instance->format_value( 'right', $this->post_id, $field );

$this->assertIsArray( $result );
$this->assertArrayHasKey( 'value', $result );
$this->assertArrayHasKey( 'label', $result );
$this->assertEquals( 'right', $result['value'] );
$this->assertEquals( 'Right', $result['label'] );
}

/**
* Test format_value returns empty string for empty.
*/
public function test_format_value_empty() {
$field = $this->get_field();

$result = $this->field_instance->format_value( '', $this->post_id, $field );

$this->assertSame( '', $result );
}

/**
* Test format_value_for_rest returns the raw value.
*
* Note: Button group doesn't override format_value_for_rest, so it inherits
* the base class behavior which returns the raw value unchanged.
* The return_format setting only affects format_value, not REST output.
*/
public function test_format_value_for_rest() {
$field = $this->get_field( array( 'return_format' => 'value' ) );

$rest_result = $this->field_instance->format_value_for_rest( 'left', $this->post_id, $field );

// REST returns raw value, not formatted value.
$this->assertEquals( 'left', $rest_result );
}

/**
* Test get_rest_schema returns valid schema.
*/
public function test_get_rest_schema() {
$field = $this->get_field();

$schema = $this->field_instance->get_rest_schema( $field );

$this->assertIsArray( $schema );
$this->assertContains( 'string', $schema['type'] );
}

/**
* Test load_value returns stored value.
*/
public function test_load_value() {
$field = $this->get_field();

$result = $this->field_instance->load_value( 'right', $this->post_id, $field );

$this->assertEquals( 'right', $result );
}

/**
* Test allow_null option.
*/
public function test_allow_null() {
$field = $this->get_field( array( 'allow_null' => 1 ) );

$result = $this->field_instance->format_value( '', $this->post_id, $field );

$this->assertSame( '', $result );
}

/**
* Test format_value with unknown choice returns value.
*/
public function test_format_value_unknown_choice() {
$field = $this->get_field( array( 'return_format' => 'label' ) );

$result = $this->field_instance->format_value( 'unknown', $this->post_id, $field );

// Unknown choices should return the value itself.
$this->assertEquals( 'unknown', $result );
}
}
Loading
Loading