true, 'result' => [ 'id' => 'zone_mock_' . md5($hostname), 'name_servers' => ['ada.ns.cloudflare.com', 'bob.ns.cloudflare.com'], ], ]; } public function getZone($zoneId) { return [ 'ok' => true, 'result' => [ 'id' => $zoneId, 'status' => $this->zoneStatus, 'name_servers' => ['ada.ns.cloudflare.com', 'bob.ns.cloudflare.com'], ], ]; } public function deleteZone($zoneId) { $this->deleteCalled = true; return ['ok' => true, 'result' => ['id' => $zoneId]]; } public function upsertARecord($zoneId, $fqdn, $ip, $proxied = true) { $this->upsertCalls[] = compact('zoneId', 'fqdn', 'ip', 'proxied'); return ['ok' => true, 'result' => ['id' => 'rec_' . md5($fqdn)]]; } public function setSslFlexible($zoneId) { return ['ok' => true]; } public function setAlwaysHttps($zoneId) { return ['ok' => true]; } } $tests = []; $host = 'cf-mock-' . substr(md5((string) microtime(true)), 0, 8) . '.test'; try { $pdo = DomainRepository::pdo(); DomainRepository::ensureTable($pdo); // 未启用 CF:添加后 cf_status=local CloudflareConfig::clearTestOverrides(); DomainProvisioningService::clearClientOverride(); $addLocal = DomainProvisioningService::provisionOnAdd($pdo, $host); $rowLocal = DomainRepository::findById($pdo, (int) ($addLocal['id'] ?? 0)); $tests['add_local_cf_status'] = ($addLocal['ok'] ?? false) === true && ($addLocal['cf_status'] ?? '') === 'local' && ($rowLocal['cf_status'] ?? '') === 'local'; DomainRepository::deleteById($pdo, (int) $addLocal['id']); // Mock:pending_ns → ready CloudflareConfig::setTestOverrides(['enabled' => true, 'server_ip' => '203.0.113.10']); $mock = new MockCloudflareClient(); DomainProvisioningService::setClientOverride($mock); $addCf = DomainProvisioningService::provisionOnAdd($pdo, $host); $domainId = (int) ($addCf['id'] ?? 0); $tests['add_cf_pending_ns'] = ($addCf['ok'] ?? false) === true && ($addCf['cf_status'] ?? '') === 'pending_ns' && count($addCf['nameservers'] ?? []) === 2; $pending = DomainProvisioningService::checkAndProvision($pdo, $domainId); $tests['check_pending_ns'] = ($pending['ok'] ?? false) === true && ($pending['status'] ?? '') === 'pending_ns'; $mock->zoneStatus = 'active'; $ready = DomainProvisioningService::checkAndProvision($pdo, $domainId); $rowReady = DomainRepository::findById($pdo, $domainId); $tests['check_ready'] = ($ready['ok'] ?? false) === true && ($ready['status'] ?? '') === 'ready' && ($rowReady['cf_status'] ?? '') === 'ready' && count($mock->upsertCalls) === 2; $del = DomainProvisioningService::deleteWithCloudflare($pdo, $domainId); $tests['delete_calls_zone'] = ($del['ok'] ?? false) === true && $mock->deleteCalled === true; $tests['delete_row_gone'] = DomainRepository::findById($pdo, $domainId) === null; } catch (Throwable $e) { $tests['exception'] = false; $tests['error'] = $e->getMessage(); } finally { CloudflareConfig::clearTestOverrides(); DomainProvisioningService::clearClientOverride(); } $ok = !in_array(false, $tests, true) && !isset($tests['error']); echo json_encode(['ok' => $ok, 'tests' => $tests], JSON_UNESCAPED_UNICODE) . "\n";