From dbc1099b0b52c3a79f137876584c0cbf464d0293 Mon Sep 17 00:00:00 2001 From: Ben Croker Date: Tue, 2 Jul 2024 10:00:55 +0200 Subject: [PATCH] Add Pest tests --- composer.json | 8 +++ tests/README.md | 7 ++ tests/pest/Architecture/ArchitectureTest.php | 9 +++ .../Feature/BlacklistSecurityPolicyTest.php | 65 +++++++++++++++++++ .../Feature/WhitelistSecurityPolicyTest.php | 65 +++++++++++++++++++ tests/pest/Pest.php | 56 ++++++++++++++++ tests/pest/phpunit.xml | 12 ++++ 7 files changed, 222 insertions(+) create mode 100644 tests/README.md create mode 100644 tests/pest/Architecture/ArchitectureTest.php create mode 100644 tests/pest/Feature/BlacklistSecurityPolicyTest.php create mode 100644 tests/pest/Feature/WhitelistSecurityPolicyTest.php create mode 100644 tests/pest/Pest.php create mode 100644 tests/pest/phpunit.xml diff --git a/composer.json b/composer.json index 3cd0f78..d201165 100755 --- a/composer.json +++ b/composer.json @@ -30,8 +30,15 @@ "craftcms/ecs": "dev-main", "craftcms/phpstan": "dev-main", "craftcms/rector": "dev-main", + "markhuot/craft-pest-core": "dev-patch-1", "nystudio107/craft-closure": "^1.0.5" }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/bencroker/craft-pest-core" + } + ], "scripts": { "phpstan": "phpstan --ansi --memory-limit=1G", "check-cs": "ecs check --ansi", @@ -40,6 +47,7 @@ "config": { "allow-plugins": { "craftcms/plugin-installer": true, + "pestphp/pest-plugin": true, "yiisoft/yii2-composer": true }, "optimize-autoloader": true, diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..517560c --- /dev/null +++ b/tests/README.md @@ -0,0 +1,7 @@ +# Testing + +## Pest Tests + +```shell +php vendor/bin/pest --configuration=vendor/nystudio107/craft-twig-sandbox/tests/pest/phpunit.xml --test-directory=vendor/nystudio107/craft-twig-sandbox/tests/pest +``` diff --git a/tests/pest/Architecture/ArchitectureTest.php b/tests/pest/Architecture/ArchitectureTest.php new file mode 100644 index 0000000..339158b --- /dev/null +++ b/tests/pest/Architecture/ArchitectureTest.php @@ -0,0 +1,9 @@ +expect(['var_dump', 'die']) + ->not->toBeUsed(); diff --git a/tests/pest/Feature/BlacklistSecurityPolicyTest.php b/tests/pest/Feature/BlacklistSecurityPolicyTest.php new file mode 100644 index 0000000..54fca4d --- /dev/null +++ b/tests/pest/Feature/BlacklistSecurityPolicyTest.php @@ -0,0 +1,65 @@ + new BlacklistSecurityPolicy([ + 'twigTags' => ['set'], + ]), + ]); + $sandboxView->renderString('{% set x = 1 %}'); +})->throws(SecurityNotAllowedTagError::class); + +test('Non blacklisted tag is allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new BlacklistSecurityPolicy([ + 'twigTags' => [], + ]), + ]); + $sandboxView->renderString('{% set x = 1 %}'); +})->throwsNoExceptions(); + +test('Blacklisted filter is not allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new BlacklistSecurityPolicy([ + 'twigFilters' => ['abs'], + ]), + ]); + $sandboxView->renderString('{{ 6|abs }}'); +})->throws(SecurityNotAllowedFilterError::class); + +test('Non blacklisted filter is allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new BlacklistSecurityPolicy([ + 'twigFilters' => [], + ]), + ]); + $sandboxView->renderString('{{ 6|abs }}'); +})->throwsNoExceptions(); + +test('Blacklisted function is not allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new BlacklistSecurityPolicy([ + 'twigFunctions' => ['random'], + ]), + ]); + $sandboxView->renderString('{{ random() }}'); +})->throws(SecurityNotAllowedFunctionError::class); + +test('Non blacklisted function is allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new BlacklistSecurityPolicy([ + 'twigFunctions' => [], + ]), + ]); + $sandboxView->renderString('{{ random() }}'); +})->throwsNoExceptions(); diff --git a/tests/pest/Feature/WhitelistSecurityPolicyTest.php b/tests/pest/Feature/WhitelistSecurityPolicyTest.php new file mode 100644 index 0000000..fec72cc --- /dev/null +++ b/tests/pest/Feature/WhitelistSecurityPolicyTest.php @@ -0,0 +1,65 @@ + new WhitelistSecurityPolicy([ + 'twigTags' => ['set'], + ]), + ]); + $sandboxView->renderString('{% set x = 1 %}'); +})->throwsNoExceptions(); + +test('Non whitelisted tag is not allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new WhitelistSecurityPolicy([ + 'twigTags' => [], + ]), + ]); + $sandboxView->renderString('{% set x = 1 %}'); +})->throws(SecurityNotAllowedTagError::class); + +test('Whitelisted filter is allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new WhitelistSecurityPolicy([ + 'twigFilters' => ['abs'], + ]), + ]); + $sandboxView->renderString('{{ 6|abs }}'); +})->throwsNoExceptions(); + +test('Non whitelisted filter is not allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new WhitelistSecurityPolicy([ + 'twigFilters' => [], + ]), + ]); + $sandboxView->renderString('{{ 6|abs }}'); +})->throws(SecurityNotAllowedFilterError::class); + +test('Whitelisted function is allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new WhitelistSecurityPolicy([ + 'twigFunctions' => ['random'], + ]), + ]); + $sandboxView->renderString('{{ random() }}'); +})->throwsNoExceptions(); + +test('Non whitelisted function is not allowed', function() { + $sandboxView = new SandboxView([ + 'securityPolicy' => new WhitelistSecurityPolicy([ + 'twigFunctions' => [], + ]), + ]); + $sandboxView->renderString('{{ random() }}'); +})->throws(SecurityNotAllowedFunctionError::class); diff --git a/tests/pest/Pest.php b/tests/pest/Pest.php new file mode 100644 index 0000000..40165fe --- /dev/null +++ b/tests/pest/Pest.php @@ -0,0 +1,56 @@ +beforeEach(function() { + // Ensure exceptions are thrown, so we can catch them in our tests. + Event::on(ErrorHandler::class, ErrorHandler::EVENT_BEFORE_HANDLE_EXCEPTION, + function(ExceptionEvent $event) { + throw $event->exception; + } + ); + }) + ->in('./'); + +/* +|-------------------------------------------------------------------------- +| Expectations +|-------------------------------------------------------------------------- +| +| When you're writing tests, you often need to check that values meet certain conditions. The +| "expect()" function gives you access to a set of "expectations" methods that you can use +| to assert different things. Of course, you may extend the Expectation API at any time. +| +*/ + +/* +|-------------------------------------------------------------------------- +| Constants +|-------------------------------------------------------------------------- +*/ + +/* +|-------------------------------------------------------------------------- +| Functions +|-------------------------------------------------------------------------- +| +| While Pest is very powerful out-of-the-box, you may have some testing code specific to your +| project that you don't want to repeat in every file. Here you can also expose helpers as +| global functions to help you to reduce the number of lines of code in your test files. +| +*/ diff --git a/tests/pest/phpunit.xml b/tests/pest/phpunit.xml new file mode 100644 index 0000000..b6e27a1 --- /dev/null +++ b/tests/pest/phpunit.xml @@ -0,0 +1,12 @@ + + + + + . + + +