diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 7276fb1..22efef6 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -32,7 +32,7 @@ jobs: with: php-version: ${{ matrix.php }} tools: composer:v2 - coverage: none + coverage: pcov env: update: true diff --git a/.gitignore b/.gitignore index d797add..b8e3bcf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ phpunit.xml .phpunit.cache .phpunit.result.cache +clover.xml +coverage-report composer.lock composer.phar vendor diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index f51d57b..728d7d2 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -4,7 +4,11 @@ ->in(__DIR__) ->exclude([ "local-test", + "docker", ".github", + ".vscode", + ".phpunit.cache", + "docs", "vendor", "node_modules" ]); diff --git a/README.md b/README.md index 0d4e1c6..c69bf43 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ This package requires **PHP >= 8.2** and supports **Laravel 12 and 13** (via `il | PHP | Laravel 12 | Laravel 13 | | --- | :---: | :---: | -| 8.2 | ✅ | — (Laravel 13 requires PHP >= 8.3) | +| 8.2 | ✅ | ❌ | | 8.3 | ✅ | ✅ | | 8.4 | ✅ | ✅ | | 8.5 | ✅ | ✅ | diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index 516a338..b234219 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -6,7 +6,10 @@ RUN apt-get update \ git \ unzip \ libzip-dev \ + $PHPIZE_DEPS \ && docker-php-ext-install zip \ + && pecl install pcov \ + && docker-php-ext-enable pcov \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/src/CloudflareServiceProvider.php b/src/CloudflareServiceProvider.php index 357c49f..1c66f13 100644 --- a/src/CloudflareServiceProvider.php +++ b/src/CloudflareServiceProvider.php @@ -30,9 +30,15 @@ private function setupConfig(): void if ($this->app instanceof LaravelApplication && $this->app->runningInConsole()) { $this->publishes([$source => $this->app->configPath('cloudflare.php')]); - } elseif ($this->app instanceof LumenApplication) { + } + // @codeCoverageIgnoreStart + // Lumen is discontinued and not an installed dependency here (only + // referenced for interface compatibility); this branch cannot be + // exercised without adding a dependency on an abandoned framework. + elseif ($this->app instanceof LumenApplication) { $this->app->configure('cloudflare'); } + // @codeCoverageIgnoreEnd $this->mergeConfigFrom($source, 'cloudflare'); } diff --git a/src/Configurations/Rules/CacheSettingsRule.php b/src/Configurations/Rules/CacheSettingsRule.php index c55f592..d3e2d38 100644 --- a/src/Configurations/Rules/CacheSettingsRule.php +++ b/src/Configurations/Rules/CacheSettingsRule.php @@ -12,6 +12,6 @@ class CacheSettingsRule extends Rule protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Configurations/Rules/ExecuteRule.php b/src/Configurations/Rules/ExecuteRule.php index ac9f95d..1e95b07 100644 --- a/src/Configurations/Rules/ExecuteRule.php +++ b/src/Configurations/Rules/ExecuteRule.php @@ -12,6 +12,6 @@ class ExecuteRule extends Rule protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Configurations/Rules/LogCustomFieldRule.php b/src/Configurations/Rules/LogCustomFieldRule.php index d2cf7ff..835bb35 100644 --- a/src/Configurations/Rules/LogCustomFieldRule.php +++ b/src/Configurations/Rules/LogCustomFieldRule.php @@ -12,6 +12,6 @@ class LogCustomFieldRule extends Rule protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Configurations/Rules/OriginRule.php b/src/Configurations/Rules/OriginRule.php index 0a14430..bb96bd5 100644 --- a/src/Configurations/Rules/OriginRule.php +++ b/src/Configurations/Rules/OriginRule.php @@ -12,6 +12,6 @@ class OriginRule extends Rule protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Configurations/Rules/RedirectRule.php b/src/Configurations/Rules/RedirectRule.php index 7eb7d86..4757152 100644 --- a/src/Configurations/Rules/RedirectRule.php +++ b/src/Configurations/Rules/RedirectRule.php @@ -12,6 +12,6 @@ class RedirectRule extends Rule protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Configurations/Rules/RewriteRule.php b/src/Configurations/Rules/RewriteRule.php index ab5d9cd..0f79d78 100644 --- a/src/Configurations/Rules/RewriteRule.php +++ b/src/Configurations/Rules/RewriteRule.php @@ -12,6 +12,6 @@ class RewriteRule extends Rule protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Configurations/Rules/ScoreRule.php b/src/Configurations/Rules/ScoreRule.php index 2474704..aee80f0 100644 --- a/src/Configurations/Rules/ScoreRule.php +++ b/src/Configurations/Rules/ScoreRule.php @@ -12,6 +12,6 @@ class ScoreRule extends Rule protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Configurations/Rules/ServeErrorRule.php b/src/Configurations/Rules/ServeErrorRule.php index bd99cbe..e84a70d 100644 --- a/src/Configurations/Rules/ServeErrorRule.php +++ b/src/Configurations/Rules/ServeErrorRule.php @@ -12,6 +12,6 @@ class ServeErrorRule extends Rule protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Configurations/Rules/SkipRule.php b/src/Configurations/Rules/SkipRule.php index 8a8eac9..7ec6dc8 100644 --- a/src/Configurations/Rules/SkipRule.php +++ b/src/Configurations/Rules/SkipRule.php @@ -40,6 +40,6 @@ public function disableLogging(): self protected function getActionParameters(): ?array { - + return null; } } diff --git a/src/Endpoints/Workers/Routes.php b/src/Endpoints/Workers/Routes.php index 37cf518..a2f6149 100644 --- a/src/Endpoints/Workers/Routes.php +++ b/src/Endpoints/Workers/Routes.php @@ -35,7 +35,7 @@ public function create(string $zoneId, array $values): ResponseInterface { $this->requiredParams(['pattern'], $values); - return $this->$this->getHttpClient()->post("/zones/{$zoneId}/workers/routes", $values); + return $this->getHttpClient()->post("/zones/{$zoneId}/workers/routes", $values); } /** diff --git a/src/Endpoints/Zones/PageRules.php b/src/Endpoints/Zones/PageRules.php index 72add30..06d5db0 100644 --- a/src/Endpoints/Zones/PageRules.php +++ b/src/Endpoints/Zones/PageRules.php @@ -55,7 +55,7 @@ public function create(string $zoneId, array|PageRule $values): ResponseInterfac $values = $values->toArray(); } - return $this->$this->getHttpClient()->post("/zones/{$zoneId}/pagerules", $values); + return $this->getHttpClient()->post("/zones/{$zoneId}/pagerules", $values); } /** diff --git a/src/Exceptions/MissingArgumentException.php b/src/Exceptions/MissingArgumentException.php index ef3d113..cf734c8 100644 --- a/src/Exceptions/MissingArgumentException.php +++ b/src/Exceptions/MissingArgumentException.php @@ -9,7 +9,7 @@ class MissingArgumentException extends \ErrorException * @param int $code * @param \Throwable|null $previous */ - public function __construct($required, int $code = 0, \Throwable $previous = null) + public function __construct($required, int $code = 0, ?\Throwable $previous = null) { if (is_string($required)) { $required = [$required]; diff --git a/src/HttpClient/Response.php b/src/HttpClient/Response.php index 4dfbc26..f3e564a 100644 --- a/src/HttpClient/Response.php +++ b/src/HttpClient/Response.php @@ -114,6 +114,9 @@ public function get($target, $key, $default = null) foreach ($key as $i => $segment) { unset($key[$i]); + // @codeCoverageIgnoreStart + // $key is always exploded into string segments above, so $segment + // can never actually be null or a float; kept as defensive guards. if (is_null($segment)) { return $target; } @@ -121,6 +124,7 @@ public function get($target, $key, $default = null) if (is_float($segment)) { $segment = (string) $segment; } + // @codeCoverageIgnoreEnd if (is_array($target) && array_key_exists($segment, $target)) { $target = $target[$segment]; diff --git a/test/Tests/Configurations/Rules/BlockRuleTest.php b/test/Tests/Configurations/Rules/BlockRuleTest.php new file mode 100644 index 0000000..28ef11a --- /dev/null +++ b/test/Tests/Configurations/Rules/BlockRuleTest.php @@ -0,0 +1,27 @@ + 'blocked'], 'application/json', 403); + + $array = $rule->toArray(); + + $this->assertSame('block', $array['action']); + $this->assertSame([ + 'response' => [ + 'content' => ['error' => 'blocked'], + 'content_type' => 'application/json', + 'status_code' => 403, + ], + ], $array['action_parameters']); + } +} diff --git a/test/Tests/Configurations/Rules/CacheSettingsRuleTest.php b/test/Tests/Configurations/Rules/CacheSettingsRuleTest.php new file mode 100644 index 0000000..1e1570d --- /dev/null +++ b/test/Tests/Configurations/Rules/CacheSettingsRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('set_cache_settings', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/ChallengeRuleTest.php b/test/Tests/Configurations/Rules/ChallengeRuleTest.php new file mode 100644 index 0000000..3951421 --- /dev/null +++ b/test/Tests/Configurations/Rules/ChallengeRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('challenge', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/CompressionRuleTest.php b/test/Tests/Configurations/Rules/CompressionRuleTest.php new file mode 100644 index 0000000..83fc737 --- /dev/null +++ b/test/Tests/Configurations/Rules/CompressionRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('compress_response', $array['action']); + $this->assertSame(['algorithms' => ['name' => 'gzip']], $array['action_parameters']); + } +} diff --git a/test/Tests/Configurations/Rules/ConfigRuleTest.php b/test/Tests/Configurations/Rules/ConfigRuleTest.php new file mode 100644 index 0000000..adbea57 --- /dev/null +++ b/test/Tests/Configurations/Rules/ConfigRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('set_config', $array['action']); + $this->assertSame(['ssl' => 'flexible'], $array['action_parameters']); + } +} diff --git a/test/Tests/Configurations/Rules/DDoSDynamicRuleTest.php b/test/Tests/Configurations/Rules/DDoSDynamicRuleTest.php new file mode 100644 index 0000000..c1135c2 --- /dev/null +++ b/test/Tests/Configurations/Rules/DDoSDynamicRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('ddos_dynamic', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/ExecuteRuleTest.php b/test/Tests/Configurations/Rules/ExecuteRuleTest.php new file mode 100644 index 0000000..d12bcb7 --- /dev/null +++ b/test/Tests/Configurations/Rules/ExecuteRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('execute', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/ForceConnectionCloseRuleTest.php b/test/Tests/Configurations/Rules/ForceConnectionCloseRuleTest.php new file mode 100644 index 0000000..bde97f1 --- /dev/null +++ b/test/Tests/Configurations/Rules/ForceConnectionCloseRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('force_connection_close', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/JSChallengeRuleTest.php b/test/Tests/Configurations/Rules/JSChallengeRuleTest.php new file mode 100644 index 0000000..8836495 --- /dev/null +++ b/test/Tests/Configurations/Rules/JSChallengeRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('js_challenge', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/LogCustomFieldRuleTest.php b/test/Tests/Configurations/Rules/LogCustomFieldRuleTest.php new file mode 100644 index 0000000..21c303e --- /dev/null +++ b/test/Tests/Configurations/Rules/LogCustomFieldRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('log_custom_field', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/LogRuleTest.php b/test/Tests/Configurations/Rules/LogRuleTest.php new file mode 100644 index 0000000..9ee3dcf --- /dev/null +++ b/test/Tests/Configurations/Rules/LogRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('log', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/ManagedChallengeRuleTest.php b/test/Tests/Configurations/Rules/ManagedChallengeRuleTest.php new file mode 100644 index 0000000..b92f351 --- /dev/null +++ b/test/Tests/Configurations/Rules/ManagedChallengeRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('managed_challenge', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/OriginRuleTest.php b/test/Tests/Configurations/Rules/OriginRuleTest.php new file mode 100644 index 0000000..925457a --- /dev/null +++ b/test/Tests/Configurations/Rules/OriginRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('route', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/RedirectRuleTest.php b/test/Tests/Configurations/Rules/RedirectRuleTest.php new file mode 100644 index 0000000..0c9bc63 --- /dev/null +++ b/test/Tests/Configurations/Rules/RedirectRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('redirect', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/RewriteRuleTest.php b/test/Tests/Configurations/Rules/RewriteRuleTest.php new file mode 100644 index 0000000..cc286dd --- /dev/null +++ b/test/Tests/Configurations/Rules/RewriteRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('rewrite', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/RuleTest.php b/test/Tests/Configurations/Rules/RuleTest.php new file mode 100644 index 0000000..8fbb1fb --- /dev/null +++ b/test/Tests/Configurations/Rules/RuleTest.php @@ -0,0 +1,76 @@ +assertSame([ + 'action' => 'log', + 'enabled' => false, + 'expression' => true, + ], $rule->toArray()); + } + + #[Test] + public function shouldEnableAndDisable() + { + $rule = (new LogRule())->enable(); + $this->assertTrue($rule->toArray()['enabled']); + + $rule->disable(); + $this->assertFalse($rule->toArray()['enabled']); + } + + #[Test] + public function shouldSetDescriptionIdAndRef() + { + $rule = (new LogRule()) + ->setDescription('my description') + ->setId('rule_id') + ->setRef('rule_ref'); + + $array = $rule->toArray(); + + $this->assertSame('my description', $array['description']); + $this->assertSame('rule_id', $array['id']); + $this->assertSame('rule_ref', $array['ref']); + } + + #[Test] + public function shouldSetExpressionFromString() + { + $rule = (new LogRule())->setExpression('ip.src eq 127.0.0.1'); + + $this->assertSame('ip.src eq 127.0.0.1', $rule->toArray()['expression']); + } + + #[Test] + public function shouldSetExpressionFromExpressionBuilder() + { + $builder = (new ExpressionBuilder())->field('ip.src')->eq('127.0.0.1'); + + $rule = (new LogRule())->setExpression($builder); + + $this->assertSame((string) $builder, $rule->toArray()['expression']); + } + + #[Test] + public function shouldSetExpressionFromClosure() + { + $rule = (new LogRule())->setExpression(function (ExpressionBuilder $builder) { + return $builder->field('ip.src')->eq('127.0.0.1'); + }); + + $this->assertSame('ip.src eq 127.0.0.1', $rule->toArray()['expression']); + } +} diff --git a/test/Tests/Configurations/Rules/ScoreRuleTest.php b/test/Tests/Configurations/Rules/ScoreRuleTest.php new file mode 100644 index 0000000..81b5b17 --- /dev/null +++ b/test/Tests/Configurations/Rules/ScoreRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('score', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/ServeErrorRuleTest.php b/test/Tests/Configurations/Rules/ServeErrorRuleTest.php new file mode 100644 index 0000000..a4e81d3 --- /dev/null +++ b/test/Tests/Configurations/Rules/ServeErrorRuleTest.php @@ -0,0 +1,21 @@ +toArray(); + + $this->assertSame('serve_error', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } +} diff --git a/test/Tests/Configurations/Rules/SkipRuleTest.php b/test/Tests/Configurations/Rules/SkipRuleTest.php new file mode 100644 index 0000000..5b60142 --- /dev/null +++ b/test/Tests/Configurations/Rules/SkipRuleTest.php @@ -0,0 +1,30 @@ +toArray(); + + $this->assertSame('skip', $array['action']); + $this->assertArrayNotHasKey('action_parameters', $array); + } + + #[Test] + public function shouldEnableAndDisableLogging() + { + $rule = new SkipRule(); + + $this->assertSame($rule, $rule->enableLogging()); + $this->assertSame($rule, $rule->disableLogging()); + } +} diff --git a/test/Tests/Configurations/RulesetTest.php b/test/Tests/Configurations/RulesetTest.php new file mode 100644 index 0000000..7687948 --- /dev/null +++ b/test/Tests/Configurations/RulesetTest.php @@ -0,0 +1,64 @@ +zone()->requestFirewallCustom(); + + $this->assertSame([ + 'name' => 'my ruleset', + 'kind' => 'zone', + 'phase' => 'http_request_firewall_custom', + 'rules' => [], + ], $ruleset->toArray()); + } + + #[Test] + public function shouldSetNameAndDescription() + { + $ruleset = (new Ruleset('my ruleset')) + ->setName('renamed') + ->setDescription('an informative description') + ->managed() + ->ddosL4(); + + $array = $ruleset->toArray(); + + $this->assertSame('renamed', $array['name']); + $this->assertSame('managed', $array['kind']); + $this->assertSame('ddos_l4', $array['phase']); + $this->assertSame('an informative description', $array['description']); + } + + #[Test] + public function shouldAddRules() + { + $ruleset = (new Ruleset('my ruleset')) + ->custom() + ->rateLimit() + ->addRule((new BlockRule(['error' => 'blocked']))->setExpression('true')); + + $array = $ruleset->toArray(); + + $this->assertCount(1, $array['rules']); + $this->assertSame('block', $array['rules'][0]['action']); + } + + #[Test] + public function shouldThrowOnUndefinedMethod() + { + $this->expectException(BadMethodCallException::class); + + (new Ruleset('my ruleset'))->notARealMethod(); + } +} diff --git a/test/Tests/Configurations/Workers/DeploymentTest.php b/test/Tests/Configurations/Workers/DeploymentTest.php index 5e5dfa6..435c1cb 100644 --- a/test/Tests/Configurations/Workers/DeploymentTest.php +++ b/test/Tests/Configurations/Workers/DeploymentTest.php @@ -4,8 +4,9 @@ use Cloudflare\Configurations\Workers\Deployment; use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\TestCase; -class DeploymentTest extends \PHPUnit\Framework\TestCase +class DeploymentTest extends TestCase { #[Test] public function shouldNotHaveVersions() @@ -21,6 +22,7 @@ public function shouldNotHaveVersions() ], $deployment->toArray()); } + #[Test] public function shouldHaveVersions() { $deployment = new Deployment('This is a human-readable message about the deployment'); @@ -41,6 +43,20 @@ public function shouldHaveVersions() ], $deployment->toArray()); } + #[Test] + public function shouldOverrideExistingVersion() + { + $deployment = (new Deployment('message')) + ->addVersion('id', 0.2) + ->addVersion('id', 0.5); + + $versions = $deployment->toArray()['versions']; + + $this->assertCount(1, $versions); + $this->assertSame(0.5, $versions[0]['percentage']); + } + + #[Test] public function shouldUpdateMessage() { $deployment = new Deployment('This is a human-readable message about the deployment'); diff --git a/test/Tests/Configurations/Zones/CachePurgeTest.php b/test/Tests/Configurations/Zones/CachePurgeTest.php index e172501..11f3cd9 100644 --- a/test/Tests/Configurations/Zones/CachePurgeTest.php +++ b/test/Tests/Configurations/Zones/CachePurgeTest.php @@ -60,4 +60,66 @@ public function shouldHaveCountry() ] ], $cachePurge->toArray()); } + + #[Test] + public function shouldHaveLanguage() + { + $cachePurge = (new CachePurge())->byFilesAdvanced('https://example.com/script.js', language: 'en-US'); + + $this->assertEquals([ + 'files' => [ + [ + 'url' => 'https://example.com/script.js', + 'headers' => [ + 'accept-language' => 'en-US' + ] + ] + ] + ], $cachePurge->toArray()); + } + + #[Test] + public function shouldOverrideExistingFileAdvancedEntry() + { + $cachePurge = (new CachePurge()) + ->byFilesAdvanced('https://example.com/script.js', 'mobile') + ->byFilesAdvanced('https://example.com/script.js', 'desktop'); + + $files = $cachePurge->toArray()['files']; + + $this->assertCount(1, $files); + $this->assertSame('desktop', $files[0]['headers']['CF-Device-Type']); + } + + #[Test] + public function shouldHaveTags() + { + $cachePurge = (new CachePurge())->byTags(['my-tag']); + + $this->assertEquals(['tags' => ['my-tag']], $cachePurge->toArray()); + } + + #[Test] + public function shouldHaveHosts() + { + $cachePurge = (new CachePurge())->byHosts(['example.com']); + + $this->assertEquals(['hosts' => ['example.com']], $cachePurge->toArray()); + } + + #[Test] + public function shouldHavePrefixes() + { + $cachePurge = (new CachePurge())->byPrefixes(['images/']); + + $this->assertEquals(['prefixes' => ['images/']], $cachePurge->toArray()); + } + + #[Test] + public function shouldHaveFiles() + { + $cachePurge = (new CachePurge())->byFiles(['https://example.com/script.js']); + + $this->assertEquals(['files' => ['https://example.com/script.js']], $cachePurge->toArray()); + } } diff --git a/test/Tests/Configurations/Zones/PageRuleTest.php b/test/Tests/Configurations/Zones/PageRuleTest.php index b4aea3e..0a7f7b0 100644 --- a/test/Tests/Configurations/Zones/PageRuleTest.php +++ b/test/Tests/Configurations/Zones/PageRuleTest.php @@ -3,9 +3,11 @@ namespace Cloudflare\Tests\Configurations\Zones; use Cloudflare\Configurations\Zones\PageRule; +use Cloudflare\Exceptions\ConfigurationException; use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\TestCase; -class PageRuleTest extends \PHPUnit\Framework\TestCase +class PageRuleTest extends TestCase { #[Test] public function shouldNotHaveActions() @@ -32,28 +34,199 @@ public function shouldHaveZarazDisabled() $pageRule = (new PageRule('example.com/*'))->disableZaraz(true); $this->assertEquals([ - 'targets' => [ - [ - 'target' => 'url', - 'constraint' => [ - 'operator' => 'matches', - 'value' => 'example.com/*' - ] - ] - ], - 'actions' => [ - [ - 'id' => 'disable_zaraz', - 'value' => 'on' - ] - ] - ], $pageRule->toArray()); + 'id' => 'disable_zaraz', + 'value' => 'on' + ], $pageRule->toArray()['actions'][0]); } + #[Test] public function shouldHaveStatusDisabled() { $pageRule = (new PageRule('example.com/*'))->disable(); $this->assertEquals('disabled', $pageRule->toArray()['status']); } + + #[Test] + public function shouldHaveStatusEnabled() + { + $pageRule = (new PageRule('example.com/*'))->enable(); + + $this->assertEquals('active', $pageRule->toArray()['status']); + } + + #[Test] + public function shouldSetPriority() + { + $pageRule = (new PageRule('example.com/*'))->setPriority(5); + + $this->assertSame(5, $pageRule->toArray()['priority']); + } + + #[Test] + public function shouldSetAllSimpleActions() + { + $pageRule = (new PageRule('example.com/*')) + ->alwaysUseHTTPS(true) + ->automaticHTTPSRewrites(true) + ->browserCacheTTL(3600) + ->browserIntegrityCheck(true) + ->cacheByDeviceType(true) + ->cacheKey('custom-key') + ->disableApps(true) + ->disablePerformance(true) + ->emailObfuscation(true) + ->hostHeaderOverride('example.com') + ->IPGeoLocationHeader(true) + ->mirage(true) + ->opportunisticEncryption(true) + ->originCacheControl(true) + ->disableSecurity(true) + ->originErrorPagePassthru(true) + ->queryStringSort(true) + ->resolveOverride('origin.example.com') + ->respectStrongEtag(true) + ->responseBuffering(true) + ->rocketLoader(true) + ->trueClientIpHeader(true) + ->waf(true); + + $ids = array_column($pageRule->toArray()['actions'], 'id'); + + $this->assertSame([ + 'always_use_https', + 'automatic_https_rewrites', + 'browser_cache_ttl', + 'browser_check', + 'cache_by_device_type', + 'cache_key', + 'disable_apps', + 'disable_performance', + 'disable_security', + 'host_header_override', + 'ip_geolocation', + 'mirage', + 'opportunistic_encryption', + 'explicit_cache_control', + 'origin_error_page_pass_thru', + 'sort_query_string_for_cache', + 'resolve_override', + 'respect_strong_etag', + 'response_buffering', + 'rocket_loader', + 'true_client_ip_header', + 'waf', + ], $ids); + } + + #[Test] + public function shouldOverrideExistingActionValue() + { + $pageRule = (new PageRule('example.com/*')) + ->browserCacheTTL(3600) + ->browserCacheTTL(7200); + + $actions = $pageRule->toArray()['actions']; + + $this->assertCount(1, $actions); + $this->assertSame(7200, $actions[0]['value']); + } + + #[Test] + public function shouldSetBypassCacheOnCookie() + { + $pageRule = (new PageRule('example.com/*'))->bypassCacheOnCookie('session_*'); + + $this->assertSame('bypass_cache_on_cookie', $pageRule->toArray()['actions'][0]['id']); + } + + #[Test] + public function shouldThrowOnInvalidBypassCacheOnCookie() + { + $this->expectException(ConfigurationException::class); + + (new PageRule('example.com/*'))->bypassCacheOnCookie('invalid cookie!'); + } + + #[Test] + public function shouldSetCacheOnCookie() + { + $pageRule = (new PageRule('example.com/*'))->cacheOnCookie('session_*'); + + $this->assertSame('cache_on_cookie', $pageRule->toArray()['actions'][0]['id']); + } + + #[Test] + public function shouldThrowOnInvalidCacheOnCookie() + { + $this->expectException(ConfigurationException::class); + + (new PageRule('example.com/*'))->cacheOnCookie('invalid cookie!'); + } + + #[Test] + public function shouldSetValidCacheLevel() + { + $pageRule = (new PageRule('example.com/*'))->cacheLevel('aggressive'); + + $this->assertSame('cache_level', $pageRule->toArray()['actions'][0]['id']); + } + + #[Test] + public function shouldThrowOnInvalidCacheLevel() + { + $this->expectException(ConfigurationException::class); + + (new PageRule('example.com/*'))->cacheLevel('invalid'); + } + + #[Test] + public function shouldSetEdgeCacheTTL() + { + $pageRule = (new PageRule('example.com/*'))->edgeCacheTTL(3600); + + $this->assertSame('edge_cache_ttl', $pageRule->toArray()['actions'][0]['id']); + } + + #[Test] + public function shouldThrowOnEdgeCacheTTLTooHigh() + { + $this->expectException(ConfigurationException::class); + + (new PageRule('example.com/*'))->edgeCacheTTL(2678401); + } + + #[Test] + public function shouldSetForwardingURLWithDefaultStatusCode() + { + $pageRule = (new PageRule('example.com/*'))->forwardingURL('https://example.com'); + + $action = $pageRule->toArray()['actions'][0]; + $this->assertSame('forwarding_url', $action['id']); + $this->assertSame(301, $action['value']['status_code']); + } + + #[Test] + public function shouldThrowOnInvalidForwardingURLStatusCode() + { + $this->expectException(ConfigurationException::class); + + (new PageRule('example.com/*'))->forwardingURL('https://example.com', 300); + } + + #[Test] + public function shouldSetValidSslMode() + { + $pageRule = (new PageRule('example.com/*'))->ssl('full'); + + $this->assertSame('ssl', $pageRule->toArray()['actions'][0]['id']); + } + + #[Test] + public function shouldThrowOnInvalidSslMode() + { + $this->expectException(ConfigurationException::class); + + (new PageRule('example.com/*'))->ssl('invalid'); + } } diff --git a/test/Tests/D1Test.php b/test/Tests/D1Test.php new file mode 100644 index 0000000..ae47d5f --- /dev/null +++ b/test/Tests/D1Test.php @@ -0,0 +1,216 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['uuid' => 'database_id']]])), + ]); + + $response = $client->d1()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/d1/database', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithoutLocation() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['uuid' => 'database_id']])), + ]); + + $response = $client->d1()->create('account_id', 'my-database'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame(['name' => 'my-database'], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldCreateWithLocation() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['uuid' => 'database_id']])), + ]); + + $response = $client->d1()->create('account_id', 'my-database', 'wnam'); + + $this->assertTrue($response->successful()); + $this->assertSame([ + 'name' => 'my-database', + 'primary_location_hint' => 'wnam', + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['uuid' => 'database_id']])), + ]); + + $response = $client->d1()->details('account_id', 'database_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/d1/database/database_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->d1()->delete('account_id', 'database_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/d1/database/database_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldExportWithoutBookmark() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['success' => true]])), + ]); + + $response = $client->d1()->export('account_id', 'database_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $body = json_decode((string) $this->lastRequest()->getBody(), true); + $this->assertArrayNotHasKey('current_bookmark', $body); + } + + #[Test] + public function shouldExportWithBookmark() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['success' => true]])), + ]); + + $response = $client->d1()->export('account_id', 'database_id', 'bookmark_1', true, true, ['table1']); + + $this->assertTrue($response->successful()); + $body = json_decode((string) $this->lastRequest()->getBody(), true); + $this->assertSame('bookmark_1', $body['current_bookmark']); + } + + #[Test] + public function shouldImportInit() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['success' => true]])), + ]); + + $response = $client->d1()->import('account_id', 'database_id', 'init', 'etag_value'); + + $this->assertTrue($response->successful()); + $body = json_decode((string) $this->lastRequest()->getBody(), true); + $this->assertSame('etag_value', $body['etag']); + } + + #[Test] + public function shouldImportIngest() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['success' => true]])), + ]); + + $response = $client->d1()->import('account_id', 'database_id', 'ingest', 'etag_value', 'filename.sql'); + + $this->assertTrue($response->successful()); + $body = json_decode((string) $this->lastRequest()->getBody(), true); + $this->assertSame('filename.sql', $body['filename']); + $this->assertSame('etag_value', $body['etag']); + } + + #[Test] + public function shouldImportPoll() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['success' => true]])), + ]); + + $response = $client->d1()->import('account_id', 'database_id', 'poll', null, null, 'bookmark_1'); + + $this->assertTrue($response->successful()); + $body = json_decode((string) $this->lastRequest()->getBody(), true); + $this->assertSame('bookmark_1', $body['current_bookmark']); + } + + #[Test] + public function shouldThrowWhenIngestMissingFilename() + { + $client = $this->mockClient([]); + + $this->expectException(MissingArgumentException::class); + + $client->d1()->import('account_id', 'database_id', 'ingest', 'etag_value'); + } + + #[Test] + public function shouldThrowWhenPollMissingBookmark() + { + $client = $this->mockClient([]); + + $this->expectException(MissingArgumentException::class); + + $client->d1()->import('account_id', 'database_id', 'poll'); + } + + #[Test] + public function shouldThrowWhenInitMissingEtag() + { + $client = $this->mockClient([]); + + $this->expectException(MissingArgumentException::class); + + $client->d1()->import('account_id', 'database_id', 'init'); + } + + #[Test] + public function shouldQuery() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['results' => []]]])), + ]); + + $response = $client->d1()->query('account_id', 'database_id', 'SELECT * FROM table1', ['param1']); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/d1/database/database_id/query', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldRaw() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['results' => []]]])), + ]); + + $response = $client->d1()->raw('account_id', 'database_id', 'SELECT * FROM table1'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/d1/database/database_id/raw', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Accounts/AuditLogsTest.php b/test/Tests/Endpoints/Accounts/AuditLogsTest.php new file mode 100644 index 0000000..54430fa --- /dev/null +++ b/test/Tests/Endpoints/Accounts/AuditLogsTest.php @@ -0,0 +1,27 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'log_id']]])), + ]); + + $response = $client->accounts()->auditLogs()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/audit_logs', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Accounts/MembersTest.php b/test/Tests/Endpoints/Accounts/MembersTest.php new file mode 100644 index 0000000..ac36a6b --- /dev/null +++ b/test/Tests/Endpoints/Accounts/MembersTest.php @@ -0,0 +1,100 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'member_id']]])), + ]); + + $response = $client->accounts()->members()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/members', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldAdd() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'member_id']])), + ]); + + $response = $client->accounts()->members()->add('account_id', [ + 'email' => 'user@example.com', + 'roles' => ['role_id'], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/members', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'member_id']])), + ]); + + $response = $client->accounts()->members()->delete('account_id', 'member_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/members/member_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'member_id']])), + ]); + + $response = $client->accounts()->members()->details('account_id', 'member_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/members/member_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateRoles() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'member_id']])), + ]); + + $response = $client->accounts()->members()->updateRoles('account_id', 'member_id', ['role_id']); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame(['roles' => ['role_id']], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldUpdatePolicies() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'member_id']])), + ]); + + $response = $client->accounts()->members()->updatePolicies('account_id', 'member_id', ['policy_id']); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame(['policies' => ['policy_id']], json_decode((string) $this->lastRequest()->getBody(), true)); + } +} diff --git a/test/Tests/Endpoints/Accounts/RolesTest.php b/test/Tests/Endpoints/Accounts/RolesTest.php new file mode 100644 index 0000000..df42300 --- /dev/null +++ b/test/Tests/Endpoints/Accounts/RolesTest.php @@ -0,0 +1,41 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'role_id']]])), + ]); + + $response = $client->accounts()->roles()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/roles', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'role_id']])), + ]); + + $response = $client->accounts()->roles()->details('account_id', 'role_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/roles/role_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Accounts/RulesetsTest.php b/test/Tests/Endpoints/Accounts/RulesetsTest.php new file mode 100644 index 0000000..db573f9 --- /dev/null +++ b/test/Tests/Endpoints/Accounts/RulesetsTest.php @@ -0,0 +1,91 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'ruleset_id']]])), + ]); + + $response = $client->accounts()->rulesets()->get('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/rulesets', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithArray() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'ruleset_id']])), + ]); + + $response = $client->accounts()->rulesets()->create('account_id', [ + 'name' => 'my ruleset', + 'kind' => 'root', + 'phase' => 'http_request_firewall_custom', + 'rules' => [['action' => 'block', 'expression' => 'true']], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/rulesets', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithRulesetObject() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'ruleset_id']])), + ]); + + $ruleset = (new Ruleset('my ruleset'))->addRule((new BlockRule(['error' => 'blocked']))->setExpression('true')); + + $response = $client->accounts()->rulesets()->create('account_id', $ruleset); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'ruleset_id']])), + ]); + + $response = $client->accounts()->rulesets()->details('account_id', 'ruleset_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/rulesets/ruleset_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->accounts()->rulesets()->delete('account_id', 'ruleset_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/rulesets/ruleset_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/AccountsTest.php b/test/Tests/Endpoints/AccountsTest.php new file mode 100644 index 0000000..5020a06 --- /dev/null +++ b/test/Tests/Endpoints/AccountsTest.php @@ -0,0 +1,119 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'account_id']]])), + ]); + + $response = $client->accounts()->list(); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithoutUnit() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'account_id']])), + ]); + + $response = $client->accounts()->create('my account', 'standard'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame([ + 'name' => 'my account', + 'type' => 'standard', + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldCreateWithUnit() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'account_id']])), + ]); + + $response = $client->accounts()->create('my account', 'enterprise', 'unit_id'); + + $this->assertTrue($response->successful()); + $this->assertSame([ + 'name' => 'my account', + 'type' => 'enterprise', + 'unit' => ['id' => 'unit_id'], + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'account_id']])), + ]); + + $response = $client->accounts()->details('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateWithoutSettings() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'account_id']])), + ]); + + $response = $client->accounts()->update('account_id', 'renamed account'); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame(['name' => 'renamed account'], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldUpdateWithSettings() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'account_id']])), + ]); + + $response = $client->accounts()->update('account_id', 'renamed account', ['enforce_twofactor' => true]); + + $this->assertTrue($response->successful()); + $this->assertSame([ + 'name' => 'renamed account', + 'settings' => ['enforce_twofactor' => true], + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'account_id']])), + ]); + + $response = $client->accounts()->delete('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Tunnel/RoutesTest.php b/test/Tests/Endpoints/Tunnel/RoutesTest.php new file mode 100644 index 0000000..6fb96c2 --- /dev/null +++ b/test/Tests/Endpoints/Tunnel/RoutesTest.php @@ -0,0 +1,128 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'route_id']]])), + ]); + + $response = $client->tunnel()->routes()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/routes', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetByIpWithoutVirtualNetwork() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'route_id']]])), + ]); + + $response = $client->tunnel()->routes()->getByIP('account_id', '127.0.0.1'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/routes/ip/127.0.0.1', $this->lastRequest()->getUri()->getPath()); + $this->assertSame('', $this->lastRequest()->getUri()->getQuery()); + } + + #[Test] + public function shouldGetByIpWithVirtualNetwork() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'route_id']]])), + ]); + + $response = $client->tunnel()->routes()->getByIP('account_id', '127.0.0.1', 'vnet_id'); + + $this->assertTrue($response->successful()); + $this->assertStringContainsString('virtual_network_id=vnet_id', $this->lastRequest()->getUri()->getQuery()); + } + + #[Test] + public function shouldCreateWithoutOptionalParams() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'route_id']])), + ]); + + $response = $client->tunnel()->routes()->create('account_id', '10.0.0.0/24'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame(['network' => '10.0.0.0/24'], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldCreateWithOptionalParams() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'route_id']])), + ]); + + $response = $client->tunnel()->routes()->create('account_id', '10.0.0.0/24', 'vnet_id', 'my comment'); + + $this->assertTrue($response->successful()); + $this->assertSame([ + 'network' => '10.0.0.0/24', + 'virtual_network_id' => 'vnet_id', + 'comment' => 'my comment', + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'route_id']])), + ]); + + $response = $client->tunnel()->routes()->details('account_id', 'route_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/routes/route_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'route_id']])), + ]); + + $response = $client->tunnel()->routes()->update('account_id', 'route_id', ['comment' => 'updated']); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/routes/route_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->tunnel()->routes()->delete('account_id', 'route_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/routes/route_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Tunnel/VirtualNetworksTest.php b/test/Tests/Endpoints/Tunnel/VirtualNetworksTest.php new file mode 100644 index 0000000..112d7a5 --- /dev/null +++ b/test/Tests/Endpoints/Tunnel/VirtualNetworksTest.php @@ -0,0 +1,103 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'vnet_id']]])), + ]); + + $response = $client->tunnel()->virtualNetworks()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/virtual_networks', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithoutComment() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'vnet_id']])), + ]); + + $response = $client->tunnel()->virtualNetworks()->create('account_id', 'my-network'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame([ + 'name' => 'my-network', + 'is_default' => false, + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldCreateWithComment() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'vnet_id']])), + ]); + + $response = $client->tunnel()->virtualNetworks()->create('account_id', 'my-network', true, 'my comment'); + + $this->assertTrue($response->successful()); + $this->assertSame([ + 'name' => 'my-network', + 'is_default' => true, + 'comment' => 'my comment', + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'vnet_id']])), + ]); + + $response = $client->tunnel()->virtualNetworks()->details('account_id', 'vnet_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/virtual_networks/vnet_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'vnet_id']])), + ]); + + $response = $client->tunnel()->virtualNetworks()->update('account_id', 'vnet_id', ['comment' => 'updated']); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/virtual_networks/vnet_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->tunnel()->virtualNetworks()->delete('account_id', 'vnet_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/teamnet/virtual_networks/vnet_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Workers/CronTest.php b/test/Tests/Endpoints/Workers/CronTest.php new file mode 100644 index 0000000..ee1ac04 --- /dev/null +++ b/test/Tests/Endpoints/Workers/CronTest.php @@ -0,0 +1,45 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['cron' => '* * * * *']]])), + ]); + + $response = $client->workers()->cron()->get('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/schedules', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['cron' => '* * * * *']]])), + ]); + + $response = $client->workers()->cron()->update('account_id', 'script_name', ['* * * * *', '0 0 * * *']); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/schedules', $this->lastRequest()->getUri()->getPath()); + $this->assertSame([ + ['cron' => '* * * * *'], + ['cron' => '0 0 * * *'], + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } +} diff --git a/test/Tests/Endpoints/Workers/DeploymentsTest.php b/test/Tests/Endpoints/Workers/DeploymentsTest.php new file mode 100644 index 0000000..4a75f9a --- /dev/null +++ b/test/Tests/Endpoints/Workers/DeploymentsTest.php @@ -0,0 +1,62 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'deployment_id']]])), + ]); + + $response = $client->workers()->deployments()->get('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/deployments', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithArray() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'deployment_id']])), + ]); + + $response = $client->workers()->deployments()->create('account_id', 'script_name', [ + 'strategy' => 'percentage', + 'versions' => [['version_id' => 'version_id', 'percentage' => 100]], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/deployments', $this->lastRequest()->getUri()->getPath()); + $this->assertSame('', $this->lastRequest()->getUri()->getQuery()); + } + + #[Test] + public function shouldCreateWithDeploymentObjectAndForce() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'deployment_id']])), + ]); + + $deployment = (new Deployment('rollout'))->addVersion('version_id', 100); + + $response = $client->workers()->deployments()->create('account_id', 'script_name', $deployment, true); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertStringContainsString('force=', $this->lastRequest()->getUri()->getQuery()); + } +} diff --git a/test/Tests/Endpoints/Workers/DomainsTest.php b/test/Tests/Endpoints/Workers/DomainsTest.php new file mode 100644 index 0000000..69584f9 --- /dev/null +++ b/test/Tests/Endpoints/Workers/DomainsTest.php @@ -0,0 +1,74 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'domain_id']]])), + ]); + + $response = $client->workers()->domains()->get('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/domains', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldAttach() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'domain_id']])), + ]); + + $response = $client->workers()->domains()->attach('account_id', [ + 'environment' => 'production', + 'hostname' => 'example.com', + 'service' => 'my-worker', + 'zone_id' => 'zone_id', + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/domains', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDetach() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->workers()->domains()->detach('account_id', 'domain_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/domains/domain_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetDomain() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'domain_id']])), + ]); + + $response = $client->workers()->domains()->domain('account_id', 'domain_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/domains/domain_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Workers/DurableObjectsTest.php b/test/Tests/Endpoints/Workers/DurableObjectsTest.php index 5bb76b0..826a6e3 100644 --- a/test/Tests/Endpoints/Workers/DurableObjectsTest.php +++ b/test/Tests/Endpoints/Workers/DurableObjectsTest.php @@ -11,6 +11,27 @@ class DurableObjectsTest extends TestCase { use InteractsWithMockClient; + #[Test] + public function shouldList() + { + $client = $this->mockClient([ + new Response(200, [], json_encode([ + 'success' => true, + 'result' => [ + ['id' => 'namespace_id'], + ], + ])), + ]); + + $response = $client->workers()->durableObjects()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('namespace_id', $response->json('result.0.id')); + + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/durable_objects/namespaces', $this->lastRequest()->getUri()->getPath()); + } + #[Test] public function shouldListObjects() { diff --git a/test/Tests/Endpoints/Workers/EnvironmentTest.php b/test/Tests/Endpoints/Workers/EnvironmentTest.php new file mode 100644 index 0000000..ec21efb --- /dev/null +++ b/test/Tests/Endpoints/Workers/EnvironmentTest.php @@ -0,0 +1,68 @@ +mockClient([ + new Response(200, [], 'script content'), + ]); + + $response = $client->workers()->environment()->get('account_id', 'service_name', 'production'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/services/service_name/environments/production/content', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldThrowOnUpdate() + { + $client = $this->mockClient([]); + + $this->expectException(BadMethodCallException::class); + + $client->workers()->environment()->update('account_id', 'service_name', 'production'); + } + + #[Test] + public function shouldGetSettings() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => []])), + ]); + + $response = $client->workers()->environment()->getSettings('account_id', 'service_name', 'production'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/services/service_name/environments/production/settings', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateSettings() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => []])), + ]); + + $response = $client->workers()->environment()->updateSettings('account_id', 'service_name', 'production', [ + 'bindings' => [], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/services/service_name/environments/production/settings', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Workers/KVTest.php b/test/Tests/Endpoints/Workers/KVTest.php index ede9b58..5ccf4cd 100644 --- a/test/Tests/Endpoints/Workers/KVTest.php +++ b/test/Tests/Endpoints/Workers/KVTest.php @@ -11,6 +11,163 @@ class KVTest extends TestCase { use InteractsWithMockClient; + #[Test] + public function shouldList() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'namespace_id']]])), + ]); + + $response = $client->workers()->kv()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'namespace_id']])), + ]); + + $response = $client->workers()->kv()->create('account_id', 'my-namespace'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces', $this->lastRequest()->getUri()->getPath()); + $this->assertSame(['title' => 'my-namespace'], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'namespace_id']])), + ]); + + $response = $client->workers()->kv()->details('account_id', 'namespace_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'namespace_id']])), + ]); + + $response = $client->workers()->kv()->update('account_id', 'namespace_id', 'renamed'); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->workers()->kv()->delete('account_id', 'namespace_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldListKeys() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['name' => 'key1']]])), + ]); + + $response = $client->workers()->kv()->listKeys('account_id', 'namespace_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id/keys', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetKeyMetadata() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['someKey' => 'someValue']])), + ]); + + $response = $client->workers()->kv()->keyMetadata('account_id', 'namespace_id', 'key1'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id/metadata/key1', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetKeyDetails() + { + $client = $this->mockClient([ + new Response(200, [], 'value1'), + ]); + + $response = $client->workers()->kv()->keyDetails('account_id', 'namespace_id', 'key1'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id/values/key1', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldWriteKeyWithMetadata() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->workers()->kv()->writeKeyWithMetadata('account_id', 'namespace_id', 'key1', ['value' => 'value1']); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id/values/key1', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDeleteKey() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->workers()->kv()->deleteKey('account_id', 'namespace_id', 'key1'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id/values/key1', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldWriteMultipleKeys() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->workers()->kv()->writeMultipleKeys('account_id', 'namespace_id', [ + ['key' => 'key1', 'value' => 'value1'], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/storage/kv/namespaces/namespace_id/bulk', $this->lastRequest()->getUri()->getPath()); + } + #[Test] public function shouldDeleteMultipleKeys() { diff --git a/test/Tests/Endpoints/Workers/LogsTest.php b/test/Tests/Endpoints/Workers/LogsTest.php new file mode 100644 index 0000000..262a503 --- /dev/null +++ b/test/Tests/Endpoints/Workers/LogsTest.php @@ -0,0 +1,55 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'tail_id']]])), + ]); + + $response = $client->workers()->logs()->get('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/tails', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldStart() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'tail_id']])), + ]); + + $response = $client->workers()->logs()->start('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/tails', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->workers()->logs()->delete('account_id', 'script_name', 'tail_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/tails/tail_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Workers/RoutesTest.php b/test/Tests/Endpoints/Workers/RoutesTest.php new file mode 100644 index 0000000..4994756 --- /dev/null +++ b/test/Tests/Endpoints/Workers/RoutesTest.php @@ -0,0 +1,89 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'route_id']]])), + ]); + + $response = $client->workers()->routes()->get('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/workers/routes', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'route_id']])), + ]); + + $response = $client->workers()->routes()->create('zone_id', [ + 'pattern' => 'example.com/*', + 'script' => 'my-worker', + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/workers/routes', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'route_id']])), + ]); + + $response = $client->workers()->routes()->details('zone_id', 'route_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/workers/routes/route_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'route_id']])), + ]); + + $response = $client->workers()->routes()->update('zone_id', 'route_id', [ + 'pattern' => 'example.com/*', + 'script' => 'my-worker', + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/workers/routes/route_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'route_id']])), + ]); + + $response = $client->workers()->routes()->delete('zone_id', 'route_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/workers/routes/route_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Workers/ScriptsTest.php b/test/Tests/Endpoints/Workers/ScriptsTest.php new file mode 100644 index 0000000..4c3a588 --- /dev/null +++ b/test/Tests/Endpoints/Workers/ScriptsTest.php @@ -0,0 +1,175 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'script_name']]])), + ]); + + $response = $client->workers()->scripts()->get('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDownload() + { + $client = $this->mockClient([ + new Response(200, [], 'export default { fetch() {} }'), + ]); + + $response = $client->workers()->scripts()->download('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldThrowOnUpload() + { + $client = $this->mockClient([]); + + $this->expectException(BadMethodCallException::class); + + $client->workers()->scripts()->upload('account_id', 'script_name'); + } + + #[Test] + public function shouldThrowOnUpdateContent() + { + $client = $this->mockClient([]); + + $this->expectException(BadMethodCallException::class); + + $client->workers()->scripts()->updateContent('account_id', 'script_name'); + } + + #[Test] + public function shouldGetContent() + { + $client = $this->mockClient([ + new Response(200, [], 'export default { fetch() {} }'), + ]); + + $response = $client->workers()->scripts()->getContent('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/content/v2', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetScriptSettings() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => []])), + ]); + + $response = $client->workers()->scripts()->getScriptSettings('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/script-settings', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateScriptSettings() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => []])), + ]); + + $response = $client->workers()->scripts()->updateScriptSettings('account_id', 'script_name', ['logpush' => true]); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/script-settings', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetSettings() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => []])), + ]); + + $response = $client->workers()->scripts()->getSettings('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/settings', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateSettings() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => []])), + ]); + + $response = $client->workers()->scripts()->updateSettings('account_id', 'script_name', ['bindings' => []]); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/settings', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetUsageModel() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['usage_model' => 'standard']])), + ]); + + $response = $client->workers()->scripts()->getUsageModel('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/usage-model', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateUsageModel() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['usage_model' => 'bundled']])), + ]); + + $response = $client->workers()->scripts()->updateUsageModel('account_id', 'script_name', 'bundled'); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/usage-model', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->workers()->scripts()->delete('account_id', 'script_name', true); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name', $this->lastRequest()->getUri()->getPath()); + $this->assertStringContainsString('force=', $this->lastRequest()->getUri()->getQuery()); + } +} diff --git a/test/Tests/Endpoints/Workers/SettingsTest.php b/test/Tests/Endpoints/Workers/SettingsTest.php new file mode 100644 index 0000000..024d5e2 --- /dev/null +++ b/test/Tests/Endpoints/Workers/SettingsTest.php @@ -0,0 +1,45 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['default_usage_model' => 'standard']])), + ]); + + $response = $client->workers()->settings()->get('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/account-settings', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['default_usage_model' => 'standard']])), + ]); + + $response = $client->workers()->settings()->create('account_id', 'standard', true); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/account-settings', $this->lastRequest()->getUri()->getPath()); + $this->assertSame([ + 'default_usage_model' => 'standard', + 'green_compute' => true, + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } +} diff --git a/test/Tests/Endpoints/Workers/SubdomainTest.php b/test/Tests/Endpoints/Workers/SubdomainTest.php new file mode 100644 index 0000000..30038d2 --- /dev/null +++ b/test/Tests/Endpoints/Workers/SubdomainTest.php @@ -0,0 +1,42 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['subdomain' => 'my-subdomain']])), + ]); + + $response = $client->workers()->subdomain()->get('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/subdomain', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['subdomain' => 'my-subdomain']])), + ]); + + $response = $client->workers()->subdomain()->create('account_id', 'my-subdomain'); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/subdomain', $this->lastRequest()->getUri()->getPath()); + $this->assertSame(['subdomain' => 'my-subdomain'], json_decode((string) $this->lastRequest()->getBody(), true)); + } +} diff --git a/test/Tests/Endpoints/Workers/VersionsTest.php b/test/Tests/Endpoints/Workers/VersionsTest.php new file mode 100644 index 0000000..9500663 --- /dev/null +++ b/test/Tests/Endpoints/Workers/VersionsTest.php @@ -0,0 +1,52 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'version_id']]])), + ]); + + $response = $client->workers()->versions()->list('account_id', 'script_name'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/versions', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldThrowOnUpload() + { + $client = $this->mockClient([]); + + $this->expectException(BadMethodCallException::class); + + $client->workers()->versions()->upload('account_id', 'script_name'); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'version_id']])), + ]); + + $response = $client->workers()->versions()->details('account_id', 'script_name', 'version_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/accounts/account_id/workers/scripts/script_name/versions/version_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Zones/CloudConnectorTest.php b/test/Tests/Endpoints/Zones/CloudConnectorTest.php new file mode 100644 index 0000000..21d8182 --- /dev/null +++ b/test/Tests/Endpoints/Zones/CloudConnectorTest.php @@ -0,0 +1,47 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'rule_id']]])), + ]); + + $response = $client->zones()->cloudConnector()->get('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('rule_id', $response->json('result.0.id')); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/cloud_connector/rules', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'rule_id']]])), + ]); + + $response = $client->zones()->cloudConnector()->update('zone_id', [ + 'name' => 'my rule', + 'expression' => 'true', + 'provider' => 'aws_s3', + 'parameters' => ['host' => 'example.com'], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/cloud_connector/rules', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Zones/DNSSECTest.php b/test/Tests/Endpoints/Zones/DNSSECTest.php new file mode 100644 index 0000000..8b4b426 --- /dev/null +++ b/test/Tests/Endpoints/Zones/DNSSECTest.php @@ -0,0 +1,61 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['status' => 'active']])), + ]); + + $response = $client->zones()->dnssec()->details('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('active', $response->json('result.status')); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dnssec', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['status' => 'active']])), + ]); + + $response = $client->zones()->dnssec()->update('zone_id', 'active', true, true); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dnssec', $this->lastRequest()->getUri()->getPath()); + $this->assertSame([ + 'dnssec_multi_signer' => true, + 'dnssec_presigned' => true, + 'status' => 'active', + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->zones()->dnssec()->delete('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dnssec', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Zones/DNSTest.php b/test/Tests/Endpoints/Zones/DNSTest.php new file mode 100644 index 0000000..57cfe19 --- /dev/null +++ b/test/Tests/Endpoints/Zones/DNSTest.php @@ -0,0 +1,163 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => []])), + ]); + + $response = $client->zones()->dns()->scan('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records/scan', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldList() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'record_id']]])), + ]); + + $response = $client->zones()->dns()->list('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('record_id', $response->json('result.0.id')); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'record_id']])), + ]); + + $response = $client->zones()->dns()->create('zone_id', [ + 'type' => 'A', + 'name' => 'example.com', + 'content' => '127.0.0.1', + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldThrowWhenCreateMissingRequiredParams() + { + $client = $this->mockClient([]); + + $this->expectException(MissingArgumentException::class); + + $client->zones()->dns()->create('zone_id', ['name' => 'example.com']); + } + + #[Test] + public function shouldExport() + { + $client = $this->mockClient([ + new Response(200, [], 'example.com. 300 IN A 127.0.0.1'), + ]); + + $response = $client->zones()->dns()->export('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records/export', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldImport() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['recs_added' => 1]])), + ]); + + $response = $client->zones()->dns()->import('zone_id', 'example.com. 300 IN A 127.0.0.1'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records/import', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'record_id']])), + ]); + + $response = $client->zones()->dns()->details('zone_id', 'record_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records/record_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'record_id']])), + ]); + + $response = $client->zones()->dns()->update('zone_id', 'record_id', [ + 'type' => 'A', + 'name' => 'example.com', + 'content' => '127.0.0.1', + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records/record_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldOverwrite() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'record_id']])), + ]); + + $response = $client->zones()->dns()->overwrite('zone_id', 'record_id', [ + 'type' => 'A', + 'name' => 'example.com', + 'content' => '127.0.0.1', + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records/record_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'record_id']])), + ]); + + $response = $client->zones()->dns()->delete('zone_id', 'record_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/dns_records/record_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Zones/HoldTest.php b/test/Tests/Endpoints/Zones/HoldTest.php new file mode 100644 index 0000000..9e7d3f4 --- /dev/null +++ b/test/Tests/Endpoints/Zones/HoldTest.php @@ -0,0 +1,71 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['hold' => true]])), + ]); + + $response = $client->zones()->holds()->details('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/hold', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['hold' => true]])), + ]); + + $response = $client->zones()->holds()->create('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/hold', $this->lastRequest()->getUri()->getPath()); + $this->assertSame(['include_subdomains' => true], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldDeleteWithoutHoldAfter() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['hold' => false]])), + ]); + + $response = $client->zones()->holds()->delete('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/hold', $this->lastRequest()->getUri()->getPath()); + $this->assertSame('', $this->lastRequest()->getUri()->getQuery()); + } + + #[Test] + public function shouldDeleteWithHoldAfter() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['hold' => true]])), + ]); + + $response = $client->zones()->holds()->delete('zone_id', '2030-01-01T00:00:00Z'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertStringContainsString('hold_after=', $this->lastRequest()->getUri()->getQuery()); + } +} diff --git a/test/Tests/Endpoints/Zones/LockdownTest.php b/test/Tests/Endpoints/Zones/LockdownTest.php new file mode 100644 index 0000000..cfeee96 --- /dev/null +++ b/test/Tests/Endpoints/Zones/LockdownTest.php @@ -0,0 +1,98 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'lockdown_id']]])), + ]); + + $response = $client->zones()->lockdowns()->list('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/firewall/lockdowns', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithSingleIp() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'lockdown_id']])), + ]); + + $response = $client->zones()->lockdowns()->create('zone_id', '127.0.0.1', ['example.com/*']); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $body = json_decode((string) $this->lastRequest()->getBody(), true); + $this->assertSame('ip', $body['configurations']['target']); + } + + #[Test] + public function shouldCreateWithIpRange() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'lockdown_id']])), + ]); + + $response = $client->zones()->lockdowns()->create('zone_id', '127.0.0.1/16', ['example.com/*']); + + $this->assertTrue($response->successful()); + $body = json_decode((string) $this->lastRequest()->getBody(), true); + $this->assertSame('ip_range', $body['configurations']['target']); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'lockdown_id']])), + ]); + + $response = $client->zones()->lockdowns()->details('zone_id', 'lockdown_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/firewall/lockdowns/lockdown_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'lockdown_id']])), + ]); + + $response = $client->zones()->lockdowns()->update('zone_id', 'lockdown_id', '127.0.0.1', ['example.com/*']); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/firewall/lockdowns/lockdown_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'lockdown_id']])), + ]); + + $response = $client->zones()->lockdowns()->delete('zone_id', 'lockdown_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/firewall/lockdowns/lockdown_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Zones/PageRulesTest.php b/test/Tests/Endpoints/Zones/PageRulesTest.php new file mode 100644 index 0000000..48c734c --- /dev/null +++ b/test/Tests/Endpoints/Zones/PageRulesTest.php @@ -0,0 +1,166 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => []])), + ]); + + $response = $client->zones()->pageRules()->settings('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/pagerules/settings', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldList() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'page_rule_id']]])), + ]); + + $response = $client->zones()->pageRules()->list('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/pagerules', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithArray() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'page_rule_id']])), + ]); + + $response = $client->zones()->pageRules()->create('zone_id', [ + 'targets' => [['target' => 'url', 'constraint' => ['operator' => 'matches', 'value' => 'example.com/*']]], + 'actions' => [['id' => 'ssl', 'value' => 'flexible']], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/pagerules', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithPageRuleObject() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'page_rule_id']])), + ]); + + $pageRule = (new PageRule('example.com/*'))->enable()->ssl('flexible'); + + $response = $client->zones()->pageRules()->create('zone_id', $pageRule); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'page_rule_id']])), + ]); + + $response = $client->zones()->pageRules()->details('zone_id', 'page_rule_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/pagerules/page_rule_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateWithArray() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'page_rule_id']])), + ]); + + $response = $client->zones()->pageRules()->update('zone_id', 'page_rule_id', [ + 'targets' => [['target' => 'url', 'constraint' => ['operator' => 'matches', 'value' => 'example.com/*']]], + 'actions' => [['id' => 'ssl', 'value' => 'flexible']], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/pagerules/page_rule_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateWithPageRuleObject() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'page_rule_id']])), + ]); + + $pageRule = (new PageRule('example.com/*'))->disable(); + + $response = $client->zones()->pageRules()->update('zone_id', 'page_rule_id', $pageRule); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + } + + #[Test] + public function shouldOverwriteWithArray() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'page_rule_id']])), + ]); + + $response = $client->zones()->pageRules()->overwrite('zone_id', 'page_rule_id', [ + 'targets' => [['target' => 'url', 'constraint' => ['operator' => 'matches', 'value' => 'example.com/*']]], + 'actions' => [['id' => 'ssl', 'value' => 'flexible']], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/pagerules/page_rule_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldOverwriteWithPageRuleObject() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'page_rule_id']])), + ]); + + $pageRule = new PageRule('example.com/*'); + + $response = $client->zones()->pageRules()->overwrite('zone_id', 'page_rule_id', $pageRule); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'page_rule_id']])), + ]); + + $response = $client->zones()->pageRules()->delete('zone_id', 'page_rule_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/pagerules/page_rule_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/Zones/RulesTest.php b/test/Tests/Endpoints/Zones/RulesTest.php new file mode 100644 index 0000000..11f144f --- /dev/null +++ b/test/Tests/Endpoints/Zones/RulesTest.php @@ -0,0 +1,46 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'rule_id']])), + ]); + + $response = $client->zones()->rules()->create('zone_id', 'ruleset_id', [ + 'action' => 'block', + 'expression' => 'true', + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/rulesets/ruleset_id/rules', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithRuleObject() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'rule_id']])), + ]); + + $rule = (new BlockRule(['error' => 'blocked']))->enable()->setExpression('true'); + + $response = $client->zones()->rules()->create('zone_id', 'ruleset_id', $rule); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + } +} diff --git a/test/Tests/Endpoints/Zones/RulesetsTest.php b/test/Tests/Endpoints/Zones/RulesetsTest.php new file mode 100644 index 0000000..2dc31a1 --- /dev/null +++ b/test/Tests/Endpoints/Zones/RulesetsTest.php @@ -0,0 +1,91 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'ruleset_id']]])), + ]); + + $response = $client->zones()->rulesets()->get('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/rulesets', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithArray() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'ruleset_id']])), + ]); + + $response = $client->zones()->rulesets()->create('zone_id', [ + 'name' => 'my ruleset', + 'kind' => 'zone', + 'phase' => 'http_request_firewall_custom', + 'rules' => [['action' => 'block', 'expression' => 'true']], + ]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/rulesets', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldCreateWithRulesetObject() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'ruleset_id']])), + ]); + + $ruleset = (new Ruleset('my ruleset'))->addRule((new BlockRule(['error' => 'blocked']))->setExpression('true')); + + $response = $client->zones()->rulesets()->create('zone_id', $ruleset); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'ruleset_id']])), + ]); + + $response = $client->zones()->rulesets()->details('zone_id', 'ruleset_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/rulesets/ruleset_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => null])), + ]); + + $response = $client->zones()->rulesets()->delete('zone_id', 'ruleset_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/rulesets/ruleset_id', $this->lastRequest()->getUri()->getPath()); + } +} diff --git a/test/Tests/Endpoints/ZonesTest.php b/test/Tests/Endpoints/ZonesTest.php new file mode 100644 index 0000000..609e0c4 --- /dev/null +++ b/test/Tests/Endpoints/ZonesTest.php @@ -0,0 +1,170 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => [['id' => 'zone_id']]])), + ]); + + $response = $client->zones()->list('account_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones', $this->lastRequest()->getUri()->getPath()); + $this->assertStringContainsString('account%5Bid%5D=account_id', $this->lastRequest()->getUri()->getQuery()); + } + + #[Test] + public function shouldCreate() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'zone_id']])), + ]); + + $response = $client->zones()->create('account_id', 'example.com'); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones', $this->lastRequest()->getUri()->getPath()); + $this->assertSame([ + 'name' => 'example.com', + 'account' => ['id' => 'account_id'], + 'type' => 'full', + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldGetDetails() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'zone_id']])), + ]); + + $response = $client->zones()->details('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldDelete() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'zone_id']])), + ]); + + $response = $client->zones()->delete('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('DELETE', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldUpdateWithoutVanityNameServers() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'zone_id']])), + ]); + + $response = $client->zones()->update('zone_id', 'full'); + + $this->assertTrue($response->successful()); + $this->assertSame('PATCH', $this->lastRequest()->getMethod()); + $this->assertSame(['type' => 'full'], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldUpdateWithVanityNameServers() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'zone_id']])), + ]); + + $response = $client->zones()->update('zone_id', 'full', ['ns1.example.com']); + + $this->assertTrue($response->successful()); + $this->assertSame([ + 'type' => 'full', + 'vanity_name_servers' => ['ns1.example.com'], + ], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldActivationCheck() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'zone_id']])), + ]); + + $response = $client->zones()->activationCheck('zone_id'); + + $this->assertTrue($response->successful()); + $this->assertSame('PUT', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/activation_check', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldPurgeWithArray() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'zone_id']])), + ]); + + $response = $client->zones()->purge('zone_id', ['tags' => ['my-tag']]); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/zones/zone_id/purge_cache', $this->lastRequest()->getUri()->getPath()); + } + + #[Test] + public function shouldPurgeWithCachePurgeObject() + { + $client = $this->mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['id' => 'zone_id']])), + ]); + + $config = (new CachePurge())->everything(); + + $response = $client->zones()->purge('zone_id', $config); + + $this->assertTrue($response->successful()); + $this->assertSame('POST', $this->lastRequest()->getMethod()); + $this->assertSame(['purge_everything' => true], json_decode((string) $this->lastRequest()->getBody(), true)); + } + + #[Test] + public function shouldThrowWhenPurgeMissingAnyRequiredParams() + { + $client = $this->mockClient([]); + + $this->expectException(MissingArgumentException::class); + + $client->zones()->purge('zone_id', []); + } + + #[Test] + public function shouldGetCache() + { + $client = $this->mockClient([]); + + $this->assertInstanceOf(Cache::class, $client->zones()->cache()); + } +} diff --git a/test/Tests/Exceptions/MissingArgumentExceptionTest.php b/test/Tests/Exceptions/MissingArgumentExceptionTest.php new file mode 100644 index 0000000..9f166a9 --- /dev/null +++ b/test/Tests/Exceptions/MissingArgumentExceptionTest.php @@ -0,0 +1,32 @@ +assertSame( + 'One or more of required ("name", "type") parameters is missing!', + $exception->getMessage() + ); + } + + #[Test] + public function shouldBuildMessageFromString() + { + $exception = new MissingArgumentException('name'); + + $this->assertSame( + 'One or more of required ("name") parameters is missing!', + $exception->getMessage() + ); + } +} diff --git a/test/Tests/ExpressionBuilderTest.php b/test/Tests/ExpressionBuilderTest.php new file mode 100644 index 0000000..ce19683 --- /dev/null +++ b/test/Tests/ExpressionBuilderTest.php @@ -0,0 +1,159 @@ +field('ip.src')->eq('127.0.0.1'); + + $this->assertSame('ip.src eq 127.0.0.1', $builder->build()); + $this->assertSame('ip.src eq 127.0.0.1', (string) $builder); + } + + #[Test] + public function shouldQuoteNonFieldNonIpStringValues() + { + $builder = (new ExpressionBuilder())->field('http.host')->eq('example.com'); + + $this->assertSame('http.host eq "example.com"', $builder->build()); + } + + #[Test] + public function shouldNotQuoteFieldNameValues() + { + $builder = (new ExpressionBuilder())->field('ip.src')->eq('ip.dst'); + + $this->assertSame('ip.src eq ip.dst', $builder->build()); + } + + #[Test] + public function shouldFormatArrayValues() + { + $builder = (new ExpressionBuilder())->field('ip.src')->in(['127.0.0.1', '127.0.0.2']); + + $this->assertSame('ip.src in {127.0.0.1 127.0.0.2}', $builder->build()); + } + + #[Test] + public function shouldFormatNonStringNonArrayValues() + { + $builder = (new ExpressionBuilder())->field('http.request.body.size')->gt(1024); + + $this->assertSame('http.request.body.size gt 1024', $builder->build()); + } + + #[Test] + public function shouldAddExpressionWithoutOperatorOrValue() + { + $builder = (new ExpressionBuilder())->addExpression('true'); + + $this->assertSame('true', $builder->build()); + } + + #[Test] + public function shouldAddLogicalOperators() + { + $builder = (new ExpressionBuilder()) + ->field('ip.src')->eq('127.0.0.1') + ->and() + ->field('ip.dst')->eq('127.0.0.2'); + + $this->assertSame('ip.src eq 127.0.0.1 and ip.dst eq 127.0.0.2', $builder->build()); + } + + #[Test] + public function shouldNegateWithNot() + { + $builder = (new ExpressionBuilder())->not()->field('ssl'); + + $this->assertSame('not ssl', $builder->build()); + } + + #[Test] + public function shouldGroupExpressions() + { + $builder = (new ExpressionBuilder())->group(function (ExpressionBuilder $b) { + return $b->field('ip.src')->eq('127.0.0.1')->or()->field('ip.src')->eq('127.0.0.2'); + }); + + $this->assertSame('ip.src eq 127.0.0.1 or ip.src eq 127.0.0.2', $builder->build()); + } + + #[Test] + public function shouldGroupExpressionsAlongsideOthers() + { + $builder = (new ExpressionBuilder()) + ->field('ssl') + ->and() + ->group(function (ExpressionBuilder $b) { + return $b->field('ip.src')->eq('127.0.0.1'); + }); + + $this->assertSame('ssl and (ip.src eq 127.0.0.1)', $builder->build()); + } + + #[Test] + public function shouldAddFunctionWithoutOperatorOrValue() + { + $builder = (new ExpressionBuilder())->addFunction('len', 'ip.src'); + + $this->assertSame('len(ip.src)', $builder->build()); + } + + #[Test] + public function shouldAddFunctionWithOperatorAndValue() + { + $builder = (new ExpressionBuilder())->addFunction('len', 'ip.src', 'eq', 10); + + $this->assertSame('len(ip.src) eq 10', $builder->build()); + } + + #[Test] + public function shouldThrowOnInvalidFunctionField() + { + $this->expectException(InvalidArgumentException::class); + + (new ExpressionBuilder())->addFunction('len', 'not.a.real.field'); + } + + #[Test] + public function shouldThrowOnInvalidFieldName() + { + $this->expectException(InvalidArgumentException::class); + + (new ExpressionBuilder())->field('not.a.real.field'); + } + + #[Test] + public function shouldAddStrictWildcard() + { + $builder = (new ExpressionBuilder())->wildcard('*.example.com', true); + + $this->assertSame('strict wildcard "*.example.com"', $builder->build()); + } + + #[Test] + public function shouldAddNonStrictWildcard() + { + $builder = (new ExpressionBuilder())->wildcard('*.example.com', false); + + $this->assertSame('wildcard "*.example.com"', $builder->build()); + } + + #[Test] + public function shouldThrowOnUndefinedMethod() + { + $this->expectException(BadMethodCallException::class); + + (new ExpressionBuilder())->notARealMethod(); + } +} diff --git a/test/Tests/HttpClient/Exceptions/RequestExceptionTest.php b/test/Tests/HttpClient/Exceptions/RequestExceptionTest.php new file mode 100644 index 0000000..3cc70c1 --- /dev/null +++ b/test/Tests/HttpClient/Exceptions/RequestExceptionTest.php @@ -0,0 +1,35 @@ + 'something went wrong']))); + + $exception = new RequestException($response); + + $this->assertSame(499, $exception->getCode()); + $this->assertStringContainsString('HTTP request returned status code 499', $exception->getMessage()); + $this->assertStringContainsString('something went wrong', $exception->getMessage()); + $this->assertSame($response, $exception->response); + } + + #[Test] + public function shouldOmitBodySummaryWhenBodyIsEmpty() + { + $response = new Response(new PsrResponse(499, [], '')); + + $exception = new RequestException($response); + + $this->assertSame('HTTP request returned status code 499', $exception->getMessage()); + } +} diff --git a/test/Tests/HttpClient/HttpClientTest.php b/test/Tests/HttpClient/HttpClientTest.php new file mode 100644 index 0000000..26935f7 --- /dev/null +++ b/test/Tests/HttpClient/HttpClientTest.php @@ -0,0 +1,98 @@ +mockClient([]); + + $this->assertInstanceOf(GuzzleClient::class, $client->getHttpClient()->getGuzzleClient()); + } + + #[Test] + public function shouldIssueHeadRequest() + { + $client = $this->mockClient([ + new Response(200, [], ''), + ]); + + $response = $client->getHttpClient()->head('/zones'); + + $this->assertTrue($response->successful()); + $this->assertSame('HEAD', $this->lastRequest()->getMethod()); + } + + #[Test] + public function shouldIssueHeadRequestWithQuery() + { + $client = $this->mockClient([ + new Response(200, [], ''), + ]); + + $client->getHttpClient()->head('/zones', ['name' => 'example.com']); + + $this->assertStringContainsString('name=example.com', $this->lastRequest()->getUri()->getQuery()); + } + + #[TestWith([400, BadRequestException::class])] + #[TestWith([401, AuthenticationException::class])] + #[TestWith([403, PermissionDeniedException::class])] + #[TestWith([404, NotFoundException::class])] + #[TestWith([422, UnprocessableEntityException::class])] + #[TestWith([429, RateLimitException::class])] + #[TestWith([500, InternalServerException::class])] + #[TestWith([503, InternalServerException::class])] + #[TestWith([418, RequestException::class])] + #[Test] + public function shouldThrowMappedExceptionForStatus(int $status, string $expectedException) + { + $client = $this->mockClient([ + new Response($status, [], json_encode(['success' => false, 'errors' => [['message' => 'failed']]])), + ]); + + $this->expectException($expectedException); + + $client->zones()->details('zone_id'); + } + + #[Test] + public function shouldWrapConnectExceptionIntoConnectionException() + { + $request = new Request('GET', 'https://api.cloudflare.com/client/v4/zones/zone_id'); + $mock = new \GuzzleHttp\Handler\MockHandler([ + new ConnectException('Could not resolve host', $request), + ]); + + $client = new \Cloudflare\Client('token', [ + \GuzzleHttp\Middleware::history($this->requestHistory), + fn (callable $handler) => fn ($req, array $options) => $mock($req, $options), + ]); + + $this->expectException(ConnectionException::class); + + $client->zones()->details('zone_id'); + } +} diff --git a/test/Tests/HttpClient/ResponseTest.php b/test/Tests/HttpClient/ResponseTest.php new file mode 100644 index 0000000..bcfacae --- /dev/null +++ b/test/Tests/HttpClient/ResponseTest.php @@ -0,0 +1,88 @@ +assertSame('raw body', $response->body()); + } + + #[Test] + public function shouldReturnFullDecodedJsonWithoutKey() + { + $response = new Response(new PsrResponse(200, [], json_encode(['success' => true, 'result' => ['id' => 'x']]))); + + $this->assertSame([ + 'success' => true, + 'result' => ['id' => 'x'], + ], $response->json()); + } + + #[Test] + public function shouldReturnDefaultForMissingKey() + { + $response = new Response(new PsrResponse(200, [], json_encode(['result' => ['id' => 'x']]))); + + $this->assertSame('fallback', $response->json('result.missing', 'fallback')); + } + + #[Test] + public function shouldReturnUnderlyingPsrResponse() + { + $psrResponse = new PsrResponse(200, [], 'body'); + + $response = new Response($psrResponse); + + $this->assertSame($psrResponse, $response->toPsrResponse()); + } + + #[Test] + public function shouldReturnStatus() + { + $response = new Response(new PsrResponse(201, [], '')); + + $this->assertSame(201, $response->status()); + } + + #[Test] + public function shouldBeSuccessfulOnlyForStatus200() + { + $this->assertTrue((new Response(new PsrResponse(200, [], '')))->successful()); + $this->assertFalse((new Response(new PsrResponse(201, [], '')))->successful()); + } + + #[Test] + public function shouldBeFailedForNon200Status() + { + $this->assertTrue((new Response(new PsrResponse(404, [], '')))->failed()); + $this->assertFalse((new Response(new PsrResponse(200, [], '')))->failed()); + } + + #[Test] + public function shouldTraverseObjectTargets() + { + $response = new Response(new PsrResponse(200, [], '')); + + $target = (object) ['result' => (object) ['id' => 'x']]; + + $this->assertSame('x', $response->get($target, 'result.id')); + } + + #[Test] + public function shouldCastToString() + { + $response = new Response(new PsrResponse(200, [], 'raw body')); + + $this->assertSame('raw body', (string) $response); + } +} diff --git a/test/Tests/IPTest.php b/test/Tests/IPTest.php new file mode 100644 index 0000000..92599a8 --- /dev/null +++ b/test/Tests/IPTest.php @@ -0,0 +1,27 @@ +mockClient([ + new Response(200, [], json_encode(['success' => true, 'result' => ['ipv4_cidrs' => []]])), + ]); + + $response = $client->ips()->get(); + + $this->assertTrue($response->successful()); + $this->assertSame('GET', $this->lastRequest()->getMethod()); + $this->assertSame('/client/v4/ips', $this->lastRequest()->getUri()->getPath()); + } +}