File "WPFormsControllerTest.php"
Full Path: /home/buyiwexj/public_html/wp-content/plugins/extendify/tests/Integration/QuickEdit/Controllers/WPFormsControllerTest.php
File size: 11.96 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace Extendify\Tests\Integration\QuickEdit\Controllers;
use Extendify\QuickEdit\Controllers\WPFormsController;
use WP_UnitTestCase;
class WPFormsControllerTest extends WP_UnitTestCase
{
public function setUp(): void
{
parent::setUp();
if (!defined('EXTENDIFY_REQUIRED_CAPABILITY')) {
define('EXTENDIFY_REQUIRED_CAPABILITY', 'manage_options');
}
// Mirror WPForms' production CPT registration (class-form.php) so
// any code that checks edit_post against a wpforms post fails here
// exactly the way it fails on a real site — map_meta_cap=false means
// edit_post resolves to the primitive cap edit_wpforms_form, which
// admins don't hold via core. A bare register_post_type('wpforms')
// silently grants admins edit_post and hides the regression.
register_post_type('wpforms', [
'capability_type' => 'wpforms_form',
'map_meta_cap' => false,
'supports' => ['title', 'author', 'revisions'],
]);
$this->loginAsAdmin();
}
public function test_permission_callback_requires_admin_capability()
{
wp_set_current_user(0);
$this->assertFalse(WPFormsController::permissionCallback());
$sub = self::factory()->user->create(['role' => 'subscriber']);
wp_set_current_user($sub);
$this->assertFalse(WPFormsController::permissionCallback());
$editor = self::factory()->user->create(['role' => 'editor']);
wp_set_current_user($editor);
$this->assertFalse(WPFormsController::permissionCallback());
$admin = self::factory()->user->create(['role' => 'administrator']);
wp_set_current_user($admin);
$this->assertTrue(WPFormsController::permissionCallback());
}
public function test_get_without_form_id_returns_400()
{
$res = WPFormsController::handleGet($this->getRequest([]));
$this->assertSame(400, $res->get_status());
$this->assertSame('form_id + field_id required', $res->get_data()['error']);
}
public function test_get_with_missing_field_id_returns_400()
{
$res = WPFormsController::handleGet($this->getRequest(['form_id' => 1]));
$this->assertSame(400, $res->get_status());
}
public function test_get_with_non_wpforms_post_returns_404()
{
$postId = self::factory()->post->create();
$res = WPFormsController::handleGet($this->getRequest([
'form_id' => $postId,
'field_id' => 1,
]));
$this->assertSame(404, $res->get_status());
$this->assertSame('wpforms form not found', $res->get_data()['error']);
}
public function test_get_with_unparseable_form_json_returns_404()
{
$formId = $this->createForm('not valid json');
$res = WPFormsController::handleGet($this->getRequest([
'form_id' => $formId,
'field_id' => 1,
]));
$this->assertSame(404, $res->get_status());
$this->assertSame('wpforms form content is not valid JSON', $res->get_data()['error']);
}
public function test_get_missing_field_returns_404()
{
$formId = $this->createForm(wp_json_encode(['fields' => []]));
$res = WPFormsController::handleGet($this->getRequest([
'form_id' => $formId,
'field_id' => 7,
]));
$this->assertSame(404, $res->get_status());
$this->assertSame('field not found', $res->get_data()['error']);
}
public function test_get_returns_four_editable_props_for_a_field()
{
$formId = $this->createForm(wp_json_encode([
'fields' => [
3 => [
'id' => 3,
'type' => 'text',
'label' => 'Your Name',
'placeholder' => 'Enter name',
'description' => 'Required field',
'required' => '1',
// Extra props must be ignored by GET.
'choices' => [['label' => 'a']],
'conditional_logic' => ['x' => 'y'],
'default_value' => 'foo',
],
],
]));
$res = WPFormsController::handleGet($this->getRequest([
'form_id' => $formId,
'field_id' => 3,
]));
$this->assertSame(200, $res->get_status());
$data = $res->get_data();
$this->assertSame([
'id', 'type', 'label', 'placeholder', 'required', 'description',
], array_keys($data));
$this->assertSame(3, $data['id']);
$this->assertSame('text', $data['type']);
$this->assertSame('Your Name', $data['label']);
$this->assertSame('Enter name', $data['placeholder']);
$this->assertTrue($data['required']);
$this->assertSame('Required field', $data['description']);
}
public function test_get_decodes_required_truthy_strings_and_falsy()
{
$formId = $this->createForm(wp_json_encode([
'fields' => [
1 => ['id' => 1, 'required' => ''],
2 => ['id' => 2, 'required' => 'yes'],
3 => ['id' => 3, 'required' => true],
],
]));
$this->assertFalse($this->getField($formId, 1)->get_data()['required']);
$this->assertTrue($this->getField($formId, 2)->get_data()['required']);
$this->assertTrue($this->getField($formId, 3)->get_data()['required']);
}
public function test_post_requires_form_id_field_id_and_changes()
{
$res = WPFormsController::handlePost($this->postRequest([
'form_id' => 1,
'field_id' => 1,
]));
$this->assertSame(400, $res->get_status());
$this->assertSame('form_id, field_id, changes required', $res->get_data()['error']);
}
public function test_post_updates_label_placeholder_description_required()
{
$formId = $this->createForm(wp_json_encode([
'fields' => [
5 => [
'id' => 5,
'type' => 'text',
'label' => 'Old',
'placeholder' => 'old',
'description' => 'old',
'required' => '',
],
],
]));
$res = WPFormsController::handlePost($this->postRequest([
'form_id' => $formId,
'field_id' => 5,
'changes' => [
'label' => 'New Label',
'placeholder' => 'new',
'description' => '<strong>desc</strong>',
'required' => true,
],
]));
$this->assertSame(200, $res->get_status());
$field = $this->reloadField($formId, 5);
$this->assertSame('New Label', $field['label']);
$this->assertSame('new', $field['placeholder']);
$this->assertSame('<strong>desc</strong>', $field['description']);
// existing required was a string ⇒ preserve string shape.
$this->assertSame('1', $field['required']);
}
public function test_post_required_preserves_bool_shape_when_existing_was_bool()
{
$formId = $this->createForm(wp_json_encode([
'fields' => [1 => ['id' => 1, 'required' => false]],
]));
WPFormsController::handlePost($this->postRequest([
'form_id' => $formId,
'field_id' => 1,
'changes' => ['required' => '1'],
]));
$this->assertSame(true, $this->reloadField($formId, 1)['required']);
}
public function test_post_does_not_drop_choices_validation_conditional_logic_defaults()
{
$formId = $this->createForm(wp_json_encode([
'fields' => [
2 => [
'id' => 2,
'type' => 'select',
'label' => 'Pick',
'choices' => [['label' => 'A'], ['label' => 'B']],
'conditional_logic' => ['enabled' => true],
'default_value' => 'A',
'validation' => ['min' => 1],
],
],
]));
WPFormsController::handlePost($this->postRequest([
'form_id' => $formId,
'field_id' => 2,
'changes' => ['label' => 'Pick One'],
]));
$field = $this->reloadField($formId, 2);
$this->assertSame('Pick One', $field['label']);
$this->assertSame([['label' => 'A'], ['label' => 'B']], $field['choices']);
$this->assertSame(['enabled' => true], $field['conditional_logic']);
$this->assertSame('A', $field['default_value']);
$this->assertSame(['min' => 1], $field['validation']);
}
public function test_post_with_unknown_change_keys_silently_drops_them()
{
$formId = $this->createForm(wp_json_encode([
'fields' => [1 => ['id' => 1, 'label' => 'L']],
]));
$res = WPFormsController::handlePost($this->postRequest([
'form_id' => $formId,
'field_id' => 1,
'changes' => ['bogus' => 'x', 'choices' => [['label' => 'evil']]],
]));
$this->assertSame(200, $res->get_status());
$field = $this->reloadField($formId, 1);
$this->assertSame('L', $field['label']);
$this->assertArrayNotHasKey('bogus', $field);
$this->assertArrayNotHasKey('choices', $field);
}
public function test_post_sanitizes_label_strips_script()
{
$formId = $this->createForm(wp_json_encode([
'fields' => [1 => ['id' => 1, 'label' => '']],
]));
WPFormsController::handlePost($this->postRequest([
'form_id' => $formId,
'field_id' => 1,
'changes' => ['label' => '<script>x</script>Hi'],
]));
$this->assertSame('Hi', $this->reloadField($formId, 1)['label']);
}
public function test_post_returns_404_for_unknown_field()
{
$formId = $this->createForm(wp_json_encode(['fields' => [1 => ['id' => 1]]]));
$res = WPFormsController::handlePost($this->postRequest([
'form_id' => $formId,
'field_id' => 999,
'changes' => ['label' => 'x'],
]));
$this->assertSame(404, $res->get_status());
}
public function test_init_hooks_registerRoutes_into_rest_api_init()
{
remove_all_filters('rest_api_init');
WPFormsController::init();
$this->assertNotFalse(
has_action('rest_api_init', [WPFormsController::class, 'registerRoutes'])
);
}
private function createForm(string $jsonContent): int
{
return self::factory()->post->create([
'post_type' => 'wpforms',
'post_status' => 'publish',
'post_content' => wp_slash($jsonContent),
]);
}
private function getField(int $formId, int $fieldId): \WP_REST_Response
{
return WPFormsController::handleGet($this->getRequest([
'form_id' => $formId,
'field_id' => $fieldId,
]));
}
private function reloadField(int $formId, int $fieldId): array
{
$form = json_decode(get_post($formId)->post_content, true);
return $form['fields'][$fieldId];
}
private function getRequest(array $params): \WP_REST_Request
{
$req = new \WP_REST_Request('GET', '/extendify/v1/quick-edit/wpforms');
foreach ($params as $k => $v) {
$req->set_param($k, $v);
}
return $req;
}
private function postRequest(array $body): \WP_REST_Request
{
$req = new \WP_REST_Request('POST', '/extendify/v1/quick-edit/wpforms');
$req->set_header('Content-Type', 'application/json');
$req->set_body(wp_json_encode($body));
return $req;
}
private function loginAsAdmin(): void
{
$admin = self::factory()->user->create(['role' => 'administrator']);
wp_set_current_user($admin);
}
}