From 90386961438f06ff81110d8fc131c53fac2390e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Tue, 17 Mar 2026 09:43:03 +0800 Subject: [PATCH] test(platform-orders): guardrail scope=all tool forms must not carry filters --- ...eAllToolFormsShouldNotCarryFiltersTest.php | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tests/Feature/AdminPlatformOrderIndexScopeAllToolFormsShouldNotCarryFiltersTest.php diff --git a/tests/Feature/AdminPlatformOrderIndexScopeAllToolFormsShouldNotCarryFiltersTest.php b/tests/Feature/AdminPlatformOrderIndexScopeAllToolFormsShouldNotCarryFiltersTest.php new file mode 100644 index 0000000..6536cfa --- /dev/null +++ b/tests/Feature/AdminPlatformOrderIndexScopeAllToolFormsShouldNotCarryFiltersTest.php @@ -0,0 +1,70 @@ +seed(); + + $this->post('/admin/login', [ + 'email' => 'platform.admin@demo.local', + 'password' => 'Platform@123456', + ])->assertRedirect('/admin'); + } + + protected function assertScopeAllToolFormDoesNotCarryFilters(string $html, string $action): void + { + $pattern = sprintf( + '/]*method="post"[^>]*action="%s"[^>]*>(.*?)<\\/form>/si', + preg_quote($action, '/') + ); + + $matched = preg_match_all($pattern, $html, $matches); + $this->assertGreaterThan(0, $matched, '未找到表单:action=' . $action); + + $checked = 0; + foreach ($matches[0] as $formHtml) { + if (! str_contains($formHtml, 'name="scope" value="all"')) { + continue; + } + + $checked++; + + // scope=all 属于全量动作,不应承载“当前筛选集合”的字段,避免语义误导。 + $this->assertStringNotContainsString('name="status"', $formHtml, 'scope=all 表单不应透传 status:' . $action); + $this->assertStringNotContainsString('name="payment_status"', $formHtml, 'scope=all 表单不应透传 payment_status:' . $action); + $this->assertStringNotContainsString('name="sync_status"', $formHtml, 'scope=all 表单不应透传 sync_status:' . $action); + $this->assertStringNotContainsString('name="renewal_missing_subscription"', $formHtml, 'scope=all 表单不应透传 renewal_missing_subscription:' . $action); + $this->assertStringNotContainsString('name="refund_status"', $formHtml, 'scope=all 表单不应透传 refund_status:' . $action); + $this->assertStringNotContainsString('name="receipt_status"', $formHtml, 'scope=all 表单不应透传 receipt_status:' . $action); + $this->assertStringNotContainsString('name="created_from"', $formHtml, 'scope=all 表单不应透传 created_from:' . $action); + $this->assertStringNotContainsString('name="created_to"', $formHtml, 'scope=all 表单不应透传 created_to:' . $action); + } + + $this->assertGreaterThan(0, $checked, '未找到 scope=all 的工具表单:' . $action); + } + + public function test_platform_orders_index_scope_all_tool_forms_should_not_carry_filters(): void + { + $this->loginAsPlatformAdmin(); + + // 故意带很多筛选参数,确保如果 view 不小心透传,会被本用例抓住。 + $page = $this->get('/admin/platform-orders?status=pending&payment_status=paid&sync_status=unsynced&receipt_status=none&refund_status=has&renewal_missing_subscription=1&created_from=2026-03-01&created_to=2026-03-17'); + $page->assertOk(); + + $html = (string) $page->getContent(); + + $this->assertScopeAllToolFormDoesNotCarryFilters($html, '/admin/platform-orders/batch-activate-subscriptions'); + $this->assertScopeAllToolFormDoesNotCarryFilters($html, '/admin/platform-orders/batch-mark-paid-and-activate'); + $this->assertScopeAllToolFormDoesNotCarryFilters($html, '/admin/platform-orders/batch-mark-activated'); + $this->assertScopeAllToolFormDoesNotCarryFilters($html, '/admin/platform-orders/clear-sync-errors'); + $this->assertScopeAllToolFormDoesNotCarryFilters($html, '/admin/platform-orders/clear-bmpa-errors'); + } +}