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
22 changes: 11 additions & 11 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ Overall coverage: **35%** (20,720 / 59,212 statements). 90 files at 0% coverage.

### Priority 1 — Business-Critical Code (low coverage, high risk)

- [ ] t453 test(checkout): write unit tests for Checkout class (inc/checkout/class-checkout.php — 7.9% coverage, 960 uncovered stmts) #testing #auto-dispatch ~6h
- [ ] t454 test(cart): improve Cart test coverage (inc/checkout/class-cart.php — 61.1% coverage, 382 uncovered stmts) #testing #auto-dispatch ~4h
- [ ] t453 test(checkout): write unit tests for Checkout class (inc/checkout/class-checkout.php — 7.9% coverage, 960 uncovered stmts) #testing #auto-dispatch ~6h ref:GH#555
- [ ] t454 test(cart): improve Cart test coverage (inc/checkout/class-cart.php — 61.1% coverage, 382 uncovered stmts) #testing #auto-dispatch ~4h ref:GH#556
- [ ] t455 test(stripe): write unit tests for Base_Stripe_Gateway (inc/gateways/class-base-stripe-gateway.php — 28.6% coverage, 1093 uncovered stmts) #testing ~8h
- [ ] t456 test(stripe): improve Stripe_Gateway test coverage (inc/gateways/class-stripe-gateway.php — 55% coverage, 200 uncovered stmts) #testing ~4h
- [ ] t457 test(paypal): write unit tests for PayPal_Gateway (inc/gateways/class-paypal-gateway.php — 1.1% coverage, 783 uncovered stmts) #testing ~6h
- [ ] t458 test(paypal): improve PayPal_REST_Gateway test coverage (inc/gateways/class-paypal-rest-gateway.php — 29.8% coverage, 683 uncovered stmts) #testing ~5h
- [ ] t459 test(paypal): write tests for PayPal_OAuth_Handler (inc/gateways/class-paypal-oauth-handler.php — 15% coverage, 238 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#549
- [ ] t460 test(gateway): improve Gateway_Manager test coverage (inc/managers/class-gateway-manager.php — 34.7% coverage, 177 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#550
- [ ] t461 test(checkout-pages): improve Checkout_Pages test coverage (inc/checkout/class-checkout-pages.php — 33.7% coverage, 203 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#551
- [x] t459 test(paypal): write tests for PayPal_OAuth_Handler (inc/gateways/class-paypal-oauth-handler.php — 15% coverage, 238 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#549 pr:#554 completed:2026-03-27
- [x] t460 test(gateway): improve Gateway_Manager test coverage (inc/managers/class-gateway-manager.php — 34.7% coverage, 177 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#550 pr:#552 completed:2026-03-27
- [x] t461 test(checkout-pages): improve Checkout_Pages test coverage (inc/checkout/class-checkout-pages.php — 33.7% coverage, 203 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#551 pr:#553 completed:2026-03-27

### Priority 2 — Core Domain Logic (moderate coverage gaps)

- [ ] t462 test(site-manager): improve Site_Manager test coverage (inc/managers/class-site-manager.php — 23.5% coverage, 433 uncovered stmts) #testing #auto-dispatch ~4h
- [ ] t463 test(domain-manager): improve DNS_Record_Manager test coverage (inc/managers/class-dns-record-manager.php — 14.4% coverage, 393 uncovered stmts) #testing #auto-dispatch ~4h
- [ ] t464 test(event-manager): improve Event_Manager test coverage (inc/managers/class-event-manager.php — 33% coverage, 240 uncovered stmts) #testing #auto-dispatch ~3h
- [ ] t465 test(form-manager): improve Form_Manager test coverage (inc/managers/class-form-manager.php — 9.7% coverage, 251 uncovered stmts) #testing #auto-dispatch ~3h
- [ ] t466 test(notes-manager): improve Notes_Manager test coverage (inc/managers/class-notes-manager.php — 9.9% coverage, 283 uncovered stmts) #testing #auto-dispatch ~3h
- [ ] t462 test(site-manager): improve Site_Manager test coverage (inc/managers/class-site-manager.php — 23.5% coverage, 433 uncovered stmts) #testing #auto-dispatch ~4h ref:GH#557
- [ ] t463 test(domain-manager): improve DNS_Record_Manager test coverage (inc/managers/class-dns-record-manager.php — 14.4% coverage, 393 uncovered stmts) #testing #auto-dispatch ~4h ref:GH#558
- [ ] t464 test(event-manager): improve Event_Manager test coverage (inc/managers/class-event-manager.php — 33% coverage, 240 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#559
- [ ] t465 test(form-manager): improve Form_Manager test coverage (inc/managers/class-form-manager.php — 9.7% coverage, 251 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#560
- [ ] t466 test(notes-manager): improve Notes_Manager test coverage (inc/managers/class-notes-manager.php — 9.9% coverage, 283 uncovered stmts) #testing #auto-dispatch ~3h ref:GH#561
- [ ] t467 test(sso): improve SSO test coverage (inc/sso/class-sso.php — 36.7% coverage, 210 uncovered stmts) #testing #auto-dispatch ~4h
- [ ] t468 test(domain-mapping): write tests for Domain_Mapping (inc/class-domain-mapping.php — 13.8% coverage, 168 uncovered stmts) #testing #auto-dispatch ~3h
- [ ] t469 test(membership-functions): improve membership function tests (inc/functions/membership.php — 28.3% coverage, 152 uncovered stmts) #testing #auto-dispatch ~2h
Expand Down Expand Up @@ -73,4 +73,4 @@ Overall coverage: **35%** (20,720 / 59,212 statements). 90 files at 0% coverage.

### Fix: Test suite exits early at 56%

- [ ] t495 fix(tests): Form_Manager_Test::test_handle_model_delete_form_requires_confirmation calls exit() killing test runner at test 2533/4411 #bug #auto-dispatch ~1h
- [ ] t495 fix(tests): Form_Manager_Test::test_handle_model_delete_form_requires_confirmation calls exit() killing test runner at test 2533/4411 #bug #auto-dispatch ~1h ref:GH#562
119 changes: 119 additions & 0 deletions tests/WP_Ultimo/Managers/Form_Manager_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -1073,4 +1073,123 @@ public function test_init_registers_hooks(): void {
$this->assertNotFalse(has_action('wu_ajax_wu_form_handler', [$manager, 'handle_form']));
$this->assertNotFalse(has_action('wu_register_forms', [$manager, 'register_action_forms']));
}

// =========================================================================
// security_checks
// =========================================================================

/**
* Test security_checks calls wp_die(0) when request is not an AJAX request.
*
* security_checks() checks $_SERVER['HTTP_X_REQUESTED_WITH'] for the value
* 'xmlhttprequest'. When absent (or wrong), it calls wp_die(0).
*
* wp_die() in non-AJAX context uses wp_die_handler (not wp_die_ajax_handler).
* We install a wp_die_handler filter that throws WPDieException so PHPUnit
* can catch it instead of the process terminating.
*/
public function test_security_checks_dies_for_non_ajax_request(): void {

$manager = $this->get_manager_instance();

// Ensure HTTP_X_REQUESTED_WITH is absent (non-AJAX request).
unset($_SERVER['HTTP_X_REQUESTED_WITH']);

$die_handler = function () {
return function ( $message ) {
throw new \WPDieException( (string) $message );
};
};

add_filter('wp_die_handler', $die_handler, 1);

$exception_caught = false;

try {
$manager->security_checks();
} catch (\WPDieException $e) {
$exception_caught = true;
}

remove_filter('wp_die_handler', $die_handler, 1);

$this->assertTrue($exception_caught, 'security_checks() should call wp_die() for non-AJAX requests');
}

/**
* Test security_checks passes through when request is AJAX and form exists with capability.
*
* When HTTP_X_REQUESTED_WITH is 'XMLHttpRequest', the form is registered,
* and the current user has the required capability, security_checks() returns
* without calling wp_die() or display_form_unavailable().
*/
public function test_security_checks_passes_for_valid_ajax_request(): void {

$manager = $this->get_manager_instance();

// Register a form with 'read' capability (all users have this).
$manager->register_form(
'security_test_form_xyz',
[
'capability' => 'read',
'render' => '__return_empty_string',
'handler' => '__return_false',
]
);

// Simulate AJAX request.
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
$_REQUEST['form'] = 'security_test_form_xyz';

// Grant the current user 'read' capability (WP_UnitTestCase sets up a user).
wp_set_current_user($this->factory()->user->create(['role' => 'subscriber']));

$exception_caught = false;

try {
$manager->security_checks();
} catch (\Exception $e) {
$exception_caught = true;
}

unset($_SERVER['HTTP_X_REQUESTED_WITH'], $_REQUEST['form']);

$this->assertFalse($exception_caught, 'security_checks() should not die for a valid AJAX request with capable user');
}

// =========================================================================
// default_bulk_action_handler — error path
// =========================================================================

/**
* Test default_bulk_action_handler sends json_error when process_bulk_action fails.
*
* process_bulk_action() returns WP_Error when the model function doesn't exist
* (e.g. model='nonexistent_model_xyz'). default_bulk_action_handler() should
* then call wp_send_json_error() with that WP_Error.
*/
public function test_default_bulk_action_handler_sends_error_when_process_fails(): void {

$manager = $this->get_manager_instance();

// Use a model that has no corresponding wu_get_* function.
$_REQUEST['bulk_action'] = 'delete';
$_REQUEST['model'] = 'nonexistent_model_xyz';
$_REQUEST['ids'] = '1,2,3';

$result = $this->run_in_ajax_context(
function () use ( $manager ) {
$manager->default_bulk_action_handler('delete', 'nonexistent_model_xyz', ['1', '2', '3']);
}
);

unset($_REQUEST['bulk_action'], $_REQUEST['model'], $_REQUEST['ids']);

$this->assertTrue($result['exception'], 'Should terminate via wp_die()');

$response = json_decode($result['output'], true);

$this->assertIsArray($response);
$this->assertFalse($response['success'], 'Should return error when process_bulk_action fails');
}
}
Loading