Skip to content

Commit 78e8f9c

Browse files
authored
test: add template_id checkout validation tests and fix Dashboard_Widgets_Test (#801)
Add 7 unit tests covering the template_selection → template_id validation mapping fix from PR #800: - template_selection required attribute maps to template_id rule key - min:1 guard rejects template_id=0 during checkout - positive template_id passes validation - no min:1 added when template_selection field is absent - template_id=0 allowed with base rule (admin/network context) - non-template required fields still map to themselves Fix Dashboard_Widgets_Test failure caused by PR #785 adding is_network_admin() guard to enqueue_scripts(). The test now uses set_current_screen('dashboard-network') to simulate the network admin context. Also adds a new test confirming the per-site dashboard does NOT enqueue wu-activity-stream.
1 parent cbeaa88 commit 78e8f9c

File tree

2 files changed

+238
-2
lines changed

2 files changed

+238
-2
lines changed

tests/WP_Ultimo/Checkout/Checkout_Test.php

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4560,6 +4560,198 @@ public function test_get_checkout_variables_with_discount_code_in_order(): void
45604560
unset($_REQUEST['discount_code']);
45614561
}
45624562

4563+
// -------------------------------------------------------------------------
4564+
// template_id validation — field_to_rule_key mapping (PR #800 fix)
4565+
// -------------------------------------------------------------------------
4566+
4567+
/**
4568+
* Test get_validation_rules maps template_selection required to template_id rule.
4569+
*
4570+
* The template_selection signup field has force_attributes() { required: true },
4571+
* but its POST key is template_id (not template_selection). Before PR #800
4572+
* the required rule was applied to the wrong key.
4573+
*/
4574+
public function test_get_validation_rules_maps_template_selection_required_to_template_id(): void {
4575+
4576+
$checkout = Checkout::get_instance();
4577+
$checkout->step = [
4578+
'fields' => [
4579+
['id' => 'template_selection', 'required' => true],
4580+
],
4581+
];
4582+
$checkout->steps = [];
4583+
$checkout->step_name = null;
4584+
4585+
unset($_REQUEST['pre-flight'], $_REQUEST['checkout_form']);
4586+
4587+
$rules = $checkout->get_validation_rules();
4588+
4589+
// template_id rule must include 'required' (mapped from template_selection)
4590+
$this->assertArrayHasKey('template_id', $rules);
4591+
$this->assertStringContainsString('required', $rules['template_id']);
4592+
4593+
// template_selection should NOT have its own rule entry
4594+
$this->assertArrayNotHasKey('template_selection', $rules);
4595+
}
4596+
4597+
/**
4598+
* Test get_validation_rules adds min:1 to template_id when required.
4599+
*
4600+
* Rakit's required rule accepts integer 0 as "present", so min:1 is
4601+
* needed to reject template_id=0 during checkout.
4602+
*/
4603+
public function test_get_validation_rules_adds_min_1_to_template_id(): void {
4604+
4605+
$checkout = Checkout::get_instance();
4606+
$checkout->step = [
4607+
'fields' => [
4608+
['id' => 'template_selection', 'required' => true],
4609+
],
4610+
];
4611+
$checkout->steps = [];
4612+
$checkout->step_name = null;
4613+
4614+
unset($_REQUEST['pre-flight'], $_REQUEST['checkout_form']);
4615+
4616+
$rules = $checkout->get_validation_rules();
4617+
4618+
$this->assertStringContainsString('min:1', $rules['template_id']);
4619+
}
4620+
4621+
/**
4622+
* Test validate rejects template_id=0 when template_selection is required.
4623+
*
4624+
* This is the core regression test: a checkout with a required template
4625+
* selection field must not allow template_id=0 through validation.
4626+
*/
4627+
public function test_validate_rejects_template_id_zero_when_required(): void {
4628+
4629+
$checkout = Checkout::get_instance();
4630+
$checkout->step = [
4631+
'fields' => [
4632+
['id' => 'template_selection', 'required' => true],
4633+
],
4634+
];
4635+
$checkout->steps = [];
4636+
$checkout->step_name = null;
4637+
4638+
$this->ensure_session($checkout);
4639+
4640+
$_REQUEST['template_id'] = 0;
4641+
4642+
unset($_REQUEST['pre-flight'], $_REQUEST['checkout_form']);
4643+
4644+
$rules = $checkout->get_validation_rules();
4645+
$result = $checkout->validate($rules);
4646+
4647+
$this->assertInstanceOf(\WP_Error::class, $result, 'template_id=0 should fail validation when template_selection is required');
4648+
4649+
unset($_REQUEST['template_id']);
4650+
}
4651+
4652+
/**
4653+
* Test validate accepts a valid non-zero template_id when required.
4654+
*
4655+
* Uses min:1 rule directly to verify a positive integer passes.
4656+
*/
4657+
public function test_validate_accepts_positive_template_id(): void {
4658+
4659+
$checkout = Checkout::get_instance();
4660+
$checkout->step = ['fields' => []];
4661+
$checkout->steps = [];
4662+
$checkout->step_name = null;
4663+
4664+
$this->ensure_session($checkout);
4665+
4666+
$_REQUEST['template_id'] = 5;
4667+
4668+
// min:1 should pass for value 5
4669+
$result = $checkout->validate(['template_id' => 'integer|min:1']);
4670+
4671+
$this->assertTrue($result);
4672+
4673+
unset($_REQUEST['template_id']);
4674+
}
4675+
4676+
/**
4677+
* Test get_validation_rules does NOT add min:1 to template_id when
4678+
* template_selection is absent (no template step on the form).
4679+
*
4680+
* This ensures admin/API paths that don't include a template_selection
4681+
* field are not affected by the checkout-specific guard.
4682+
*/
4683+
public function test_get_validation_rules_no_min_1_without_template_selection_field(): void {
4684+
4685+
$checkout = Checkout::get_instance();
4686+
$checkout->step = [
4687+
'fields' => [
4688+
['id' => 'email_address', 'required' => true],
4689+
],
4690+
];
4691+
$checkout->steps = [];
4692+
$checkout->step_name = null;
4693+
4694+
unset($_REQUEST['pre-flight'], $_REQUEST['checkout_form']);
4695+
4696+
$rules = $checkout->get_validation_rules();
4697+
4698+
// template_id should still have its base rule but NOT min:1
4699+
$this->assertArrayHasKey('template_id', $rules);
4700+
$this->assertStringNotContainsString('min:1', $rules['template_id']);
4701+
}
4702+
4703+
/**
4704+
* Test base template_id rule (integer|site_template) allows 0
4705+
* when no template_selection field is present.
4706+
*
4707+
* This confirms admin/network site creation can still use template_id=0.
4708+
*/
4709+
public function test_validate_allows_template_id_zero_without_template_selection_field(): void {
4710+
4711+
$checkout = Checkout::get_instance();
4712+
$checkout->step = ['fields' => []];
4713+
$checkout->steps = [];
4714+
$checkout->step_name = null;
4715+
4716+
$this->ensure_session($checkout);
4717+
4718+
$_REQUEST['template_id'] = 0;
4719+
4720+
// Base rule without required or min:1
4721+
$result = $checkout->validate(['template_id' => 'integer|site_template']);
4722+
4723+
$this->assertTrue($result, 'template_id=0 should pass with base rule (admin/network context)');
4724+
4725+
unset($_REQUEST['template_id']);
4726+
}
4727+
4728+
/**
4729+
* Test that a non-template required field still maps to itself.
4730+
*
4731+
* Ensures the field_to_rule_key mapping only affects template_selection
4732+
* and does not break other required fields.
4733+
*/
4734+
public function test_get_validation_rules_non_template_required_field_maps_to_itself(): void {
4735+
4736+
$checkout = Checkout::get_instance();
4737+
$checkout->step = [
4738+
'fields' => [
4739+
['id' => 'site_title', 'required' => true],
4740+
],
4741+
];
4742+
$checkout->steps = [];
4743+
$checkout->step_name = null;
4744+
4745+
unset($_REQUEST['pre-flight'], $_REQUEST['checkout_form']);
4746+
4747+
$rules = $checkout->get_validation_rules();
4748+
4749+
$this->assertArrayHasKey('site_title', $rules);
4750+
$this->assertStringContainsString('required', $rules['site_title']);
4751+
// min:1 should NOT be added to non-template fields
4752+
$this->assertStringNotContainsString('min:1', $rules['site_title']);
4753+
}
4754+
45634755
// -------------------------------------------------------------------------
45644756
// Teardown
45654757
// -------------------------------------------------------------------------

tests/WP_Ultimo/Dashboard_Widgets_Test.php

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,11 @@ public function test_enqueue_scripts_skips_non_index_page(): void {
114114
}
115115

116116
/**
117-
* Test enqueue_scripts enqueues activity-stream with correct deps on index.php.
117+
* Test enqueue_scripts enqueues activity-stream on the network admin index.php.
118+
*
119+
* Since PR #785, enqueue_scripts() guards with is_network_admin() so the
120+
* activity-stream assets are only loaded on the network dashboard — not
121+
* the per-site dashboard. The test must simulate the network admin context.
118122
*/
119123
public function test_enqueue_scripts_enqueues_activity_stream_on_index(): void {
120124

@@ -129,6 +133,9 @@ public function test_enqueue_scripts_enqueues_activity_stream_on_index(): void {
129133
$wp_scripts->done = [];
130134
}
131135

136+
// Simulate the network admin so is_network_admin() returns true.
137+
set_current_screen('dashboard-network');
138+
132139
// Ensure wu-functions is registered so the dependency chain resolves.
133140
\WP_Ultimo\Scripts::get_instance()->register_default_scripts();
134141

@@ -137,7 +144,7 @@ public function test_enqueue_scripts_enqueues_activity_stream_on_index(): void {
137144

138145
$this->assertTrue(
139146
wp_script_is('wu-activity-stream', 'enqueued'),
140-
'wu-activity-stream should be enqueued on index.php'
147+
'wu-activity-stream should be enqueued on the network admin index.php'
141148
);
142149

143150
// Verify wu-functions and moment are declared dependencies.
@@ -152,6 +159,43 @@ public function test_enqueue_scripts_enqueues_activity_stream_on_index(): void {
152159
$pagenow = $original;
153160
}
154161

162+
/**
163+
* Test enqueue_scripts does NOT enqueue activity-stream on per-site dashboard.
164+
*
165+
* PR #785 added an is_network_admin() guard to prevent the Vue
166+
* "Cannot find element: #activity-stream-content" console error
167+
* on the per-site /wp-admin/index.php.
168+
*/
169+
public function test_enqueue_scripts_skips_activity_stream_on_per_site_dashboard(): void {
170+
171+
global $pagenow, $wp_scripts;
172+
173+
$original = $pagenow;
174+
$original_queue = isset($wp_scripts) ? $wp_scripts->queue : [];
175+
$pagenow = 'index.php';
176+
177+
if (isset($wp_scripts)) {
178+
$wp_scripts->queue = [];
179+
$wp_scripts->done = [];
180+
}
181+
182+
// Simulate the per-site dashboard (not network admin).
183+
set_current_screen('dashboard');
184+
185+
$instance = $this->get_instance();
186+
$instance->enqueue_scripts();
187+
188+
$this->assertFalse(
189+
wp_script_is('wu-activity-stream', 'enqueued'),
190+
'wu-activity-stream should NOT be enqueued on the per-site dashboard'
191+
);
192+
193+
if (isset($wp_scripts)) {
194+
$wp_scripts->queue = $original_queue;
195+
}
196+
$pagenow = $original;
197+
}
198+
155199
/**
156200
* Test get_registered_dashboard_widgets returns array.
157201
*

0 commit comments

Comments
 (0)