feat(tests): pest php (#899)

This commit is contained in:
Kyrch
2025-07-29 23:31:12 -03:00
committed by GitHub
parent a2ed59cc01
commit e58518f51a
487 changed files with 41992 additions and 54171 deletions
+8 -8
View File
@@ -54,8 +54,8 @@ trait ResolvesArguments
{
return collect($fields)
->filter(fn (Field $field) => $field instanceof FilterableField)
->map(fn (FilterableField $field) =>
collect($field->filterDirectives())
->map(
fn (FilterableField $field) => collect($field->filterDirectives())
->map(fn (FilterDirective $directive) => $directive->argument())
->toArray()
)
@@ -106,8 +106,8 @@ trait ResolvesArguments
{
return collect($fields)
->filter(fn (Field $field) => $field instanceof CreatableField)
->map(fn (Field $field) =>
new Argument($field->getColumn(), $field->type())
->map(
fn (Field $field) => new Argument($field->getColumn(), $field->type())
->required($field instanceof RequiredOnCreation)
)
->flatten()
@@ -124,8 +124,8 @@ trait ResolvesArguments
{
return collect($fields)
->filter(fn (Field $field) => $field instanceof UpdatableField)
->map(fn (Field $field) =>
new Argument($field->getColumn(), $field->type())
->map(
fn (Field $field) => new Argument($field->getColumn(), $field->type())
->required($field instanceof RequiredOnUpdate)
)
->flatten()
@@ -142,8 +142,8 @@ trait ResolvesArguments
{
return collect($fields)
->filter(fn (Field $field) => $field instanceof BindableField)
->map(fn (Field&BindableField $field) =>
new Argument($field->getName(), $field->type())
->map(
fn (Field&BindableField $field) => new Argument($field->getName(), $field->type())
->required($shouldRequire)
->directives([
'bind' => [
@@ -40,8 +40,10 @@ class PerformanceType extends EloquentType implements HasFields, HasRelations, R
public function relations(): array
{
return [
new BelongsToRelation(new SongType(), Performance::RELATION_SONG),
new MorphToRelation(new PerformanceArtistUnion(), Performance::RELATION_ARTIST),
new BelongsToRelation(new SongType(), Performance::RELATION_SONG)
->notNullable(),
new MorphToRelation(new PerformanceArtistUnion(), Performance::RELATION_ARTIST)
->notNullable(),
];
}
+3 -3
View File
@@ -58,12 +58,11 @@
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.16.0",
"brianium/paratest": "^7.8.4",
"laravel/pint": "^1.24.0",
"laravel/sail": "^1.44.0",
"mockery/mockery": "^1.6.12",
"nunomaduro/collision": "^8.8.2",
"phpunit/phpunit": "^11.5.27",
"pestphp/pest": "3.8.2",
"pestphp/pest-plugin-laravel": "^3.2",
"predis/predis": "^2.4.0",
"spatie/laravel-ignition": "^2.9.1"
},
@@ -76,6 +75,7 @@
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
Generated
+763 -44
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c103caa65639f246e64aee89ed9c823f",
"content-hash": "3fec187b8284d78cf9fbb2f595a6c296",
"packages": [
{
"name": "anourvalar/eloquent-serialize",
@@ -6083,16 +6083,16 @@
},
{
"name": "nikic/php-parser",
"version": "v5.5.0",
"version": "v5.6.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "ae59794362fe85e051a58ad36b289443f57be7a9"
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9",
"reference": "ae59794362fe85e051a58ad36b289443f57be7a9",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/221b0d0fdf1369c71047ad1d18bb5880017bbc56",
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56",
"shasum": ""
},
"require": {
@@ -6135,9 +6135,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.0"
},
"time": "2025-05-31T08:24:38+00:00"
"time": "2025-07-27T20:03:57+00:00"
},
{
"name": "nunomaduro/termwind",
@@ -12071,16 +12071,16 @@
},
{
"name": "brianium/paratest",
"version": "v7.8.4",
"version": "v7.8.3",
"source": {
"type": "git",
"url": "https://github.com/paratestphp/paratest.git",
"reference": "130a9bf0e269ee5f5b320108f794ad03e275cad4"
"reference": "a585c346ddf1bec22e51e20b5387607905604a71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/130a9bf0e269ee5f5b320108f794ad03e275cad4",
"reference": "130a9bf0e269ee5f5b320108f794ad03e275cad4",
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/a585c346ddf1bec22e51e20b5387607905604a71",
"reference": "a585c346ddf1bec22e51e20b5387607905604a71",
"shasum": ""
},
"require": {
@@ -12089,26 +12089,26 @@
"ext-reflection": "*",
"ext-simplexml": "*",
"fidry/cpu-core-counter": "^1.2.0",
"jean85/pretty-package-versions": "^2.1.1",
"jean85/pretty-package-versions": "^2.1.0",
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
"phpunit/php-code-coverage": "^11.0.10",
"phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-timer": "^7.0.1",
"phpunit/phpunit": "^11.5.24",
"sebastian/environment": "^7.2.1",
"symfony/console": "^6.4.22 || ^7.3.0",
"symfony/process": "^6.4.20 || ^7.3.0"
"phpunit/php-code-coverage": "^11.0.9 || ^12.0.4",
"phpunit/php-file-iterator": "^5.1.0 || ^6",
"phpunit/php-timer": "^7.0.1 || ^8",
"phpunit/phpunit": "^11.5.11 || ^12.0.6",
"sebastian/environment": "^7.2.0 || ^8",
"symfony/console": "^6.4.17 || ^7.2.1",
"symfony/process": "^6.4.19 || ^7.2.4"
},
"require-dev": {
"doctrine/coding-standard": "^12.0.0",
"ext-pcov": "*",
"ext-posix": "*",
"phpstan/phpstan": "^2.1.17",
"phpstan/phpstan-deprecation-rules": "^2.0.3",
"phpstan/phpstan-phpunit": "^2.0.6",
"phpstan/phpstan-strict-rules": "^2.0.4",
"squizlabs/php_codesniffer": "^3.13.2",
"symfony/filesystem": "^6.4.13 || ^7.3.0"
"phpstan/phpstan": "^2.1.6",
"phpstan/phpstan-deprecation-rules": "^2.0.1",
"phpstan/phpstan-phpunit": "^2.0.4",
"phpstan/phpstan-strict-rules": "^2.0.3",
"squizlabs/php_codesniffer": "^3.11.3",
"symfony/filesystem": "^6.4.13 || ^7.2.0"
},
"bin": [
"bin/paratest",
@@ -12148,7 +12148,7 @@
],
"support": {
"issues": "https://github.com/paratestphp/paratest/issues",
"source": "https://github.com/paratestphp/paratest/tree/v7.8.4"
"source": "https://github.com/paratestphp/paratest/tree/v7.8.3"
},
"funding": [
{
@@ -12160,7 +12160,55 @@
"type": "paypal"
}
],
"time": "2025-06-23T06:07:21+00:00"
"time": "2025-03-05T08:29:11+00:00"
},
{
"name": "doctrine/deprecations",
"version": "1.1.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/deprecations.git",
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"phpunit/phpunit": "<=7.5 || >=13"
},
"require-dev": {
"doctrine/coding-standard": "^9 || ^12 || ^13",
"phpstan/phpstan": "1.4.10 || 2.1.11",
"phpstan/phpstan-phpunit": "^1.0 || ^2",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12",
"psr/log": "^1 || ^2 || ^3"
},
"suggest": {
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Deprecations\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
"homepage": "https://www.doctrine-project.org/",
"support": {
"issues": "https://github.com/doctrine/deprecations/issues",
"source": "https://github.com/doctrine/deprecations/tree/1.1.5"
},
"time": "2025-04-07T20:06:18+00:00"
},
{
"name": "fidry/cpu-core-counter",
@@ -12779,6 +12827,404 @@
],
"time": "2025-06-25T02:12:12+00:00"
},
{
"name": "pestphp/pest",
"version": "v3.8.2",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest.git",
"reference": "c6244a8712968dbac88eb998e7ff3b5caa556b0d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pestphp/pest/zipball/c6244a8712968dbac88eb998e7ff3b5caa556b0d",
"reference": "c6244a8712968dbac88eb998e7ff3b5caa556b0d",
"shasum": ""
},
"require": {
"brianium/paratest": "^7.8.3",
"nunomaduro/collision": "^8.8.0",
"nunomaduro/termwind": "^2.3.0",
"pestphp/pest-plugin": "^3.0.0",
"pestphp/pest-plugin-arch": "^3.1.0",
"pestphp/pest-plugin-mutate": "^3.0.5",
"php": "^8.2.0",
"phpunit/phpunit": "^11.5.15"
},
"conflict": {
"filp/whoops": "<2.16.0",
"phpunit/phpunit": ">11.5.15",
"sebastian/exporter": "<6.0.0",
"webmozart/assert": "<1.11.0"
},
"require-dev": {
"pestphp/pest-dev-tools": "^3.4.0",
"pestphp/pest-plugin-type-coverage": "^3.5.0",
"symfony/process": "^7.2.5"
},
"bin": [
"bin/pest"
],
"type": "library",
"extra": {
"pest": {
"plugins": [
"Pest\\Mutate\\Plugins\\Mutate",
"Pest\\Plugins\\Configuration",
"Pest\\Plugins\\Bail",
"Pest\\Plugins\\Cache",
"Pest\\Plugins\\Coverage",
"Pest\\Plugins\\Init",
"Pest\\Plugins\\Environment",
"Pest\\Plugins\\Help",
"Pest\\Plugins\\Memory",
"Pest\\Plugins\\Only",
"Pest\\Plugins\\Printer",
"Pest\\Plugins\\ProcessIsolation",
"Pest\\Plugins\\Profile",
"Pest\\Plugins\\Retry",
"Pest\\Plugins\\Snapshot",
"Pest\\Plugins\\Verbose",
"Pest\\Plugins\\Version",
"Pest\\Plugins\\Parallel"
]
},
"phpstan": {
"includes": [
"extension.neon"
]
}
},
"autoload": {
"files": [
"src/Functions.php",
"src/Pest.php"
],
"psr-4": {
"Pest\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nuno Maduro",
"email": "enunomaduro@gmail.com"
}
],
"description": "The elegant PHP Testing Framework.",
"keywords": [
"framework",
"pest",
"php",
"test",
"testing",
"unit"
],
"support": {
"issues": "https://github.com/pestphp/pest/issues",
"source": "https://github.com/pestphp/pest/tree/v3.8.2"
},
"funding": [
{
"url": "https://www.paypal.com/paypalme/enunomaduro",
"type": "custom"
},
{
"url": "https://github.com/nunomaduro",
"type": "github"
}
],
"time": "2025-04-17T10:53:02+00:00"
},
{
"name": "pestphp/pest-plugin",
"version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest-plugin.git",
"reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e79b26c65bc11c41093b10150c1341cc5cdbea83",
"reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0.0",
"composer-runtime-api": "^2.2.2",
"php": "^8.2"
},
"conflict": {
"pestphp/pest": "<3.0.0"
},
"require-dev": {
"composer/composer": "^2.7.9",
"pestphp/pest": "^3.0.0",
"pestphp/pest-dev-tools": "^3.0.0"
},
"type": "composer-plugin",
"extra": {
"class": "Pest\\Plugin\\Manager"
},
"autoload": {
"psr-4": {
"Pest\\Plugin\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "The Pest plugin manager",
"keywords": [
"framework",
"manager",
"pest",
"php",
"plugin",
"test",
"testing",
"unit"
],
"support": {
"source": "https://github.com/pestphp/pest-plugin/tree/v3.0.0"
},
"funding": [
{
"url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L",
"type": "custom"
},
{
"url": "https://github.com/nunomaduro",
"type": "github"
},
{
"url": "https://www.patreon.com/nunomaduro",
"type": "patreon"
}
],
"time": "2024-09-08T23:21:41+00:00"
},
{
"name": "pestphp/pest-plugin-arch",
"version": "v3.1.1",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest-plugin-arch.git",
"reference": "db7bd9cb1612b223e16618d85475c6f63b9c8daa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/db7bd9cb1612b223e16618d85475c6f63b9c8daa",
"reference": "db7bd9cb1612b223e16618d85475c6f63b9c8daa",
"shasum": ""
},
"require": {
"pestphp/pest-plugin": "^3.0.0",
"php": "^8.2",
"ta-tikoma/phpunit-architecture-test": "^0.8.4"
},
"require-dev": {
"pestphp/pest": "^3.8.1",
"pestphp/pest-dev-tools": "^3.4.0"
},
"type": "library",
"extra": {
"pest": {
"plugins": [
"Pest\\Arch\\Plugin"
]
}
},
"autoload": {
"files": [
"src/Autoload.php"
],
"psr-4": {
"Pest\\Arch\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "The Arch plugin for Pest PHP.",
"keywords": [
"arch",
"architecture",
"framework",
"pest",
"php",
"plugin",
"test",
"testing",
"unit"
],
"support": {
"source": "https://github.com/pestphp/pest-plugin-arch/tree/v3.1.1"
},
"funding": [
{
"url": "https://www.paypal.com/paypalme/enunomaduro",
"type": "custom"
},
{
"url": "https://github.com/nunomaduro",
"type": "github"
}
],
"time": "2025-04-16T22:59:48+00:00"
},
{
"name": "pestphp/pest-plugin-laravel",
"version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest-plugin-laravel.git",
"reference": "6801be82fd92b96e82dd72e563e5674b1ce365fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/6801be82fd92b96e82dd72e563e5674b1ce365fc",
"reference": "6801be82fd92b96e82dd72e563e5674b1ce365fc",
"shasum": ""
},
"require": {
"laravel/framework": "^11.39.1|^12.9.2",
"pestphp/pest": "^3.8.2",
"php": "^8.2.0"
},
"require-dev": {
"laravel/dusk": "^8.2.13|dev-develop",
"orchestra/testbench": "^9.9.0|^10.2.1",
"pestphp/pest-dev-tools": "^3.4.0"
},
"type": "library",
"extra": {
"pest": {
"plugins": [
"Pest\\Laravel\\Plugin"
]
},
"laravel": {
"providers": [
"Pest\\Laravel\\PestServiceProvider"
]
}
},
"autoload": {
"files": [
"src/Autoload.php"
],
"psr-4": {
"Pest\\Laravel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "The Pest Laravel Plugin",
"keywords": [
"framework",
"laravel",
"pest",
"php",
"test",
"testing",
"unit"
],
"support": {
"source": "https://github.com/pestphp/pest-plugin-laravel/tree/v3.2.0"
},
"funding": [
{
"url": "https://www.paypal.com/paypalme/enunomaduro",
"type": "custom"
},
{
"url": "https://github.com/nunomaduro",
"type": "github"
}
],
"time": "2025-04-21T07:40:53+00:00"
},
{
"name": "pestphp/pest-plugin-mutate",
"version": "v3.0.5",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest-plugin-mutate.git",
"reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/e10dbdc98c9e2f3890095b4fe2144f63a5717e08",
"reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08",
"shasum": ""
},
"require": {
"nikic/php-parser": "^5.2.0",
"pestphp/pest-plugin": "^3.0.0",
"php": "^8.2",
"psr/simple-cache": "^3.0.0"
},
"require-dev": {
"pestphp/pest": "^3.0.8",
"pestphp/pest-dev-tools": "^3.0.0",
"pestphp/pest-plugin-type-coverage": "^3.0.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Pest\\Mutate\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sandro Gehri",
"email": "sandrogehri@gmail.com"
}
],
"description": "Mutates your code to find untested cases",
"keywords": [
"framework",
"mutate",
"mutation",
"pest",
"php",
"plugin",
"test",
"testing",
"unit"
],
"support": {
"source": "https://github.com/pestphp/pest-plugin-mutate/tree/v3.0.5"
},
"funding": [
{
"url": "https://www.paypal.com/paypalme/enunomaduro",
"type": "custom"
},
{
"url": "https://github.com/gehrisandro",
"type": "github"
},
{
"url": "https://github.com/nunomaduro",
"type": "github"
}
],
"time": "2024-09-22T07:54:40+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.4",
@@ -12970,6 +13416,228 @@
},
"time": "2025-07-22T14:01:30+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-2.x": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
},
"time": "2020-06-27T09:03:43+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "5.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "92dde6a5919e34835c506ac8c523ef095a95ed62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62",
"reference": "92dde6a5919e34835c506ac8c523ef095a95ed62",
"shasum": ""
},
"require": {
"doctrine/deprecations": "^1.1",
"ext-filter": "*",
"php": "^7.4 || ^8.0",
"phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.7",
"phpstan/phpdoc-parser": "^1.7|^2.0",
"webmozart/assert": "^1.9.1"
},
"require-dev": {
"mockery/mockery": "~1.3.5 || ~1.6.0",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-mockery": "^1.1",
"phpstan/phpstan-webmozart-assert": "^1.2",
"phpunit/phpunit": "^9.5",
"psalm/phar": "^5.26"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
},
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.2"
},
"time": "2025-04-13T19:20:35+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.10.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a",
"reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a",
"shasum": ""
},
"require": {
"doctrine/deprecations": "^1.0",
"php": "^7.3 || ^8.0",
"phpdocumentor/reflection-common": "^2.0",
"phpstan/phpdoc-parser": "^1.18|^2.0"
},
"require-dev": {
"ext-tokenizer": "*",
"phpbench/phpbench": "^1.2",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.13.9",
"vimeo/psalm": "^4.25"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0"
},
"time": "2024-11-09T15:12:26+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8",
"reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"require-dev": {
"doctrine/annotations": "^2.0",
"nikic/php-parser": "^5.3.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^9.6",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0"
},
"time": "2025-07-13T07:04:09+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "11.0.10",
@@ -13307,16 +13975,16 @@
},
{
"name": "phpunit/phpunit",
"version": "11.5.27",
"version": "11.5.15",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "446d43867314781df7e9adf79c3ec7464956fd8f"
"reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/446d43867314781df7e9adf79c3ec7464956fd8f",
"reference": "446d43867314781df7e9adf79c3ec7464956fd8f",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c",
"reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c",
"shasum": ""
},
"require": {
@@ -13326,11 +13994,11 @@
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"myclabs/deep-copy": "^1.13.3",
"myclabs/deep-copy": "^1.13.0",
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.2",
"phpunit/php-code-coverage": "^11.0.10",
"phpunit/php-code-coverage": "^11.0.9",
"phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-invoker": "^5.0.1",
"phpunit/php-text-template": "^4.0.1",
@@ -13339,7 +14007,7 @@
"sebastian/code-unit": "^3.0.3",
"sebastian/comparator": "^6.3.1",
"sebastian/diff": "^6.0.2",
"sebastian/environment": "^7.2.1",
"sebastian/environment": "^7.2.0",
"sebastian/exporter": "^6.3.0",
"sebastian/global-state": "^7.0.2",
"sebastian/object-enumerator": "^6.0.1",
@@ -13388,7 +14056,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.27"
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.15"
},
"funding": [
{
@@ -13399,20 +14067,12 @@
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2025-07-11T04:10:06+00:00"
"time": "2025-03-23T16:02:11+00:00"
},
{
"name": "predis/predis",
@@ -14918,6 +15578,65 @@
],
"time": "2025-06-03T06:57:57+00:00"
},
{
"name": "ta-tikoma/phpunit-architecture-test",
"version": "0.8.5",
"source": {
"type": "git",
"url": "https://github.com/ta-tikoma/phpunit-architecture-test.git",
"reference": "cf6fb197b676ba716837c886baca842e4db29005"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/cf6fb197b676ba716837c886baca842e4db29005",
"reference": "cf6fb197b676ba716837c886baca842e4db29005",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.18.0 || ^5.0.0",
"php": "^8.1.0",
"phpdocumentor/reflection-docblock": "^5.3.0",
"phpunit/phpunit": "^10.5.5 || ^11.0.0 || ^12.0.0",
"symfony/finder": "^6.4.0 || ^7.0.0"
},
"require-dev": {
"laravel/pint": "^1.13.7",
"phpstan/phpstan": "^1.10.52"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPUnit\\Architecture\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ni Shi",
"email": "futik0ma011@gmail.com"
},
{
"name": "Nuno Maduro",
"email": "enunomaduro@gmail.com"
}
],
"description": "Methods for testing application architecture",
"keywords": [
"architecture",
"phpunit",
"stucture",
"test",
"testing"
],
"support": {
"issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues",
"source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.5"
},
"time": "2025-04-20T20:23:40+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.2.3",
+12
View File
@@ -34,3 +34,15 @@ parameters:
- '#Access to an undefined property App\\Models\\Wiki\\Artist::\$pivot.#'
- '#Call to method assertActionMounted\(\) on an unknown class static.#'
- '#Call to method assertTableActionMounted\(\) on an unknown class static.#'
-
message: '#Call to an undefined method PHPUnit\\Framework\\TestCase::.*\(\)#'
path: tests/*
-
message: '#Call to protected method expectException\(\) of class PHPUnit\\Framework\\TestCase.#'
path: tests/*
-
message: '#Call to an undefined method Pest\\PendingCalls\\TestCall::expect\(\).#'
path: tests/Unit/ArchTest.php
-
message: '#Undefined variable: \$this#'
path: tests/Pest.php
+3
View File
@@ -120,6 +120,9 @@
"trailing_comma_in_multiline": true,
"trim_array_spaces": true,
"unary_operator_spaces": true,
"visibility_required": {
"elements": ["method", "property"]
},
"whitespace_after_comma_in_array": true
}
}
@@ -2,284 +2,217 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Fortify;
use App\Actions\Fortify\CreateNewUser;
use App\Constants\Config\ValidationConstants;
use App\Enums\Rules\ModerationService;
use App\Models\Auth\User;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Mockery\MockInterface;
use Propaganistas\LaravelDisposableEmail\Validation\Indisposable;
use Tests\TestCase;
class CreateNewUserTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Create New User Action shall require the name, email, password & terms fields.
*
* @throws ValidationException
*/
public function testRequired(): void
{
static::expectException(ValidationException::class);
test('required', function () {
$this->expectException(ValidationException::class);
$action = new CreateNewUser();
$action = new CreateNewUser();
$action->create([]);
}
$action->create([]);
});
/**
* The Create New User Action shall require usernames to be restricted to alphanumeric characters and dashes.
*
* @throws ValidationException
*/
public function testUsernameAlphaDash(): void
{
static::expectException(ValidationException::class);
test('username alpha dash', function () {
$this->expectException(ValidationException::class);
$action = new CreateNewUser();
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $this->faker->password(20),
User::ATTRIBUTE_EMAIL => $this->faker->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
}
$action->create([
User::ATTRIBUTE_NAME => fake()->password(20),
User::ATTRIBUTE_EMAIL => fake()->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
});
/**
* The Create New User Action shall require usernames to be unique.
*
* @throws ValidationException
*/
public function testUsernameUnique(): void
{
static::expectException(ValidationException::class);
test('username unique', function () {
$this->expectException(ValidationException::class);
$name = $this->faker()->word();
$name = fake()->word();
User::factory()->createOne([
User::ATTRIBUTE_NAME => $name,
]);
User::factory()->createOne([
User::ATTRIBUTE_NAME => $name,
]);
$action = new CreateNewUser();
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $name,
User::ATTRIBUTE_EMAIL => $this->faker->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
}
$action->create([
User::ATTRIBUTE_NAME => $name,
User::ATTRIBUTE_EMAIL => fake()->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
});
/**
* The Create New User Action shall create a new user.
*
* @throws ValidationException
*/
public function testCreated(): void
{
$action = new CreateNewUser();
test('created', function () {
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $this->faker()->word(),
User::ATTRIBUTE_EMAIL => $this->faker->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
$action->create([
User::ATTRIBUTE_NAME => fake()->word(),
User::ATTRIBUTE_EMAIL => fake()->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
static::assertDatabaseCount(User::class, 1);
}
$this->assertDatabaseCount(User::class, 1);
});
/**
* The Create New User Action shall create a new user if the name is not flagged by OpenAI.
*
* @throws ValidationException
*/
public function testCreatedIfNotFlaggedByOpenAi(): void
{
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
test('created if not flagged by open ai', function () {
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response([
'results' => [
0 => [
'flagged' => false,
],
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response([
'results' => [
0 => [
'flagged' => false,
],
]),
]);
],
]),
]);
$action = new CreateNewUser();
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $this->faker()->word(),
User::ATTRIBUTE_EMAIL => $this->faker->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
$action->create([
User::ATTRIBUTE_NAME => fake()->word(),
User::ATTRIBUTE_EMAIL => fake()->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
static::assertDatabaseCount(User::class, 1);
}
$this->assertDatabaseCount(User::class, 1);
});
/**
* The Create New User Action shall create a new user if the moderation service returns some error.
*
* @throws ValidationException
*/
public function testCreatedIfOpenAiFails(): void
{
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
test('created if open ai fails', function () {
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response(status: 404),
]);
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response(status: 404),
]);
$action = new CreateNewUser();
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $this->faker()->word(),
User::ATTRIBUTE_EMAIL => $this->faker->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
$action->create([
User::ATTRIBUTE_NAME => fake()->word(),
User::ATTRIBUTE_EMAIL => fake()->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
static::assertDatabaseCount(User::class, 1);
}
$this->assertDatabaseCount(User::class, 1);
});
/**
* The Create New User Action shall prohibit users from creating usernames flagged by OpenAI.
*
* @throws ValidationException
*/
public function testValidationErrorWhenFlaggedByOpenAi(): void
{
static::expectException(ValidationException::class);
test('validation error when flagged by open ai', function () {
$this->expectException(ValidationException::class);
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response([
'results' => [
0 => [
'flagged' => true,
],
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response([
'results' => [
0 => [
'flagged' => true,
],
]),
]);
],
]),
]);
$action = new CreateNewUser();
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $this->faker()->word(),
User::ATTRIBUTE_EMAIL => $this->faker->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
}
$action->create([
User::ATTRIBUTE_NAME => fake()->word(),
User::ATTRIBUTE_EMAIL => fake()->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
});
/**
* The Create New User Action shall prohibit registrations using disposable email services.
*
* @throws ValidationException
*/
public function testDisposableEmail(): void
{
static::expectException(ValidationException::class);
test('disposable email', function () {
$this->expectException(ValidationException::class);
$this->mock(Indisposable::class, function (MockInterface $mock) {
$mock->shouldReceive('validate')->once()->andReturn(false);
});
$this->mock(Indisposable::class, function (MockInterface $mock) {
$mock->shouldReceive('validate')->once()->andReturn(false);
});
$action = new CreateNewUser();
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $this->faker()->word(),
User::ATTRIBUTE_EMAIL => $this->faker->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
}
$action->create([
User::ATTRIBUTE_NAME => fake()->word(),
User::ATTRIBUTE_EMAIL => fake()->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
});
/**
* The Create New User Action shall permit registrations using indisposable email services.
*
* @throws ValidationException
*/
public function testIndisposableEmail(): void
{
$this->mock(Indisposable::class, function (MockInterface $mock) {
$mock->shouldReceive('validate')->once()->andReturn(true);
});
test('indisposable email', function () {
$this->mock(Indisposable::class, function (MockInterface $mock) {
$mock->shouldReceive('validate')->once()->andReturn(true);
});
$action = new CreateNewUser();
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $this->faker()->word(),
User::ATTRIBUTE_EMAIL => $this->faker->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
$action->create([
User::ATTRIBUTE_NAME => fake()->word(),
User::ATTRIBUTE_EMAIL => fake()->companyEmail(),
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
static::assertDatabaseCount(User::class, 1);
}
$this->assertDatabaseCount(User::class, 1);
});
/**
* The Create New User Action shall require emails to be unique.
*
* @throws ValidationException
*/
public function testEmailUnique(): void
{
static::expectException(ValidationException::class);
test('email unique', function () {
$this->expectException(ValidationException::class);
$email = $this->faker()->companyEmail();
$email = fake()->companyEmail();
User::factory()->createOne([
User::ATTRIBUTE_EMAIL => $email,
]);
User::factory()->createOne([
User::ATTRIBUTE_EMAIL => $email,
]);
$action = new CreateNewUser();
$action = new CreateNewUser();
$password = Str::password(20);
$password = Str::password(20);
$action->create([
User::ATTRIBUTE_NAME => $this->faker->word(),
User::ATTRIBUTE_EMAIL => $email,
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
}
}
$action->create([
User::ATTRIBUTE_NAME => fake()->word(),
User::ATTRIBUTE_EMAIL => $email,
User::ATTRIBUTE_PASSWORD => $password,
'password_confirmation' => $password,
'terms' => 'terms',
]);
});
@@ -2,331 +2,258 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Fortify;
use App\Actions\Fortify\UpdateUserProfileInformation;
use App\Constants\Config\ValidationConstants;
use App\Enums\Rules\ModerationService;
use App\Models\Auth\User;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Notification;
use Illuminate\Validation\ValidationException;
use Mockery\MockInterface;
use Propaganistas\LaravelDisposableEmail\Validation\Indisposable;
use Tests\TestCase;
class UpdateUserProfileInformationTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Update User Profile Information Action shall require the name, email, password & terms fields.
*
* @throws ValidationException
*/
public function testRequired(): void
{
static::expectException(ValidationException::class);
test('required', function () {
$this->expectException(ValidationException::class);
$user = User::factory()->createOne();
$user = User::factory()->createOne();
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, []);
}
$action->update($user, []);
});
/**
* The Update User Profile Information Action shall require usernames to be restricted to alphanumeric characters and dashes.
*
* @throws ValidationException
*/
public function testUsernameAlphaDash(): void
{
static::expectException(ValidationException::class);
test('username alpha dash', function () {
$this->expectException(ValidationException::class);
$user = User::factory()->createOne();
$user = User::factory()->createOne();
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_NAME => $this->faker->password(20),
]);
}
$action->update($user, [
User::ATTRIBUTE_NAME => fake()->password(20),
]);
});
/**
* The Update User Profile Information Action shall require usernames to be unique.
*
* @throws ValidationException
*/
public function testUsernameUnique(): void
{
static::expectException(ValidationException::class);
test('username unique', function () {
$this->expectException(ValidationException::class);
$name = $this->faker()->word();
$name = fake()->word();
User::factory()->createOne([
User::ATTRIBUTE_NAME => $name,
]);
User::factory()->createOne([
User::ATTRIBUTE_NAME => $name,
]);
$user = User::factory()->createOne();
$user = User::factory()->createOne();
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
}
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
});
/**
* The Update User Profile Information Action shall update the user name.
*
* @throws ValidationException
*/
public function testUpdateName(): void
{
$name = $this->faker->unique()->word();
test('update name', function () {
$name = fake()->unique()->word();
$user = User::factory()->createOne([
User::ATTRIBUTE_NAME => $this->faker->unique()->word(),
]);
$user = User::factory()->createOne([
User::ATTRIBUTE_NAME => fake()->unique()->word(),
]);
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
static::assertDatabaseCount(User::class, 1);
static::assertDatabaseHas(User::class, [
User::ATTRIBUTE_NAME => $name,
]);
static::assertDatabaseMissing(User::class, [
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
}
$this->assertDatabaseCount(User::class, 1);
$this->assertDatabaseHas(User::class, [
User::ATTRIBUTE_NAME => $name,
]);
$this->assertDatabaseMissing(User::class, [
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
});
/**
* The Update User Profile Information Action shall update the user email.
*
* @throws ValidationException
*/
public function testUpdateEmail(): void
{
Notification::fake();
test('update email', function () {
Notification::fake();
$email = $this->faker->unique()->companyEmail();
$email = fake()->unique()->companyEmail();
$user = User::factory()->createOne([
User::ATTRIBUTE_EMAIL => $this->faker->unique()->companyEmail(),
]);
$user = User::factory()->createOne([
User::ATTRIBUTE_EMAIL => fake()->unique()->companyEmail(),
]);
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_EMAIL => $email,
]);
$action->update($user, [
User::ATTRIBUTE_EMAIL => $email,
]);
static::assertDatabaseCount(User::class, 1);
static::assertDatabaseHas(User::class, [
User::ATTRIBUTE_EMAIL => $email,
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
$this->assertDatabaseCount(User::class, 1);
$this->assertDatabaseHas(User::class, [
User::ATTRIBUTE_EMAIL => $email,
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
Notification::assertSentTimes(VerifyEmail::class, 1);
}
Notification::assertSentTimes(VerifyEmail::class, 1);
});
/**
* The Update User Profile Information Action shall update the user if the name is not flagged by OpenAI.
*
* @throws ValidationException
*/
public function testCreatedIfNotFlaggedByOpenAi(): void
{
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
test('created if not flagged by open ai', function () {
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response([
'results' => [
0 => [
'flagged' => false,
],
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response([
'results' => [
0 => [
'flagged' => false,
],
]),
]);
],
]),
]);
$name = $this->faker->unique()->word();
$name = fake()->unique()->word();
$user = User::factory()->createOne([
User::ATTRIBUTE_NAME => $this->faker->unique()->word(),
]);
$user = User::factory()->createOne([
User::ATTRIBUTE_NAME => fake()->unique()->word(),
]);
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
static::assertDatabaseCount(User::class, 1);
static::assertDatabaseHas(User::class, [
User::ATTRIBUTE_NAME => $name,
]);
static::assertDatabaseMissing(User::class, [
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
}
$this->assertDatabaseCount(User::class, 1);
$this->assertDatabaseHas(User::class, [
User::ATTRIBUTE_NAME => $name,
]);
$this->assertDatabaseMissing(User::class, [
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
});
/**
* The Update User Profile Information Action shall update the user if the moderation service returns some error.
*
* @throws ValidationException
*/
public function testCreatedIfOpenAiFails(): void
{
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
test('created if open ai fails', function () {
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response(status: 404),
]);
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response(status: 404),
]);
$name = $this->faker->unique()->word();
$name = fake()->unique()->word();
$user = User::factory()->createOne([
User::ATTRIBUTE_NAME => $this->faker->unique()->word(),
]);
$user = User::factory()->createOne([
User::ATTRIBUTE_NAME => fake()->unique()->word(),
]);
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
static::assertDatabaseCount(User::class, 1);
static::assertDatabaseHas(User::class, [
User::ATTRIBUTE_NAME => $name,
]);
static::assertDatabaseMissing(User::class, [
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
}
$this->assertDatabaseCount(User::class, 1);
$this->assertDatabaseHas(User::class, [
User::ATTRIBUTE_NAME => $name,
]);
$this->assertDatabaseMissing(User::class, [
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
});
/**
* The Update User Profile Information Action shall prohibit users from updating usernames flagged by OpenAI.
*
* @throws ValidationException
*/
public function testValidationErrorWhenFlaggedByOpenAi(): void
{
static::expectException(ValidationException::class);
test('validation error when flagged by open ai', function () {
$this->expectException(ValidationException::class);
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
Config::set(ValidationConstants::MODERATION_SERVICE_QUALIFIED, ModerationService::OPENAI->value);
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response([
'results' => [
0 => [
'flagged' => true,
],
Http::fake([
'https://api.openai.com/v1/moderations' => Http::response([
'results' => [
0 => [
'flagged' => true,
],
]),
]);
],
]),
]);
$name = $this->faker->unique()->word();
$name = fake()->unique()->word();
$user = User::factory()->createOne([
User::ATTRIBUTE_NAME => $this->faker->unique()->word(),
]);
$user = User::factory()->createOne([
User::ATTRIBUTE_NAME => fake()->unique()->word(),
]);
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
}
$action->update($user, [
User::ATTRIBUTE_NAME => $name,
]);
});
/**
* The Update User Profile Information Action shall prohibit updating user emails using disposable email services.
*
* @throws ValidationException
*/
public function testDisposableEmail(): void
{
static::expectException(ValidationException::class);
test('disposable email', function () {
$this->expectException(ValidationException::class);
$this->mock(Indisposable::class, function (MockInterface $mock) {
$mock->shouldReceive('validate')->once()->andReturn(false);
});
$this->mock(Indisposable::class, function (MockInterface $mock) {
$mock->shouldReceive('validate')->once()->andReturn(false);
});
$email = $this->faker->unique()->companyEmail();
$email = fake()->unique()->companyEmail();
$user = User::factory()->createOne([
User::ATTRIBUTE_EMAIL => $this->faker->unique()->companyEmail(),
]);
$user = User::factory()->createOne([
User::ATTRIBUTE_EMAIL => fake()->unique()->companyEmail(),
]);
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_EMAIL => $email,
]);
}
$action->update($user, [
User::ATTRIBUTE_EMAIL => $email,
]);
});
/**
* The Update User Profile Information Action shall permit updating user emails using indisposable email services.
*
* @throws ValidationException
*/
public function testIndisposableEmail(): void
{
Notification::fake();
test('indisposable email', function () {
Notification::fake();
$this->mock(Indisposable::class, function (MockInterface $mock) {
$mock->shouldReceive('validate')->once()->andReturn(true);
});
$this->mock(Indisposable::class, function (MockInterface $mock) {
$mock->shouldReceive('validate')->once()->andReturn(true);
});
$email = $this->faker->unique()->companyEmail();
$email = fake()->unique()->companyEmail();
$user = User::factory()->createOne([
User::ATTRIBUTE_EMAIL => $this->faker->unique()->companyEmail(),
]);
$user = User::factory()->createOne([
User::ATTRIBUTE_EMAIL => fake()->unique()->companyEmail(),
]);
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_EMAIL => $email,
]);
$action->update($user, [
User::ATTRIBUTE_EMAIL => $email,
]);
static::assertDatabaseCount(User::class, 1);
static::assertDatabaseHas(User::class, [
User::ATTRIBUTE_EMAIL => $email,
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
$this->assertDatabaseCount(User::class, 1);
$this->assertDatabaseHas(User::class, [
User::ATTRIBUTE_EMAIL => $email,
User::ATTRIBUTE_EMAIL_VERIFIED_AT => null,
]);
Notification::assertSentTimes(VerifyEmail::class, 1);
}
Notification::assertSentTimes(VerifyEmail::class, 1);
});
/**
* The Update User Profile Information Action shall require emails to be unique.
*
* @throws ValidationException
*/
public function testEmailUnique(): void
{
static::expectException(ValidationException::class);
test('email unique', function () {
$this->expectException(ValidationException::class);
$email = $this->faker()->companyEmail();
$email = fake()->companyEmail();
User::factory()->createOne([
User::ATTRIBUTE_EMAIL => $email,
]);
User::factory()->createOne([
User::ATTRIBUTE_EMAIL => $email,
]);
$user = User::factory()->createOne();
$user = User::factory()->createOne();
$action = new UpdateUserProfileInformation();
$action = new UpdateUserProfileInformation();
$action->update($user, [
User::ATTRIBUTE_EMAIL => $email,
]);
}
}
$action->update($user, [
User::ATTRIBUTE_EMAIL => $email,
]);
});
@@ -2,79 +2,59 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Models\List\Playlist;
use App\Actions\Models\List\Playlist\InsertTrackAfterAction;
use App\Models\List\Playlist;
use App\Models\List\Playlist\PlaylistTrack;
use App\Models\Wiki\Video;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class InsertTrackAfterTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Insert Track After Action shall set the track as the playlist's last track if inserting after the last track.
*
* @throws Exception
*/
public function testLastTrack(): void
{
$playlist = Playlist::factory()
->tracks($this->faker->numberBetween(2, 9))
->createOne();
test('last track', function () {
$playlist = Playlist::factory()
->tracks(fake()->numberBetween(2, 9))
->createOne();
$last = $playlist->last;
$last = $playlist->last;
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$action = new InsertTrackAfterAction();
$action = new InsertTrackAfterAction();
$action->insertAfter($playlist, $track, $last);
$action->insertAfter($playlist, $track, $last);
static::assertTrue($playlist->last()->is($track));
$this->assertTrue($playlist->last()->is($track));
static::assertTrue($last->next()->is($track));
$this->assertTrue($last->next()->is($track));
static::assertTrue($track->previous()->is($last));
static::assertTrue($track->next()->doesntExist());
}
$this->assertTrue($track->previous()->is($last));
$this->assertTrue($track->next()->doesntExist());
});
/**
* The Insert Track After Action shall set the track as the first track's next track if inserting after it.
*
* @throws Exception
*/
public function testFirstTrack(): void
{
$playlist = Playlist::factory()
->tracks($this->faker->numberBetween(2, 9))
->createOne();
test('first track', function () {
$playlist = Playlist::factory()
->tracks(fake()->numberBetween(2, 9))
->createOne();
$first = $playlist->first;
$first = $playlist->first;
$next = $first->next;
$next = $first->next;
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$action = new InsertTrackAfterAction();
$action = new InsertTrackAfterAction();
$action->insertAfter($playlist, $track, $first);
$action->insertAfter($playlist, $track, $first);
static::assertTrue($playlist->first()->is($first));
$this->assertTrue($playlist->first()->is($first));
static::assertTrue($first->next()->is($track));
$this->assertTrue($first->next()->is($track));
static::assertTrue($track->previous()->is($first));
static::assertTrue($track->next()->is($next));
}
}
$this->assertTrue($track->previous()->is($first));
$this->assertTrue($track->next()->is($next));
});
@@ -2,79 +2,59 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Models\List\Playlist;
use App\Actions\Models\List\Playlist\InsertTrackBeforeAction;
use App\Models\List\Playlist;
use App\Models\List\Playlist\PlaylistTrack;
use App\Models\Wiki\Video;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class InsertTrackBeforeTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Insert Track Before Action shall set the track as the playlist's first track if inserting before the first track.
*
* @throws Exception
*/
public function testFirstTrack(): void
{
$playlist = Playlist::factory()
->tracks($this->faker->numberBetween(2, 9))
->createOne();
test('first track', function () {
$playlist = Playlist::factory()
->tracks(fake()->numberBetween(2, 9))
->createOne();
$first = $playlist->first;
$first = $playlist->first;
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$action = new InsertTrackBeforeAction();
$action = new InsertTrackBeforeAction();
$action->insertBefore($playlist, $track, $first);
$action->insertBefore($playlist, $track, $first);
static::assertTrue($playlist->first()->is($track));
$this->assertTrue($playlist->first()->is($track));
static::assertTrue($first->previous()->is($track));
$this->assertTrue($first->previous()->is($track));
static::assertTrue($track->next()->is($first));
static::assertTrue($track->previous()->doesntExist());
}
$this->assertTrue($track->next()->is($first));
$this->assertTrue($track->previous()->doesntExist());
});
/**
* The Insert Track Before Action shall set the track as the last track's previous track if inserting before it.
*
* @throws Exception
*/
public function testLastTrack(): void
{
$playlist = Playlist::factory()
->tracks($this->faker->numberBetween(2, 9))
->createOne();
test('last track', function () {
$playlist = Playlist::factory()
->tracks(fake()->numberBetween(2, 9))
->createOne();
$last = $playlist->last;
$last = $playlist->last;
$previous = $last->previous;
$previous = $last->previous;
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$action = new InsertTrackBeforeAction();
$action = new InsertTrackBeforeAction();
$action->insertBefore($playlist, $track, $last);
$action->insertBefore($playlist, $track, $last);
static::assertTrue($playlist->last()->is($last));
$this->assertTrue($playlist->last()->is($last));
static::assertTrue($last->previous()->is($track));
$this->assertTrue($last->previous()->is($track));
static::assertTrue($track->previous()->is($previous));
static::assertTrue($track->next()->is($last));
}
}
$this->assertTrue($track->previous()->is($previous));
$this->assertTrue($track->next()->is($last));
});
@@ -2,113 +2,88 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Models\List\Playlist;
use App\Actions\Models\List\Playlist\InsertTrackAction;
use App\Models\List\Playlist;
use App\Models\List\Playlist\PlaylistTrack;
use App\Models\Wiki\Video;
use Exception;
use Tests\TestCase;
class InsertTrackTest extends TestCase
{
/**
* The Insert Track Action shall set the first inserted track as first and last.
*
* @throws Exception
*/
public function testFirstTrack(): void
{
$playlist = Playlist::factory()->createOne();
test('first track', function () {
$playlist = Playlist::factory()->createOne();
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$track = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$action = new InsertTrackAction();
$action = new InsertTrackAction();
$action->insert($playlist, $track);
$action->insert($playlist, $track);
static::assertTrue($playlist->first()->is($track));
static::assertTrue($playlist->last()->is($track));
}
$this->assertTrue($playlist->first()->is($track));
$this->assertTrue($playlist->last()->is($track));
});
/**
* The Insert Track Action shall set the second track as the first's next track and the playlist's last track.
*
* @throws Exception
*/
public function testSecondTrack(): void
{
$playlist = Playlist::factory()->createOne();
test('second track', function () {
$playlist = Playlist::factory()->createOne();
$first = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$first = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$second = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$second = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$action = new InsertTrackAction();
$action = new InsertTrackAction();
$action->insert($playlist, $first);
$action->insert($playlist, $second);
$action->insert($playlist, $first);
$action->insert($playlist, $second);
static::assertTrue($playlist->first()->is($first));
static::assertTrue($playlist->last()->is($second));
$this->assertTrue($playlist->first()->is($first));
$this->assertTrue($playlist->last()->is($second));
static::assertTrue($first->previous()->doesntExist());
static::assertTrue($first->next()->is($second));
$this->assertTrue($first->previous()->doesntExist());
$this->assertTrue($first->next()->is($second));
static::assertTrue($second->previous()->is($first));
static::assertTrue($second->next()->doesntExist());
}
$this->assertTrue($second->previous()->is($first));
$this->assertTrue($second->next()->doesntExist());
});
/**
* The Insert Track Action shall set the third track as the second's next track and the playlist's last track.
*
* @throws Exception
*/
public function testThirdTrack(): void
{
$playlist = Playlist::factory()->createOne();
test('third track', function () {
$playlist = Playlist::factory()->createOne();
$first = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$first = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$second = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$second = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$third = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$third = PlaylistTrack::factory()
->for($playlist)
->for(Video::factory())
->createOne();
$action = new InsertTrackAction();
$action = new InsertTrackAction();
$action->insert($playlist, $first);
$action->insert($playlist, $second);
$action->insert($playlist, $third);
$action->insert($playlist, $first);
$action->insert($playlist, $second);
$action->insert($playlist, $third);
static::assertTrue($playlist->first()->is($first));
static::assertTrue($playlist->last()->is($third));
$this->assertTrue($playlist->first()->is($first));
$this->assertTrue($playlist->last()->is($third));
static::assertTrue($first->previous()->doesntExist());
static::assertTrue($first->next()->is($second));
$this->assertTrue($first->previous()->doesntExist());
$this->assertTrue($first->next()->is($second));
static::assertTrue($second->previous()->is($first));
static::assertTrue($second->next()->is($third));
$this->assertTrue($second->previous()->is($first));
$this->assertTrue($second->next()->is($third));
static::assertTrue($third->previous()->is($second));
static::assertTrue($third->next()->doesntExist());
}
}
$this->assertTrue($third->previous()->is($second));
$this->assertTrue($third->next()->doesntExist());
});
@@ -2,123 +2,91 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Models\List\Playlist;
use App\Actions\Models\List\Playlist\RemoveTrackAction;
use App\Models\List\Playlist;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class RemoveTrackTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Remove Track Action shall remove the sole track.
*
* @throws Exception
*/
public function testRemoveSole(): void
{
$playlist = Playlist::factory()
->tracks(1)
->createOne();
test('remove sole', function () {
$playlist = Playlist::factory()
->tracks(1)
->createOne();
$first = $playlist->first;
$first = $playlist->first;
$action = new RemoveTrackAction();
$action = new RemoveTrackAction();
$action->remove($playlist, $first);
$action->remove($playlist, $first);
static::assertTrue($playlist->first()->doesntExist());
static::assertTrue($playlist->last()->doesntExist());
$this->assertTrue($playlist->first()->doesntExist());
$this->assertTrue($playlist->last()->doesntExist());
static::assertTrue($first->previous()->doesntExist());
static::assertTrue($first->next()->doesntExist());
}
$this->assertTrue($first->previous()->doesntExist());
$this->assertTrue($first->next()->doesntExist());
});
/**
* The Remove Track Action shall remove the first track and set the second track as first.
*
* @throws Exception
*/
public function testRemoveFirst(): void
{
$playlist = Playlist::factory()
->tracks($this->faker->numberBetween(3, 9))
->createOne();
test('remove first', function () {
$playlist = Playlist::factory()
->tracks(fake()->numberBetween(3, 9))
->createOne();
$first = $playlist->first;
$second = $first->next;
$first = $playlist->first;
$second = $first->next;
$action = new RemoveTrackAction();
$action = new RemoveTrackAction();
$action->remove($playlist, $first);
$action->remove($playlist, $first);
static::assertTrue($playlist->first()->is($second));
$this->assertTrue($playlist->first()->is($second));
static::assertTrue($first->previous()->doesntExist());
static::assertTrue($first->next()->doesntExist());
$this->assertTrue($first->previous()->doesntExist());
$this->assertTrue($first->next()->doesntExist());
static::assertTrue($second->previous()->doesntExist());
}
$this->assertTrue($second->previous()->doesntExist());
});
/**
* The Remove Track Action shall remove the last track and set the penultimate track as last.
*
* @throws Exception
*/
public function testRemoveLast(): void
{
$playlist = Playlist::factory()
->tracks($this->faker->numberBetween(3, 9))
->createOne();
test('remove last', function () {
$playlist = Playlist::factory()
->tracks(fake()->numberBetween(3, 9))
->createOne();
$last = $playlist->last;
$previous = $last->previous;
$last = $playlist->last;
$previous = $last->previous;
$action = new RemoveTrackAction();
$action = new RemoveTrackAction();
$action->remove($playlist, $last);
$action->remove($playlist, $last);
static::assertTrue($playlist->last()->is($previous));
$this->assertTrue($playlist->last()->is($previous));
static::assertTrue($last->previous()->doesntExist());
static::assertTrue($last->next()->doesntExist());
$this->assertTrue($last->previous()->doesntExist());
$this->assertTrue($last->next()->doesntExist());
static::assertTrue($previous->next()->doesntExist());
}
$this->assertTrue($previous->next()->doesntExist());
});
/**
* The Remove Track Action shall remove the second track and fill next and previous relations.
*
* @throws Exception
*/
public function testRemoveSecond(): void
{
$playlist = Playlist::factory()
->tracks(3)
->createOne();
test('remove second', function () {
$playlist = Playlist::factory()
->tracks(3)
->createOne();
$first = $playlist->first;
$second = $first->next;
$third = $playlist->last;
$first = $playlist->first;
$second = $first->next;
$third = $playlist->last;
$action = new RemoveTrackAction();
$action = new RemoveTrackAction();
$action->remove($playlist, $second);
$action->remove($playlist, $second);
static::assertTrue($playlist->first()->is($first));
static::assertTrue($playlist->last()->is($third));
$this->assertTrue($playlist->first()->is($first));
$this->assertTrue($playlist->last()->is($third));
static::assertTrue($first->previous()->doesntExist());
static::assertTrue($first->next()->is($third));
$this->assertTrue($first->previous()->doesntExist());
$this->assertTrue($first->next()->is($third));
static::assertTrue($second->previous()->doesntExist());
static::assertTrue($second->next()->doesntExist());
$this->assertTrue($second->previous()->doesntExist());
$this->assertTrue($second->next()->doesntExist());
static::assertTrue($third->previous()->is($first));
static::assertTrue($third->next()->doesntExist());
}
}
$this->assertTrue($third->previous()->is($first));
$this->assertTrue($third->next()->doesntExist());
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Models\Wiki\Video\Audio;
use App\Actions\Models\Wiki\Video\Audio\BackfillAudioAction;
use App\Constants\Config\AudioConstants;
use App\Constants\Config\VideoConstants;
@@ -14,165 +12,129 @@ use App\Models\Wiki\Anime\AnimeTheme;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use App\Models\Wiki\Audio;
use App\Models\Wiki\Video;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Tests\TestCase;
class BackfillVideoAudioTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Backfill Audio Action shall skip the Anime if the relation already exists.
*
* @throws Exception
*/
public function testSkipped(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('skipped', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$video = Video::factory()
->for(Audio::factory())
->createOne();
$video = Video::factory()
->for(Audio::factory())
->createOne();
$action = new BackfillAudioAction($video);
$action = new BackfillAudioAction($video);
$result = $action->handle();
$result = $action->handle();
static::assertTrue($result->getStatus() === ActionStatus::SKIPPED);
static::assertDatabaseCount(Audio::class, 1);
static::assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
$this->assertTrue($result->getStatus() === ActionStatus::SKIPPED);
$this->assertDatabaseCount(Audio::class, 1);
$this->assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
/**
* The Backfill Audio Action shall fail if the Video is not attached to any Entries.
*
* @throws Exception
*/
public function testFailedWhenNoEntries(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('failed when no entries', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$video = Video::factory()->createOne();
$video = Video::factory()->createOne();
$action = new BackfillAudioAction($video);
$action = new BackfillAudioAction($video);
$result = $action->handle();
$result = $action->handle();
static::assertTrue($result->hasFailed());
static::assertDatabaseCount(Audio::class, 0);
static::assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
$this->assertTrue($result->hasFailed());
$this->assertDatabaseCount(Audio::class, 0);
$this->assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
/**
* The Backfill Audio Action shall pass if the Video is a source.
*
* @throws Exception
*/
public function testPassesSourceVideo(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('passes source video', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$video = Video::factory()
->has(AnimeThemeEntry::factory()->for(AnimeTheme::factory()->for(Anime::factory())))
->createOne([
Video::ATTRIBUTE_PATH => $this->faker()->word().'.webm',
]);
Audio::factory()->createOne([
Audio::ATTRIBUTE_PATH => Str::replace('webm', 'ogg', $video->path),
$video = Video::factory()
->has(AnimeThemeEntry::factory()->for(AnimeTheme::factory()->for(Anime::factory())))
->createOne([
Video::ATTRIBUTE_PATH => fake()->word().'.webm',
]);
$action = new BackfillAudioAction($video);
Audio::factory()->createOne([
Audio::ATTRIBUTE_PATH => Str::replace('webm', 'ogg', $video->path),
]);
$result = $action->handle();
$action = new BackfillAudioAction($video);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertDatabaseCount(Audio::class, 1);
static::assertTrue($video->audio()->exists());
static::assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
$result = $action->handle();
/**
* The Backfill Audio Action shall pass if the Video has a higher priority source.
*
* @throws Exception
*/
public function testPassesWithHigherPrioritySource(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertDatabaseCount(Audio::class, 1);
$this->assertTrue($video->audio()->exists());
$this->assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
$entry = AnimeThemeEntry::factory()->for(AnimeTheme::factory()->for(Anime::factory()));
test('passes with higher priority source', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Video::factory()
->hasAttached($entry, [], Video::RELATION_ANIMETHEMEENTRIES)
->for(Audio::factory())
->createOne([
Video::ATTRIBUTE_SOURCE => VideoSource::BD->value,
]);
$entry = AnimeThemeEntry::factory()->for(AnimeTheme::factory()->for(Anime::factory()));
$video = Video::factory()
->hasAttached($entry, [], Video::RELATION_ANIMETHEMEENTRIES)
->createOne([
Video::ATTRIBUTE_SOURCE => VideoSource::WEB->value,
]);
Video::factory()
->hasAttached($entry, [], Video::RELATION_ANIMETHEMEENTRIES)
->for(Audio::factory())
->createOne([
Video::ATTRIBUTE_SOURCE => VideoSource::BD->value,
]);
$action = new BackfillAudioAction($video);
$video = Video::factory()
->hasAttached($entry, [], Video::RELATION_ANIMETHEMEENTRIES)
->createOne([
Video::ATTRIBUTE_SOURCE => VideoSource::WEB->value,
]);
$result = $action->handle();
$action = new BackfillAudioAction($video);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertDatabaseCount(Audio::class, 1);
static::assertTrue($video->audio()->exists());
static::assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
$result = $action->handle();
/**
* The Backfill Audio Action shall pass if the Video has a primary version source.
*
* @throws Exception
*/
public function testPassesWithPrimaryVersionSource(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertDatabaseCount(Audio::class, 1);
$this->assertTrue($video->audio()->exists());
$this->assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
test('passes with primary version source', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$videoAttributes = Video::factory()->raw();
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
$sourceAudio = Audio::factory()->createOne();
$videoAttributes = Video::factory()->raw();
Video::factory()
->has(AnimeThemeEntry::factory()->set(AnimeThemeEntry::ATTRIBUTE_VERSION, 1)->for($theme))
->for($sourceAudio)
->createOne($videoAttributes);
$sourceAudio = Audio::factory()->createOne();
Video::factory()
->has(AnimeThemeEntry::factory()->set(AnimeThemeEntry::ATTRIBUTE_VERSION, 2)->for($theme))
->for(Audio::factory())
->createOne($videoAttributes);
Video::factory()
->has(AnimeThemeEntry::factory()->set(AnimeThemeEntry::ATTRIBUTE_VERSION, 1)->for($theme))
->for($sourceAudio)
->createOne($videoAttributes);
$video = Video::factory()
->has(AnimeThemeEntry::factory()->set(AnimeThemeEntry::ATTRIBUTE_VERSION, 3)->for($theme))
->createOne($videoAttributes);
Video::factory()
->has(AnimeThemeEntry::factory()->set(AnimeThemeEntry::ATTRIBUTE_VERSION, 2)->for($theme))
->for(Audio::factory())
->createOne($videoAttributes);
$action = new BackfillAudioAction($video);
$video = Video::factory()
->has(AnimeThemeEntry::factory()->set(AnimeThemeEntry::ATTRIBUTE_VERSION, 3)->for($theme))
->createOne($videoAttributes);
$result = $action->handle();
$action = new BackfillAudioAction($video);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertDatabaseCount(Audio::class, 2);
static::assertTrue($video->audio()->is($sourceAudio));
static::assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
}
$result = $action->handle();
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertDatabaseCount(Audio::class, 2);
$this->assertTrue($video->audio()->is($sourceAudio));
$this->assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
@@ -2,109 +2,83 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Repositories\Admin\Dump;
use App\Actions\Repositories\Admin\Dump\ReconcileDumpRepositoriesAction;
use App\Constants\Config\DumpConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Admin\Dump;
use App\Repositories\Eloquent\Admin\DumpRepository as DumpDestinationRepository;
use App\Repositories\Storage\Admin\DumpRepository as DumpSourceRepository;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Mockery\MockInterface;
use Tests\TestCase;
class ReconcileDumpRepositoriesTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Reconcile Dump Repository Action shall indicate no changes were made.
*
* @throws Exception
*/
public function testNoResults(): void
{
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('no results', function () {
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$this->mock(DumpSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->mock(DumpSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileDumpRepositoriesAction();
$action = new ReconcileDumpRepositoriesAction();
$source = App::make(DumpSourceRepository::class);
$destination = App::make(DumpDestinationRepository::class);
$source = App::make(DumpSourceRepository::class);
$destination = App::make(DumpDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertFalse($result->hasChanges());
static::assertDatabaseCount(Dump::class, 0);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertFalse($result->hasChanges());
$this->assertDatabaseCount(Dump::class, 0);
});
/**
* If dumps are created, the Reconcile Dump Repository Action shall return created dumps.
*
* @throws Exception
*/
public function testCreated(): void
{
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('created', function () {
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$createdDumpCount = $this->faker->numberBetween(2, 9);
$createdDumpCount = fake()->numberBetween(2, 9);
$dumps = Dump::factory()->count($createdDumpCount)->make();
$dumps = Dump::factory()->count($createdDumpCount)->make();
$this->mock(DumpSourceRepository::class, function (MockInterface $mock) use ($dumps) {
$mock->shouldReceive('get')->once()->andReturn($dumps);
});
$this->mock(DumpSourceRepository::class, function (MockInterface $mock) use ($dumps) {
$mock->shouldReceive('get')->once()->andReturn($dumps);
});
$action = new ReconcileDumpRepositoriesAction();
$action = new ReconcileDumpRepositoriesAction();
$source = App::make(DumpSourceRepository::class);
$destination = App::make(DumpDestinationRepository::class);
$source = App::make(DumpSourceRepository::class);
$destination = App::make(DumpDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($createdDumpCount, $result->getCreated());
static::assertDatabaseCount(Dump::class, $createdDumpCount);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($createdDumpCount, $result->getCreated());
$this->assertDatabaseCount(Dump::class, $createdDumpCount);
});
/**
* If dumps are deleted, the Reconcile Dump Repository Action shall return deleted dumps.
*
* @throws Exception
*/
public function testDeleted(): void
{
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('deleted', function () {
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$deletedDumpCount = $this->faker->numberBetween(2, 9);
$deletedDumpCount = fake()->numberBetween(2, 9);
Dump::factory()->count($deletedDumpCount)->create();
Dump::factory()->count($deletedDumpCount)->create();
$this->mock(DumpSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->mock(DumpSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileDumpRepositoriesAction();
$action = new ReconcileDumpRepositoriesAction();
$source = App::make(DumpSourceRepository::class);
$destination = App::make(DumpDestinationRepository::class);
$source = App::make(DumpSourceRepository::class);
$destination = App::make(DumpDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($deletedDumpCount, $result->getDeleted());
static::assertEmpty(Dump::all());
}
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($deletedDumpCount, $result->getDeleted());
$this->assertEmpty(Dump::all());
});
@@ -2,143 +2,111 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Repositories\Wiki\Audio;
use App\Actions\Repositories\Wiki\Audio\ReconcileAudioRepositoriesAction;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Audio;
use App\Repositories\Eloquent\Wiki\AudioRepository as AudioDestinationRepository;
use App\Repositories\Storage\Wiki\AudioRepository;
use App\Repositories\Storage\Wiki\AudioRepository as AudioSourceRepository;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Mockery\MockInterface;
use Tests\TestCase;
class ReconcileAudioRepositoriesTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Reconcile Audio Repository Action shall indicate no changes were made.
*
* @throws Exception
*/
public function testNoResults(): void
{
$this->mock(AudioSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
test('no results', function () {
$this->mock(AudioSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileAudioRepositoriesAction();
$action = new ReconcileAudioRepositoriesAction();
$source = App::make(AudioSourceRepository::class);
$destination = App::make(AudioDestinationRepository::class);
$source = App::make(AudioSourceRepository::class);
$destination = App::make(AudioDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertFalse($result->hasChanges());
static::assertDatabaseCount(Audio::class, 0);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertFalse($result->hasChanges());
$this->assertDatabaseCount(Audio::class, 0);
});
test('created', function () {
$createdAudioCount = fake()->numberBetween(2, 9);
$audios = Audio::factory()->count($createdAudioCount)->make();
$this->mock(AudioSourceRepository::class, function (MockInterface $mock) use ($audios) {
$mock->shouldReceive('get')->once()->andReturn($audios);
});
$action = new ReconcileAudioRepositoriesAction();
$source = App::make(AudioSourceRepository::class);
$destination = App::make(AudioDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($createdAudioCount, $result->getCreated());
$this->assertDatabaseCount(Audio::class, $createdAudioCount);
});
test('deleted', function () {
$deletedAudioCount = fake()->numberBetween(2, 9);
$audios = Audio::factory()->count($deletedAudioCount)->create();
$this->mock(AudioSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileAudioRepositoriesAction();
$source = App::make(AudioSourceRepository::class);
$destination = App::make(AudioDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($deletedAudioCount, $result->getDeleted());
$this->assertDatabaseCount(Audio::class, $deletedAudioCount);
foreach ($audios as $audio) {
$this->assertSoftDeleted($audio);
}
});
/**
* If audios are created, the Reconcile Audio Repository Action shall return created audios.
*
* @throws Exception
*/
public function testCreated(): void
{
$createdAudioCount = $this->faker->numberBetween(2, 9);
test('updated', function () {
$updatedAudioCount = fake()->numberBetween(2, 9);
$audios = Audio::factory()->count($createdAudioCount)->make();
$basenames = collect(fake()->words($updatedAudioCount));
$this->mock(AudioSourceRepository::class, function (MockInterface $mock) use ($audios) {
$mock->shouldReceive('get')->once()->andReturn($audios);
});
Audio::factory()
->count($updatedAudioCount)
->sequence(fn ($sequence) => [Audio::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$action = new ReconcileAudioRepositoriesAction();
$sourceAudios = Audio::factory()
->count($updatedAudioCount)
->sequence(fn ($sequence) => [Audio::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->make();
$source = App::make(AudioSourceRepository::class);
$destination = App::make(AudioDestinationRepository::class);
$this->mock(AudioRepository::class, function (MockInterface $mock) use ($sourceAudios) {
$mock->shouldReceive('get')->once()->andReturn($sourceAudios);
});
$result = $action->reconcileRepositories($source, $destination);
$action = new ReconcileAudioRepositoriesAction();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($createdAudioCount, $result->getCreated());
static::assertDatabaseCount(Audio::class, $createdAudioCount);
}
$source = App::make(AudioSourceRepository::class);
$destination = App::make(AudioDestinationRepository::class);
/**
* If audios are deleted, the Reconcile Audio Repository Action shall return deleted audios.
*
* @throws Exception
*/
public function testDeleted(): void
{
$deletedAudioCount = $this->faker->numberBetween(2, 9);
$result = $action->reconcileRepositories($source, $destination);
$audios = Audio::factory()->count($deletedAudioCount)->create();
$this->mock(AudioSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileAudioRepositoriesAction();
$source = App::make(AudioSourceRepository::class);
$destination = App::make(AudioDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($deletedAudioCount, $result->getDeleted());
static::assertDatabaseCount(Audio::class, $deletedAudioCount);
foreach ($audios as $audio) {
static::assertSoftDeleted($audio);
}
}
/**
* If audios are updated, the Reconcile Audio Repository Action shall return updated audios.
*
* @throws Exception
*/
public function testUpdated(): void
{
$updatedAudioCount = $this->faker->numberBetween(2, 9);
$basenames = collect($this->faker->words($updatedAudioCount));
Audio::factory()
->count($updatedAudioCount)
->sequence(fn ($sequence) => [Audio::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$sourceAudios = Audio::factory()
->count($updatedAudioCount)
->sequence(fn ($sequence) => [Audio::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->make();
$this->mock(AudioRepository::class, function (MockInterface $mock) use ($sourceAudios) {
$mock->shouldReceive('get')->once()->andReturn($sourceAudios);
});
$action = new ReconcileAudioRepositoriesAction();
$source = App::make(AudioSourceRepository::class);
$destination = App::make(AudioDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($updatedAudioCount, $result->getUpdated());
static::assertDatabaseCount(Audio::class, $updatedAudioCount);
}
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($updatedAudioCount, $result->getUpdated());
$this->assertDatabaseCount(Audio::class, $updatedAudioCount);
});
@@ -2,143 +2,111 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Repositories\Wiki\Video;
use App\Actions\Repositories\Wiki\Video\ReconcileVideoRepositoriesAction;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Video;
use App\Repositories\Eloquent\Wiki\VideoRepository as VideoDestinationRepository;
use App\Repositories\Storage\Wiki\VideoRepository;
use App\Repositories\Storage\Wiki\VideoRepository as VideoSourceRepository;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Mockery\MockInterface;
use Tests\TestCase;
class ReconcileVideoRepositoriesTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Reconcile Video Repository Action shall indicate no changes were made.
*
* @throws Exception
*/
public function testNoResults(): void
{
$this->mock(VideoSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
test('no results', function () {
$this->mock(VideoSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileVideoRepositoriesAction();
$action = new ReconcileVideoRepositoriesAction();
$source = App::make(VideoSourceRepository::class);
$destination = App::make(VideoDestinationRepository::class);
$source = App::make(VideoSourceRepository::class);
$destination = App::make(VideoDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertFalse($result->hasChanges());
static::assertDatabaseCount(Video::class, 0);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertFalse($result->hasChanges());
$this->assertDatabaseCount(Video::class, 0);
});
test('created', function () {
$createdVideoCount = fake()->numberBetween(2, 9);
$videos = Video::factory()->count($createdVideoCount)->make();
$this->mock(VideoSourceRepository::class, function (MockInterface $mock) use ($videos) {
$mock->shouldReceive('get')->once()->andReturn($videos);
});
$action = new ReconcileVideoRepositoriesAction();
$source = App::make(VideoSourceRepository::class);
$destination = App::make(VideoDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($createdVideoCount, $result->getCreated());
$this->assertDatabaseCount(Video::class, $createdVideoCount);
});
test('deleted', function () {
$deletedVideoCount = fake()->numberBetween(2, 9);
$videos = Video::factory()->count($deletedVideoCount)->create();
$this->mock(VideoSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileVideoRepositoriesAction();
$source = App::make(VideoSourceRepository::class);
$destination = App::make(VideoDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($deletedVideoCount, $result->getDeleted());
$this->assertDatabaseCount(Video::class, $deletedVideoCount);
foreach ($videos as $video) {
$this->assertSoftDeleted($video);
}
});
/**
* If videos are created, the Reconcile Video Repository Action shall return created videos.
*
* @throws Exception
*/
public function testCreated(): void
{
$createdVideoCount = $this->faker->numberBetween(2, 9);
test('updated', function () {
$updatedVideoCount = fake()->numberBetween(2, 9);
$videos = Video::factory()->count($createdVideoCount)->make();
$basenames = collect(fake()->words($updatedVideoCount));
$this->mock(VideoSourceRepository::class, function (MockInterface $mock) use ($videos) {
$mock->shouldReceive('get')->once()->andReturn($videos);
});
Video::factory()
->count($updatedVideoCount)
->sequence(fn ($sequence) => [Video::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$action = new ReconcileVideoRepositoriesAction();
$sourceVideos = Video::factory()
->count($updatedVideoCount)
->sequence(fn ($sequence) => [Video::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->make();
$source = App::make(VideoSourceRepository::class);
$destination = App::make(VideoDestinationRepository::class);
$this->mock(VideoRepository::class, function (MockInterface $mock) use ($sourceVideos) {
$mock->shouldReceive('get')->once()->andReturn($sourceVideos);
});
$result = $action->reconcileRepositories($source, $destination);
$action = new ReconcileVideoRepositoriesAction();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($createdVideoCount, $result->getCreated());
static::assertDatabaseCount(Video::class, $createdVideoCount);
}
$source = App::make(VideoSourceRepository::class);
$destination = App::make(VideoDestinationRepository::class);
/**
* If videos are deleted, the Reconcile Video Repository Action shall return deleted videos.
*
* @throws Exception
*/
public function testDeleted(): void
{
$deletedVideoCount = $this->faker->numberBetween(2, 9);
$result = $action->reconcileRepositories($source, $destination);
$videos = Video::factory()->count($deletedVideoCount)->create();
$this->mock(VideoSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileVideoRepositoriesAction();
$source = App::make(VideoSourceRepository::class);
$destination = App::make(VideoDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($deletedVideoCount, $result->getDeleted());
static::assertDatabaseCount(Video::class, $deletedVideoCount);
foreach ($videos as $video) {
static::assertSoftDeleted($video);
}
}
/**
* If videos are updated, the Reconcile Video Repository Action shall return updated videos.
*
* @throws Exception
*/
public function testUpdated(): void
{
$updatedVideoCount = $this->faker->numberBetween(2, 9);
$basenames = collect($this->faker->words($updatedVideoCount));
Video::factory()
->count($updatedVideoCount)
->sequence(fn ($sequence) => [Video::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$sourceVideos = Video::factory()
->count($updatedVideoCount)
->sequence(fn ($sequence) => [Video::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->make();
$this->mock(VideoRepository::class, function (MockInterface $mock) use ($sourceVideos) {
$mock->shouldReceive('get')->once()->andReturn($sourceVideos);
});
$action = new ReconcileVideoRepositoriesAction();
$source = App::make(VideoSourceRepository::class);
$destination = App::make(VideoDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($updatedVideoCount, $result->getUpdated());
static::assertDatabaseCount(Video::class, $updatedVideoCount);
}
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($updatedVideoCount, $result->getUpdated());
$this->assertDatabaseCount(Video::class, $updatedVideoCount);
});
@@ -2,104 +2,78 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Repositories\Wiki\Video\Script;
use App\Actions\Repositories\Wiki\Video\Script\ReconcileScriptRepositoriesAction;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Video\VideoScript;
use App\Repositories\Eloquent\Wiki\Video\ScriptRepository as ScriptDestinationRepository;
use App\Repositories\Storage\Wiki\Video\ScriptRepository as ScriptSourceRepository;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Mockery\MockInterface;
use Tests\TestCase;
class ReconcileScriptRepositoriesTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Reconcile Script Repository Action shall indicate no changes were made.
*
* @throws Exception
*/
public function testNoResults(): void
{
$this->mock(ScriptSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
test('no results', function () {
$this->mock(ScriptSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileScriptRepositoriesAction();
$action = new ReconcileScriptRepositoriesAction();
$source = App::make(ScriptSourceRepository::class);
$destination = App::make(ScriptDestinationRepository::class);
$source = App::make(ScriptSourceRepository::class);
$destination = App::make(ScriptDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertFalse($result->hasChanges());
static::assertDatabaseCount(VideoScript::class, 0);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertFalse($result->hasChanges());
$this->assertDatabaseCount(VideoScript::class, 0);
});
test('created', function () {
$createdScriptCount = fake()->numberBetween(2, 9);
$scripts = VideoScript::factory()->count($createdScriptCount)->make();
$this->mock(ScriptSourceRepository::class, function (MockInterface $mock) use ($scripts) {
$mock->shouldReceive('get')->once()->andReturn($scripts);
});
$action = new ReconcileScriptRepositoriesAction();
$source = App::make(ScriptSourceRepository::class);
$destination = App::make(ScriptDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($createdScriptCount, $result->getCreated());
$this->assertDatabaseCount(VideoScript::class, $createdScriptCount);
});
test('deleted', function () {
$deletedScriptCount = fake()->numberBetween(2, 9);
$scripts = VideoScript::factory()->count($deletedScriptCount)->create();
$this->mock(ScriptSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileScriptRepositoriesAction();
$source = App::make(ScriptSourceRepository::class);
$destination = App::make(ScriptDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertTrue($result->hasChanges());
$this->assertCount($deletedScriptCount, $result->getDeleted());
$this->assertDatabaseCount(VideoScript::class, $deletedScriptCount);
foreach ($scripts as $script) {
$this->assertSoftDeleted($script);
}
/**
* If video scripts are created, the Reconcile Script Repository Action shall return created video scripts.
*
* @throws Exception
*/
public function testCreated(): void
{
$createdScriptCount = $this->faker->numberBetween(2, 9);
$scripts = VideoScript::factory()->count($createdScriptCount)->make();
$this->mock(ScriptSourceRepository::class, function (MockInterface $mock) use ($scripts) {
$mock->shouldReceive('get')->once()->andReturn($scripts);
});
$action = new ReconcileScriptRepositoriesAction();
$source = App::make(ScriptSourceRepository::class);
$destination = App::make(ScriptDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($createdScriptCount, $result->getCreated());
static::assertDatabaseCount(VideoScript::class, $createdScriptCount);
}
/**
* If video scripts are deleted, the Reconcile Script Repository Action shall return deleted video scripts.
*
* @throws Exception
*/
public function testDeleted(): void
{
$deletedScriptCount = $this->faker->numberBetween(2, 9);
$scripts = VideoScript::factory()->count($deletedScriptCount)->create();
$this->mock(ScriptSourceRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$action = new ReconcileScriptRepositoriesAction();
$source = App::make(ScriptSourceRepository::class);
$destination = App::make(ScriptDestinationRepository::class);
$result = $action->reconcileRepositories($source, $destination);
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertTrue($result->hasChanges());
static::assertCount($deletedScriptCount, $result->getDeleted());
static::assertDatabaseCount(VideoScript::class, $deletedScriptCount);
foreach ($scripts as $script) {
static::assertSoftDeleted($script);
}
}
}
});
@@ -2,42 +2,28 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Admin\Dump;
use App\Actions\Storage\Admin\Dump\DumpDocumentAction;
use App\Constants\Config\DumpConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Admin\Dump;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class DumpDocumentTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Database Dump Command shall output "Database dump '{dumpFile}' has been created".
*
* @throws Exception
*/
public function testDataBaseDumpOutput(): void
{
$local = Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('database dump output', function () {
$local = Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Date::setTestNow($this->faker->iso8601());
Date::setTestNow(fake()->iso8601());
$action = new DumpDocumentAction();
$action = new DumpDocumentAction();
$result = $action->handle();
$result = $action->handle();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertEmpty($local->allFiles());
static::assertCount(1, $fs->allFiles());
static::assertDatabaseCount(Dump::class, 1);
}
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertEmpty($local->allFiles());
$this->assertCount(1, $fs->allFiles());
$this->assertDatabaseCount(Dump::class, 1);
});
@@ -2,42 +2,28 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Admin\Dump;
use App\Actions\Storage\Admin\Dump\DumpWikiAction;
use App\Constants\Config\DumpConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Admin\Dump;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class DumpWikiTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Database Dump Command shall output "Database dump '{dumpFile}' has been created".
*
* @throws Exception
*/
public function testDataBaseDumpOutput(): void
{
$local = Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('database dump output', function () {
$local = Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Date::setTestNow($this->faker->iso8601());
Date::setTestNow(fake()->iso8601());
$action = new DumpWikiAction();
$action = new DumpWikiAction();
$result = $action->handle();
$result = $action->handle();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertEmpty($local->allFiles());
static::assertCount(1, $fs->allFiles());
static::assertDatabaseCount(Dump::class, 1);
}
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertEmpty($local->allFiles());
$this->assertCount(1, $fs->allFiles());
$this->assertDatabaseCount(Dump::class, 1);
});
@@ -2,76 +2,56 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Admin\Dump;
use App\Actions\Storage\Admin\Dump\DumpWikiAction;
use App\Actions\Storage\Admin\Dump\PruneDumpAction;
use App\Constants\Config\DumpConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Admin\Dump;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class PruneDumpTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Prune Dumps Action shall fail.
*
* @throws Exception
*/
public function testNoResults(): void
{
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('no results', function () {
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$action = new PruneDumpAction($this->faker->numberBetween(2, 9));
$action = new PruneDumpAction(fake()->numberBetween(2, 9));
$pruneResults = $action->handle();
$pruneResults = $action->handle();
$result = $pruneResults->toActionResult();
$result = $pruneResults->toActionResult();
static::assertEmpty($fs->allFiles());
static::assertTrue($result->hasFailed());
static::assertDatabaseCount(Dump::class, 0);
}
$this->assertEmpty($fs->allFiles());
$this->assertTrue($result->hasFailed());
$this->assertDatabaseCount(Dump::class, 0);
});
/**
* The Prune Dumps Action shall prune dumps before the specified date by hours from the present time.
*
* @throws Exception
*/
public function testPruned(): void
{
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('pruned', function () {
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$prunedCount = $this->faker->randomDigitNotNull();
$prunedCount = fake()->randomDigitNotNull();
Collection::times($prunedCount, function () {
Date::setTestNow($this->faker->iso8601());
Collection::times($prunedCount, function () {
Date::setTestNow(fake()->iso8601());
$action = new DumpWikiAction();
$action = new DumpWikiAction();
$action->handle();
});
$action->handle();
});
Date::setTestNow();
Date::setTestNow();
$action = new PruneDumpAction(-1);
$action = new PruneDumpAction(-1);
$pruneResults = $action->handle();
$pruneResults = $action->handle();
$action->then($pruneResults);
$action->then($pruneResults);
$result = $pruneResults->toActionResult();
$result = $pruneResults->toActionResult();
static::assertEmpty($fs->allFiles());
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
static::assertEmpty(Dump::all());
}
}
$this->assertEmpty($fs->allFiles());
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
$this->assertEmpty(Dump::all());
});
@@ -2,119 +2,93 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Audio;
use App\Actions\Storage\Wiki\Audio\DeleteAudioAction;
use App\Constants\Config\AudioConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Audio;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Http\Testing\MimeType;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File as FileFacade;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class DeleteAudioTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Delete Audio Action shall fail if there are no deletions.
*/
public function testDefault(): void
{
Config::set(AudioConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('default', function () {
Config::set(AudioConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$audio = Audio::factory()->createOne();
$audio = Audio::factory()->createOne();
$action = new DeleteAudioAction($audio);
$action = new DeleteAudioAction($audio);
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Delete Audio Action shall pass if there are deletions.
*/
public function testPassed(): void
{
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('passed', function () {
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $file->path(),
]);
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteAudioAction($audio);
$action = new DeleteAudioAction($audio);
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Delete Audio Action shall delete the file from the configured disks.
*/
public function testDeletedFromDisk(): void
{
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('deleted from disk', function () {
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $file->path(),
]);
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteAudioAction($audio);
$action = new DeleteAudioAction($audio);
$action->handle();
$action->handle();
static::assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
$this->assertEmpty(Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
/**
* The Delete Audio Action shall delete the audio.
*
* @throws Exception
*/
public function testAudioDeleted(): void
{
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('audio deleted', function () {
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $file->path(),
]);
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteAudioAction($audio);
$action = new DeleteAudioAction($audio);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertSoftDeleted($audio);
}
}
$this->assertSoftDeleted($audio);
});
@@ -2,133 +2,110 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Audio;
use App\Actions\Storage\Wiki\Audio\MoveAudioAction;
use App\Constants\Config\AudioConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Audio;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Http\Testing\MimeType;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File as FileFacade;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Tests\TestCase;
class MoveAudioTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Move Audio Action shall fail if there are no moves.
*/
public function testDefault(): void
{
Config::set(AudioConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('default', function () {
Config::set(AudioConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$audio = Audio::factory()->createOne();
$audio = Audio::factory()->createOne();
$action = new MoveAudioAction($audio, $this->faker->word());
$action = new MoveAudioAction($audio, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Move Audio Action shall pass if there are moves.
*/
public function testPassed(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
test('passed', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$action = new MoveAudioAction($audio, Str::replace($directory, $this->faker->unique()->word(), $audio->path));
$action = new MoveAudioAction($audio, Str::replace($directory, fake()->unique()->word(), $audio->path));
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Move Audio Action shall move the file in the configured disks.
*/
public function testMovedInDisk(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
test('moved in disk', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$from = $audio->path();
$to = Str::replace($directory, $this->faker->unique()->word(), $audio->path);
$from = $audio->path();
$to = Str::replace($directory, fake()->unique()->word(), $audio->path);
$action = new MoveAudioAction($audio, $to);
$action = new MoveAudioAction($audio, $to);
$action->handle();
$action->handle();
$fs->assertMissing($from);
$fs->assertExists($to);
}
$fs->assertMissing($from);
$fs->assertExists($to);
});
/**
* The Move Audio Action shall move the audio.
*/
public function testAudioUpdated(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
test('audio updated', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$audio = Audio::factory()->createOne([
Audio::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Audio::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Audio::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Audio::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$to = Str::replace($directory, $this->faker->unique()->word(), $audio->path);
$to = Str::replace($directory, fake()->unique()->word(), $audio->path);
$action = new MoveAudioAction($audio, $to);
$action = new MoveAudioAction($audio, $to);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertDatabaseHas(Audio::class, [Audio::ATTRIBUTE_PATH => $to]);
}
}
$this->assertDatabaseHas(Audio::class, [Audio::ATTRIBUTE_PATH => $to]);
});
@@ -2,93 +2,70 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Audio;
use App\Actions\Storage\Wiki\Audio\UploadAudioAction;
use App\Constants\Config\AudioConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Audio;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class UploadAudioTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Upload Audio Action shall fail if there are no uploads.
*/
public function testDefault(): void
{
Config::set(AudioConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
test('default', function () {
Config::set(AudioConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$action = new UploadAudioAction($file, $this->faker->word());
$action = new UploadAudioAction($file, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Upload Audio Action shall pass if given a valid file.
*/
public function testPassed(): void
{
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
test('passed', function () {
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$action = new UploadAudioAction($file, $this->faker->word());
$action = new UploadAudioAction($file, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Upload Audio Action shall upload the file to the configured disk.
*/
public function testUploadedToDisk(): void
{
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
test('uploaded to disk', function () {
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$action = new UploadAudioAction($file, $this->faker->word());
$action = new UploadAudioAction($file, fake()->word());
$action->handle();
$action->handle();
static::assertCount(1, Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
$this->assertCount(1, Storage::disk(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
/**
* The Upload Audio Action shall upload the file to the configured disk.
*/
public function testCreatedAudio(): void
{
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
test('created audio', function () {
Storage::fake(Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED));
Config::set(AudioConstants::DISKS_QUALIFIED, [Config::get(AudioConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.ogg', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.ogg', fake()->randomDigitNotNull());
$action = new UploadAudioAction($file, $this->faker->word());
$action = new UploadAudioAction($file, fake()->word());
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertDatabaseCount(Audio::class, 1);
}
}
$this->assertDatabaseCount(Audio::class, 1);
});
@@ -2,119 +2,93 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Video;
use App\Actions\Storage\Wiki\Video\DeleteVideoAction;
use App\Constants\Config\VideoConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Video;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Http\Testing\MimeType;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File as FileFacade;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class DeleteVideoTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Delete Video Action shall fail if there are no deletions.
*/
public function testDefault(): void
{
Config::set(VideoConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('default', function () {
Config::set(VideoConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$video = Video::factory()->createOne();
$video = Video::factory()->createOne();
$action = new DeleteVideoAction($video);
$action = new DeleteVideoAction($video);
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Delete Video Action shall pass if there are deletions.
*/
public function testPassed(): void
{
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('passed', function () {
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $file->path(),
]);
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteVideoAction($video);
$action = new DeleteVideoAction($video);
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Delete Video Action shall delete the file from the configured disks.
*/
public function testDeletedFromDisk(): void
{
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('deleted from disk', function () {
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $file->path(),
]);
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteVideoAction($video);
$action = new DeleteVideoAction($video);
$action->handle();
$action->handle();
static::assertEmpty(Storage::disk(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
$this->assertEmpty(Storage::disk(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
/**
* The Delete Video Action shall delete the video.
*
* @throws Exception
*/
public function testVideoDeleted(): void
{
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('video deleted', function () {
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $file->path(),
]);
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteVideoAction($video);
$action = new DeleteVideoAction($video);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertSoftDeleted($video);
}
}
$this->assertSoftDeleted($video);
});
@@ -2,133 +2,110 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Video;
use App\Actions\Storage\Wiki\Video\MoveVideoAction;
use App\Constants\Config\VideoConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Video;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Http\Testing\MimeType;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File as FileFacade;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Tests\TestCase;
class MoveVideoTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Move Video Action shall fail if there are no moves.
*/
public function testDefault(): void
{
Config::set(VideoConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('default', function () {
Config::set(VideoConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$video = Video::factory()->createOne();
$video = Video::factory()->createOne();
$action = new MoveVideoAction($video, $this->faker->word());
$action = new MoveVideoAction($video, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Move Video Action shall pass if there are moves.
*/
public function testPassed(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
test('passed', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$action = new MoveVideoAction($video, Str::replace($directory, $this->faker->unique()->word(), $video->path));
$action = new MoveVideoAction($video, Str::replace($directory, fake()->unique()->word(), $video->path));
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Move Video Action shall move the file in the configured disks.
*/
public function testMovedInDisk(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
test('moved in disk', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$from = $video->path();
$to = Str::replace($directory, $this->faker->unique()->word(), $video->path);
$from = $video->path();
$to = Str::replace($directory, fake()->unique()->word(), $video->path);
$action = new MoveVideoAction($video, $to);
$action = new MoveVideoAction($video, $to);
$action->handle();
$action->handle();
$fs->assertMissing($from);
$fs->assertExists($to);
}
$fs->assertMissing($from);
$fs->assertExists($to);
});
/**
* The Move Video Action shall move the video.
*/
public function testVideoUpdated(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
test('video updated', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$video = Video::factory()->createOne([
Video::ATTRIBUTE_BASENAME => FileFacade::basename($file->path()),
Video::ATTRIBUTE_FILENAME => FileFacade::name($file->path()),
Video::ATTRIBUTE_MIMETYPE => MimeType::from($file->path()),
Video::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$to = Str::replace($directory, $this->faker->unique()->word(), $video->path);
$to = Str::replace($directory, fake()->unique()->word(), $video->path);
$action = new MoveVideoAction($video, $to);
$action = new MoveVideoAction($video, $to);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertDatabaseHas(Video::class, [Video::ATTRIBUTE_PATH => $to]);
}
}
$this->assertDatabaseHas(Video::class, [Video::ATTRIBUTE_PATH => $to]);
});
@@ -2,105 +2,79 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Video\Script;
use App\Actions\Storage\Wiki\Video\Script\DeleteScriptAction;
use App\Constants\Config\VideoConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Video\VideoScript;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class DeleteScriptTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Delete Script Action shall fail if there are no deletions.
*/
public function testDefault(): void
{
Config::set(VideoConstants::SCRIPT_DISK_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('default', function () {
Config::set(VideoConstants::SCRIPT_DISK_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$script = VideoScript::factory()->createOne();
$script = VideoScript::factory()->createOne();
$action = new DeleteScriptAction($script);
$action = new DeleteScriptAction($script);
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Delete Script Action shall pass if there are deletions.
*/
public function testPassed(): void
{
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('passed', function () {
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $file->path(),
]);
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteScriptAction($script);
$action = new DeleteScriptAction($script);
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Delete Script Action shall delete the file from the configured disks.
*/
public function testDeletedFromDisk(): void
{
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('deleted from disk', function () {
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $file->path(),
]);
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteScriptAction($script);
$action = new DeleteScriptAction($script);
$action->handle();
$action->handle();
static::assertEmpty($fs->allFiles());
}
$this->assertEmpty($fs->allFiles());
});
/**
* The Delete Video Action shall delete the script.
*
* @throws Exception
*/
public function testVideoDeleted(): void
{
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('video deleted', function () {
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $file->path(),
]);
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $file->path(),
]);
$action = new DeleteScriptAction($script);
$action = new DeleteScriptAction($script);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertSoftDeleted($script);
}
}
$this->assertSoftDeleted($script);
});
@@ -2,119 +2,96 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Video\Script;
use App\Actions\Storage\Wiki\Video\Script\MoveScriptAction;
use App\Constants\Config\VideoConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Video\VideoScript;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Tests\TestCase;
class MoveScriptTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Move Script Action shall fail if there are no moves.
*/
public function testDefault(): void
{
Config::set(VideoConstants::SCRIPT_DISK_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('default', function () {
Config::set(VideoConstants::SCRIPT_DISK_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$script = VideoScript::factory()->createOne();
$script = VideoScript::factory()->createOne();
$action = new MoveScriptAction($script, $this->faker->word());
$action = new MoveScriptAction($script, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Move Script Action shall pass if there are moves.
*/
public function testPassed(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('passed', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$action = new MoveScriptAction($script, Str::replace($directory, $this->faker->unique()->word(), $script->path));
$action = new MoveScriptAction($script, Str::replace($directory, fake()->unique()->word(), $script->path));
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Move Script Action shall move the file in the configured disks.
*/
public function testMovedInDisk(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('moved in disk', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$from = $script->path;
$to = Str::replace($directory, $this->faker->unique()->word(), $script->path);
$from = $script->path;
$to = Str::replace($directory, fake()->unique()->word(), $script->path);
$action = new MoveScriptAction($script, $to);
$action = new MoveScriptAction($script, $to);
$action->handle();
$action->handle();
$fs->assertMissing($from);
$fs->assertExists($to);
}
$fs->assertMissing($from);
$fs->assertExists($to);
});
/**
* The Move Script Action shall move the script.
*/
public function testScriptUpdated(): void
{
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('script updated', function () {
/** @var FilesystemAdapter $fs */
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$directory = $this->faker->unique()->word();
$directory = fake()->unique()->word();
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$script = VideoScript::factory()->createOne([
VideoScript::ATTRIBUTE_PATH => $fs->putFileAs($directory, $file, $file->getClientOriginalName()),
]);
$to = Str::replace($directory, $this->faker->unique()->word(), $script->path);
$to = Str::replace($directory, fake()->unique()->word(), $script->path);
$action = new MoveScriptAction($script, $to);
$action = new MoveScriptAction($script, $to);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertDatabaseHas(VideoScript::class, [VideoScript::ATTRIBUTE_PATH => $to]);
}
}
$this->assertDatabaseHas(VideoScript::class, [VideoScript::ATTRIBUTE_PATH => $to]);
});
@@ -2,111 +2,84 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Video\Script;
use App\Actions\Storage\Wiki\Video\Script\UploadScriptAction;
use App\Constants\Config\VideoConstants;
use App\Enums\Actions\ActionStatus;
use App\Models\Wiki\Video;
use App\Models\Wiki\Video\VideoScript;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class UploadScriptTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Upload Script Action shall fail if there are no uploads.
*/
public function testDefault(): void
{
Config::set(VideoConstants::SCRIPT_DISK_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('default', function () {
Config::set(VideoConstants::SCRIPT_DISK_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$action = new UploadScriptAction($file, $this->faker->word());
$action = new UploadScriptAction($file, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Upload Script Action shall pass if given a valid file.
*/
public function testPassed(): void
{
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('passed', function () {
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$action = new UploadScriptAction($file, $this->faker->word());
$action = new UploadScriptAction($file, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Upload Script Action shall upload the file to the configured disk.
*/
public function testUploadedToDisk(): void
{
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('uploaded to disk', function () {
$fs = Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$action = new UploadScriptAction($file, $this->faker->word());
$action = new UploadScriptAction($file, fake()->word());
$action->handle();
$action->handle();
static::assertCount(1, $fs->allFiles());
}
$this->assertCount(1, $fs->allFiles());
});
/**
* The Upload Video Action shall upload the file to the configured disk.
*/
public function testCreatedVideo(): void
{
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('created video', function () {
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$action = new UploadScriptAction($file, $this->faker->word());
$action = new UploadScriptAction($file, fake()->word());
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertDatabaseCount(VideoScript::class, 1);
}
$this->assertDatabaseCount(VideoScript::class, 1);
});
/**
* The Upload Script Action shall attach the provided video.
*/
public function testAttachesVideo(): void
{
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('attaches video', function () {
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
$video = Video::factory()->createOne();
$video = Video::factory()->createOne();
$action = new UploadScriptAction($file, $this->faker->word(), $video);
$action = new UploadScriptAction($file, fake()->word(), $video);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertTrue($video->videoscript()->exists());
}
}
$this->assertTrue($video->videoscript()->exists());
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Actions\Storage\Wiki\Video;
use App\Actions\Storage\Wiki\UploadedFileAction;
use App\Actions\Storage\Wiki\Video\UploadVideoAction;
use App\Constants\Config\VideoConstants;
@@ -16,218 +14,176 @@ use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use App\Models\Wiki\Video;
use App\Models\Wiki\Video\VideoScript;
use App\Pivots\Wiki\AnimeThemeEntryVideo;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class UploadVideoTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Upload Video Action shall fail if there are no uploads.
*/
public function testDefault(): void
{
Config::set(VideoConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('default', function () {
Config::set(VideoConstants::DISKS_QUALIFIED, []);
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$action = new UploadVideoAction($file, $this->faker->word());
$action = new UploadVideoAction($file, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->hasFailed());
}
$this->assertTrue($result->hasFailed());
});
/**
* The Upload Video Action shall pass if given a valid file.
*/
public function testPassed(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
test('passed', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$action = new UploadVideoAction($file, $this->faker->word());
$action = new UploadVideoAction($file, fake()->word());
$storageResults = $action->handle();
$storageResults = $action->handle();
$result = $storageResults->toActionResult();
$result = $storageResults->toActionResult();
static::assertTrue($result->getStatus() === ActionStatus::PASSED);
}
$this->assertTrue($result->getStatus() === ActionStatus::PASSED);
});
/**
* The Upload Video Action shall upload the file to the configured disk.
*/
public function testUploadedToDisk(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
test('uploaded to disk', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$action = new UploadVideoAction($file, $this->faker->word());
$action = new UploadVideoAction($file, fake()->word());
$action->handle();
$action->handle();
static::assertCount(1, Storage::disk(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
}
$this->assertCount(1, Storage::disk(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED))->allFiles());
});
/**
* The Upload Video Action shall upload the file to the configured disk.
*
* @throws Exception
*/
public function testCreatedVideo(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
test('created video', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
Process::fake([
UploadedFileAction::formatFfprobeCommand($file) => Process::result(json_encode([
'streams' => [
0 => [
'height' => $this->faker->randomNumber(),
],
Process::fake([
UploadedFileAction::formatFfprobeCommand($file) => Process::result(json_encode([
'streams' => [
0 => [
'height' => fake()->randomNumber(),
],
])),
]);
],
])),
]);
$action = new UploadVideoAction($file, $this->faker->word());
$action = new UploadVideoAction($file, fake()->word());
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertDatabaseCount(Video::class, 1);
}
$this->assertDatabaseCount(Video::class, 1);
});
/**
* The Upload Video Action shall set additional video attributes.
*
* @throws Exception
*/
public function testSetsAttributes(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
test('sets attributes', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
Process::fake([
UploadedFileAction::formatFfprobeCommand($file) => Process::result(json_encode([
'streams' => [
0 => [
'height' => $this->faker->randomNumber(),
],
Process::fake([
UploadedFileAction::formatFfprobeCommand($file) => Process::result(json_encode([
'streams' => [
0 => [
'height' => fake()->randomNumber(),
],
])),
]);
],
])),
]);
$overlap = Arr::random(VideoOverlap::cases());
$source = Arr::random(VideoSource::cases());
$overlap = Arr::random(VideoOverlap::cases());
$source = Arr::random(VideoSource::cases());
$attributes = [
Video::ATTRIBUTE_NC => $this->faker->boolean(),
Video::ATTRIBUTE_SUBBED => $this->faker->boolean(),
Video::ATTRIBUTE_LYRICS => $this->faker->boolean(),
Video::ATTRIBUTE_UNCEN => $this->faker->boolean(),
Video::ATTRIBUTE_OVERLAP => $overlap->value,
Video::ATTRIBUTE_SOURCE => $source->value,
];
$attributes = [
Video::ATTRIBUTE_NC => fake()->boolean(),
Video::ATTRIBUTE_SUBBED => fake()->boolean(),
Video::ATTRIBUTE_LYRICS => fake()->boolean(),
Video::ATTRIBUTE_UNCEN => fake()->boolean(),
Video::ATTRIBUTE_OVERLAP => $overlap->value,
Video::ATTRIBUTE_SOURCE => $source->value,
];
$action = new UploadVideoAction($file, $this->faker->word(), $attributes);
$action = new UploadVideoAction($file, fake()->word(), $attributes);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertDatabaseHas(Video::class, $attributes);
}
$this->assertDatabaseHas(Video::class, $attributes);
});
/**
* The Upload Video Action shall attach the provided entry.
*
* @throws Exception
*/
public function testAttachesEntry(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
test('attaches entry', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
Process::fake([
UploadedFileAction::formatFfprobeCommand($file) => Process::result(json_encode([
'streams' => [
0 => [
'height' => $this->faker->randomNumber(),
],
Process::fake([
UploadedFileAction::formatFfprobeCommand($file) => Process::result(json_encode([
'streams' => [
0 => [
'height' => fake()->randomNumber(),
],
])),
]);
],
])),
]);
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$action = new UploadVideoAction(file: $file, path: $this->faker->word(), entry: $entry);
$action = new UploadVideoAction(file: $file, path: fake()->word(), entry: $entry);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
static::assertDatabaseCount(AnimeThemeEntryVideo::class, 1);
}
$this->assertDatabaseCount(AnimeThemeEntryVideo::class, 1);
});
/**
* The Upload Video Action shall attach the provided script.
*
* @throws Exception
*/
public function testAssociatesScript(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('associates script', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
Config::set(VideoConstants::DISKS_QUALIFIED, [Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED)]);
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$file = File::fake()->create($this->faker->word().'.webm', $this->faker->randomDigitNotNull());
$script = File::fake()->create($this->faker->word().'.txt', $this->faker->randomDigitNotNull());
$file = File::fake()->create(fake()->word().'.webm', fake()->randomDigitNotNull());
$script = File::fake()->create(fake()->word().'.txt', fake()->randomDigitNotNull());
Process::fake([
UploadedFileAction::formatFfprobeCommand($file) => Process::result(json_encode([
'streams' => [
0 => [
'height' => $this->faker->randomNumber(),
],
Process::fake([
UploadedFileAction::formatFfprobeCommand($file) => Process::result(json_encode([
'streams' => [
0 => [
'height' => fake()->randomNumber(),
],
])),
]);
],
])),
]);
$action = new UploadVideoAction(file: $file, path: $this->faker->word(), script: $script);
$action = new UploadVideoAction(file: $file, path: fake()->word(), script: $script);
$result = $action->handle();
$result = $action->handle();
$action->then($result);
$action->then($result);
/** @var Video $video */
$video = Video::query()->first();
/** @var Video $video */
$video = Video::query()->first();
static::assertNotNull($video);
$this->assertNotNull($video);
static::assertDatabaseHas(VideoScript::class, [VideoScript::ATTRIBUTE_VIDEO => $video->video_id]);
}
}
$this->assertDatabaseHas(VideoScript::class, [VideoScript::ATTRIBUTE_VIDEO => $video->video_id]);
});
@@ -2,74 +2,55 @@
declare(strict_types=1);
namespace Tests\Feature\Console\Commands\Repositories\Storage\Admin;
use App\Console\Commands\Repositories\Storage\Admin\DumpReconcileCommand;
use App\Constants\Config\DumpConstants;
use App\Models\Admin\Dump;
use App\Repositories\Storage\Admin\DumpRepository;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Mockery\MockInterface;
use Tests\TestCase;
class DumpReconcileTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Reconcile Dump Command shall output 'No Dumps created or deleted or updated'.
*/
public function testNoResults(): void
{
$this->mock(DumpRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
test('no results', function () {
$this->mock(DumpRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->artisan(DumpReconcileCommand::class)
->assertSuccessful()
->expectsOutput('No Dumps created or deleted or updated');
}
$this->artisan(DumpReconcileCommand::class)
->assertSuccessful()
->expectsOutput('No Dumps created or deleted or updated');
});
/**
* If dumps are created, the Reconcile Dump Command shall output '{Created Count} Dumps created, 0 Dumps deleted, 0 Dumps updated'.
*/
public function testCreated(): void
{
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('created', function () {
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$createdDumpCount = $this->faker->numberBetween(2, 9);
$createdDumpCount = fake()->numberBetween(2, 9);
$dumps = Dump::factory()->count($createdDumpCount)->make();
$dumps = Dump::factory()->count($createdDumpCount)->make();
$this->mock(DumpRepository::class, function (MockInterface $mock) use ($dumps) {
$mock->shouldReceive('get')->once()->andReturn($dumps);
});
$this->mock(DumpRepository::class, function (MockInterface $mock) use ($dumps) {
$mock->shouldReceive('get')->once()->andReturn($dumps);
});
$this->artisan(DumpReconcileCommand::class)
->assertSuccessful()
->expectsOutput("$createdDumpCount Dumps created, 0 Dumps deleted, 0 Dumps updated");
}
$this->artisan(DumpReconcileCommand::class)
->assertSuccessful()
->expectsOutput("$createdDumpCount Dumps created, 0 Dumps deleted, 0 Dumps updated");
});
/**
* If dumps are deleted, the Reconcile Dump Command shall output '0 Dumps created, {Deleted Count} Dumps deleted, 0 Dumps updated'.
*/
public function testDeleted(): void
{
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('deleted', function () {
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$deletedDumpCount = $this->faker->numberBetween(2, 9);
$deletedDumpCount = fake()->numberBetween(2, 9);
Dump::factory()->count($deletedDumpCount)->create();
Dump::factory()->count($deletedDumpCount)->create();
$this->mock(DumpRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->mock(DumpRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->artisan(DumpReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Dumps created, $deletedDumpCount Dumps deleted, 0 Dumps updated");
}
}
$this->artisan(DumpReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Dumps created, $deletedDumpCount Dumps deleted, 0 Dumps updated");
});
@@ -2,95 +2,72 @@
declare(strict_types=1);
namespace Tests\Feature\Console\Commands\Repositories\Storage\Wiki;
use App\Console\Commands\Repositories\Storage\Wiki\AudioReconcileCommand;
use App\Models\Wiki\Audio;
use App\Repositories\Storage\Wiki\AudioRepository;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Mockery\MockInterface;
use Tests\TestCase;
class AudioReconcileTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Reconcile Audio Command shall output 'No Audio created or deleted or updated'.
*/
public function testNoResults(): void
{
$this->mock(AudioRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
test('no results', function () {
$this->mock(AudioRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->artisan(AudioReconcileCommand::class)
->assertSuccessful()
->expectsOutput('No Audio created or deleted or updated');
}
$this->artisan(AudioReconcileCommand::class)
->assertSuccessful()
->expectsOutput('No Audio created or deleted or updated');
});
/**
* If audios are created, the Reconcile Audio Command shall output '{Created Count} Audio created, 0 Audio deleted, 0 Audio updated'.
*/
public function testCreated(): void
{
$createdAudioCount = $this->faker->numberBetween(2, 9);
test('created', function () {
$createdAudioCount = fake()->numberBetween(2, 9);
$audios = Audio::factory()->count($createdAudioCount)->make();
$audios = Audio::factory()->count($createdAudioCount)->make();
$this->mock(AudioRepository::class, function (MockInterface $mock) use ($audios) {
$mock->shouldReceive('get')->once()->andReturn($audios);
});
$this->mock(AudioRepository::class, function (MockInterface $mock) use ($audios) {
$mock->shouldReceive('get')->once()->andReturn($audios);
});
$this->artisan(AudioReconcileCommand::class)
->assertSuccessful()
->expectsOutput("$createdAudioCount Audio created, 0 Audio deleted, 0 Audio updated");
}
$this->artisan(AudioReconcileCommand::class)
->assertSuccessful()
->expectsOutput("$createdAudioCount Audio created, 0 Audio deleted, 0 Audio updated");
});
/**
* If audios are deleted, the Reconcile Audio Command shall output '0 Audio created, {Deleted Count} Audio deleted, 0 Audio updated'.
*/
public function testDeleted(): void
{
$deletedAudioCount = $this->faker->numberBetween(2, 9);
test('deleted', function () {
$deletedAudioCount = fake()->numberBetween(2, 9);
Audio::factory()->count($deletedAudioCount)->create();
Audio::factory()->count($deletedAudioCount)->create();
$this->mock(AudioRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->mock(AudioRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->artisan(AudioReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Audio created, $deletedAudioCount Audio deleted, 0 Audio updated");
}
$this->artisan(AudioReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Audio created, $deletedAudioCount Audio deleted, 0 Audio updated");
});
/**
* If audios are updated, the Reconcile Audio Command shall output '0 Audio created, 0 Audio deleted, {Updated Count} Audio updated'.
*/
public function testUpdated(): void
{
$updatedAudioCount = $this->faker->numberBetween(2, 9);
test('updated', function () {
$updatedAudioCount = fake()->numberBetween(2, 9);
$basenames = collect($this->faker->words($updatedAudioCount));
$basenames = collect(fake()->words($updatedAudioCount));
Audio::factory()
->count($updatedAudioCount)
->sequence(fn ($sequence) => [Audio::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
Audio::factory()
->count($updatedAudioCount)
->sequence(fn ($sequence) => [Audio::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$sourceAudios = Audio::factory()
->count($updatedAudioCount)
->sequence(fn ($sequence) => [Audio::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$sourceAudios = Audio::factory()
->count($updatedAudioCount)
->sequence(fn ($sequence) => [Audio::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$this->mock(AudioRepository::class, function (MockInterface $mock) use ($sourceAudios) {
$mock->shouldReceive('get')->once()->andReturn($sourceAudios);
});
$this->mock(AudioRepository::class, function (MockInterface $mock) use ($sourceAudios) {
$mock->shouldReceive('get')->once()->andReturn($sourceAudios);
});
$this->artisan(AudioReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Audio created, 0 Audio deleted, $updatedAudioCount Audio updated");
}
}
$this->artisan(AudioReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Audio created, 0 Audio deleted, $updatedAudioCount Audio updated");
});
@@ -2,76 +2,57 @@
declare(strict_types=1);
namespace Tests\Feature\Console\Commands\Repositories\Storage\Wiki\Video;
use App\Console\Commands\Repositories\Storage\Wiki\Video\ScriptReconcileCommand;
use App\Constants\Config\VideoConstants;
use App\Models\Wiki\Video\VideoScript;
use App\Repositories\Storage\Wiki\Video\ScriptRepository;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Mockery\MockInterface;
use Tests\TestCase;
class ScriptReconcileTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Reconcile Script Command shall output 'No Video Scripts created or deleted or updated'.
*/
public function testNoResults(): void
{
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('no results', function () {
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$this->mock(ScriptRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->mock(ScriptRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->artisan(ScriptReconcileCommand::class)
->assertSuccessful()
->expectsOutput('No Video Scripts created or deleted or updated');
}
$this->artisan(ScriptReconcileCommand::class)
->assertSuccessful()
->expectsOutput('No Video Scripts created or deleted or updated');
});
/**
* If scripts are created, the Reconcile Script Command shall output '{Created Count} Video Scripts created, 0 Video Scripts deleted, 0 Video Scripts updated'.
*/
public function testCreated(): void
{
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('created', function () {
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$createdScriptCount = $this->faker->numberBetween(2, 9);
$createdScriptCount = fake()->numberBetween(2, 9);
$scripts = VideoScript::factory()->count($createdScriptCount)->make();
$scripts = VideoScript::factory()->count($createdScriptCount)->make();
$this->mock(ScriptRepository::class, function (MockInterface $mock) use ($scripts) {
$mock->shouldReceive('get')->once()->andReturn($scripts);
});
$this->mock(ScriptRepository::class, function (MockInterface $mock) use ($scripts) {
$mock->shouldReceive('get')->once()->andReturn($scripts);
});
$this->artisan(ScriptReconcileCommand::class)
->assertSuccessful()
->expectsOutput("$createdScriptCount Video Scripts created, 0 Video Scripts deleted, 0 Video Scripts updated");
}
$this->artisan(ScriptReconcileCommand::class)
->assertSuccessful()
->expectsOutput("$createdScriptCount Video Scripts created, 0 Video Scripts deleted, 0 Video Scripts updated");
});
/**
* If scripts are deleted, the Reconcile Script Command shall output '0 Video Scripts created, {Deleted Count} Video Scripts deleted, 0 Video Scripts updated'.
*/
public function testDeleted(): void
{
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
test('deleted', function () {
Storage::fake(Config::get(VideoConstants::SCRIPT_DISK_QUALIFIED));
$deletedScriptCount = $this->faker->numberBetween(2, 9);
$deletedScriptCount = fake()->numberBetween(2, 9);
VideoScript::factory()->count($deletedScriptCount)->create();
VideoScript::factory()->count($deletedScriptCount)->create();
$this->mock(ScriptRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->mock(ScriptRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->artisan(ScriptReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Video Scripts created, $deletedScriptCount Video Scripts deleted, 0 Video Scripts updated");
}
}
$this->artisan(ScriptReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Video Scripts created, $deletedScriptCount Video Scripts deleted, 0 Video Scripts updated");
});
@@ -2,106 +2,83 @@
declare(strict_types=1);
namespace Tests\Feature\Console\Commands\Repositories\Storage\Wiki;
use App\Console\Commands\Repositories\Storage\Wiki\VideoReconcileCommand;
use App\Constants\Config\VideoConstants;
use App\Models\Wiki\Video;
use App\Repositories\Storage\Wiki\VideoRepository;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Mockery\MockInterface;
use Tests\TestCase;
class VideoReconcileTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Reconcile Video Command shall output 'No Videos created or deleted or updated'.
*/
public function testNoResults(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('no results', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$this->mock(VideoRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->mock(VideoRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->artisan(VideoReconcileCommand::class)
->assertSuccessful()
->expectsOutput('No Videos created or deleted or updated');
}
$this->artisan(VideoReconcileCommand::class)
->assertSuccessful()
->expectsOutput('No Videos created or deleted or updated');
});
/**
* If videos are created, the Reconcile Video Command shall output '{Created Count} Videos created, 0 Videos deleted, 0 Videos updated'.
*/
public function testCreated(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('created', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$createdVideoCount = $this->faker->numberBetween(2, 9);
$createdVideoCount = fake()->numberBetween(2, 9);
$videos = Video::factory()->count($createdVideoCount)->make();
$videos = Video::factory()->count($createdVideoCount)->make();
$this->mock(VideoRepository::class, function (MockInterface $mock) use ($videos) {
$mock->shouldReceive('get')->once()->andReturn($videos);
});
$this->mock(VideoRepository::class, function (MockInterface $mock) use ($videos) {
$mock->shouldReceive('get')->once()->andReturn($videos);
});
$this->artisan(VideoReconcileCommand::class)
->assertSuccessful()
->expectsOutput("$createdVideoCount Videos created, 0 Videos deleted, 0 Videos updated");
}
$this->artisan(VideoReconcileCommand::class)
->assertSuccessful()
->expectsOutput("$createdVideoCount Videos created, 0 Videos deleted, 0 Videos updated");
});
/**
* If videos are deleted, the Reconcile Video Command shall output '0 Videos created, {Deleted Count} Videos deleted, 0 Videos updated'.
*/
public function testDeleted(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('deleted', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$deletedVideoCount = $this->faker->numberBetween(2, 9);
$deletedVideoCount = fake()->numberBetween(2, 9);
Video::factory()->count($deletedVideoCount)->create();
Video::factory()->count($deletedVideoCount)->create();
$this->mock(VideoRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->mock(VideoRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('get')->once()->andReturn(Collection::make());
});
$this->artisan(VideoReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Videos created, $deletedVideoCount Videos deleted, 0 Videos updated");
}
$this->artisan(VideoReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Videos created, $deletedVideoCount Videos deleted, 0 Videos updated");
});
/**
* If videos are updated, the Reconcile Video Command shall output '0 Videos created, 0 Videos deleted, {Updated Count} Videos updated'.
*/
public function testUpdated(): void
{
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
test('updated', function () {
Storage::fake(Config::get(VideoConstants::DEFAULT_DISK_QUALIFIED));
$updatedVideoCount = $this->faker->numberBetween(2, 9);
$updatedVideoCount = fake()->numberBetween(2, 9);
$basenames = collect($this->faker->words($updatedVideoCount));
$basenames = collect(fake()->words($updatedVideoCount));
Video::factory()
->count($updatedVideoCount)
->sequence(fn ($sequence) => [Video::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
Video::factory()
->count($updatedVideoCount)
->sequence(fn ($sequence) => [Video::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$sourceVideos = Video::factory()
->count($updatedVideoCount)
->sequence(fn ($sequence) => [Video::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$sourceVideos = Video::factory()
->count($updatedVideoCount)
->sequence(fn ($sequence) => [Video::ATTRIBUTE_BASENAME => $basenames->get($sequence->index)])
->create();
$this->mock(VideoRepository::class, function (MockInterface $mock) use ($sourceVideos) {
$mock->shouldReceive('get')->once()->andReturn($sourceVideos);
});
$this->mock(VideoRepository::class, function (MockInterface $mock) use ($sourceVideos) {
$mock->shouldReceive('get')->once()->andReturn($sourceVideos);
});
$this->artisan(VideoReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Videos created, 0 Videos deleted, $updatedVideoCount Videos updated");
}
}
$this->artisan(VideoReconcileCommand::class)
->assertSuccessful()
->expectsOutput("0 Videos created, 0 Videos deleted, $updatedVideoCount Videos updated");
});
@@ -2,48 +2,33 @@
declare(strict_types=1);
namespace Tests\Feature\Console\Commands\Storage\Admin;
use App\Console\Commands\Storage\Admin\DocumentDumpCommand;
use App\Constants\Config\DumpConstants;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class DocumentDumpTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Database Dump Command shall output "Database dump '{dumpFile}' has been created".
*/
public function testDataBaseDumpOutput(): void
{
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('database dump output', function () {
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Date::setTestNow($this->faker->iso8601());
Date::setTestNow(fake()->iso8601());
$this->artisan(DocumentDumpCommand::class)
->assertSuccessful()
->expectsOutputToContain('has been created');
}
$this->artisan(DocumentDumpCommand::class)
->assertSuccessful()
->expectsOutputToContain('has been created');
});
/**
* The Database Dump Command shall produce a file in the /path/to/project/storage/db-dumps directory.
*/
public function testDataBaseDumpFile(): void
{
$local = Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('database dump file', function () {
$local = Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Date::setTestNow($this->faker->iso8601());
Date::setTestNow(fake()->iso8601());
$this->artisan(DocumentDumpCommand::class)->run();
$this->artisan(DocumentDumpCommand::class)->run();
static::assertEmpty($local->allFiles());
static::assertCount(1, $fs->allFiles());
}
}
$this->assertEmpty($local->allFiles());
$this->assertCount(1, $fs->allFiles());
});
@@ -2,55 +2,40 @@
declare(strict_types=1);
namespace Tests\Feature\Console\Commands\Storage\Admin;
use App\Actions\Storage\Admin\Dump\DumpWikiAction;
use App\Console\Commands\Storage\Admin\DumpPruneCommand;
use App\Constants\Config\DumpConstants;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class DumpPruneTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* If no changes are needed, the Prune Database Dumps Command shall output 'No database dumps deleted'.
*/
public function testNoResults(): void
{
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('no results', function () {
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$this->artisan(DumpPruneCommand::class, ['--hours' => 0])
->assertFailed()
->expectsOutput('No prunings were attempted.');
}
$this->artisan(DumpPruneCommand::class, ['--hours' => 0])
->assertFailed()
->expectsOutput('No prunings were attempted.');
});
/**
* If dumps are deleted, the Prune Database Dumps Command shall output '{Deleted Count} database dumps deleted'.
*/
public function testDeleted(): void
{
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('deleted', function () {
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$prunedCount = $this->faker->randomDigitNotNull();
$prunedCount = fake()->randomDigitNotNull();
Collection::times($prunedCount, function () {
Date::setTestNow($this->faker->iso8601());
Collection::times($prunedCount, function () {
Date::setTestNow(fake()->iso8601());
$action = new DumpWikiAction();
$action = new DumpWikiAction();
$action->handle();
});
$action->handle();
});
Date::setTestNow();
Date::setTestNow();
$this->artisan(DumpPruneCommand::class, ['--hours' => -1])
->assertSuccessful()
->expectsOutputToContain('Pruned');
}
}
$this->artisan(DumpPruneCommand::class, ['--hours' => -1])
->assertSuccessful()
->expectsOutputToContain('Pruned');
});
@@ -2,47 +2,32 @@
declare(strict_types=1);
namespace Tests\Feature\Console\Commands\Storage\Admin;
use App\Console\Commands\Storage\Admin\WikiDumpCommand;
use App\Constants\Config\DumpConstants;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class WikiDumpTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The Database Dump Command shall output "Database dump '{dumpFile}' has been created".
*/
public function testDataBaseDumpOutput(): void
{
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('database dump output', function () {
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Date::setTestNow($this->faker->iso8601());
Date::setTestNow(fake()->iso8601());
$this->artisan(WikiDumpCommand::class)
->assertSuccessful()
->expectsOutputToContain('has been created');
}
$this->artisan(WikiDumpCommand::class)
->assertSuccessful()
->expectsOutputToContain('has been created');
});
/**
* The Database Dump Command shall produce a file in the /path/to/project/storage/db-dumps directory.
*/
public function testDataBaseDumpFile(): void
{
$local = Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('database dump file', function () {
$local = Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Date::setTestNow($this->faker->iso8601());
Date::setTestNow(fake()->iso8601());
$this->artisan(WikiDumpCommand::class)->run();
$this->artisan(WikiDumpCommand::class)->run();
static::assertEmpty($local->allFiles());
static::assertCount(1, $fs->allFiles());
}
}
$this->assertEmpty($local->allFiles());
$this->assertCount(1, $fs->allFiles());
});
+26 -48
View File
@@ -2,69 +2,47 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Admin;
use App\Events\Admin\Announcement\AnnouncementCreated;
use App\Events\Admin\Announcement\AnnouncementDeleted;
use App\Events\Admin\Announcement\AnnouncementUpdated;
use App\Models\Admin\Announcement;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class AnnouncementTest extends TestCase
{
/**
* When an Announcement is created, an AnnouncementCreated event shall be dispatched.
*/
public function testAnnouncementCreatedEventDispatched(): void
{
Announcement::factory()->create();
test('announcement created event dispatched', function () {
Announcement::factory()->create();
Event::assertDispatched(AnnouncementCreated::class);
}
Event::assertDispatched(AnnouncementCreated::class);
});
/**
* When an Announcement is deleted, an AnnouncementDeleted event shall be dispatched.
*/
public function testAnnouncementDeletedEventDispatched(): void
{
$announcement = Announcement::factory()->create();
test('announcement deleted event dispatched', function () {
$announcement = Announcement::factory()->create();
$announcement->delete();
$announcement->delete();
Event::assertDispatched(AnnouncementDeleted::class);
}
Event::assertDispatched(AnnouncementDeleted::class);
});
/**
* When an Announcement is updated, an AnnouncementUpdated event shall be dispatched.
*/
public function testAnnouncementUpdatedEventDispatched(): void
{
$announcement = Announcement::factory()->createOne();
$changes = Announcement::factory()->makeOne();
test('announcement updated event dispatched', function () {
$announcement = Announcement::factory()->createOne();
$changes = Announcement::factory()->makeOne();
$announcement->fill($changes->getAttributes());
$announcement->save();
$announcement->fill($changes->getAttributes());
$announcement->save();
Event::assertDispatched(AnnouncementUpdated::class);
}
Event::assertDispatched(AnnouncementUpdated::class);
});
/**
* The AnnouncementUpdated event shall contain embed fields.
*/
public function testAnnouncementUpdatedEventEmbedFields(): void
{
$announcement = Announcement::factory()->createOne();
$changes = Announcement::factory()->makeOne();
test('announcement updated event embed fields', function () {
$announcement = Announcement::factory()->createOne();
$changes = Announcement::factory()->makeOne();
$announcement->fill($changes->getAttributes());
$announcement->save();
$announcement->fill($changes->getAttributes());
$announcement->save();
Event::assertDispatched(AnnouncementUpdated::class, function (AnnouncementUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(AnnouncementUpdated::class, function (AnnouncementUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+26 -48
View File
@@ -2,69 +2,47 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Admin;
use App\Events\Admin\Dump\DumpCreated;
use App\Events\Admin\Dump\DumpDeleted;
use App\Events\Admin\Dump\DumpUpdated;
use App\Models\Admin\Dump;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class DumpTest extends TestCase
{
/**
* When a Dump is created, a DumpCreated event shall be dispatched.
*/
public function testDumpCreatedEventDispatched(): void
{
Dump::factory()->create();
test('dump created event dispatched', function () {
Dump::factory()->create();
Event::assertDispatched(DumpCreated::class);
}
Event::assertDispatched(DumpCreated::class);
});
/**
* When a Dump is deleted, a DumpDeleted event shall be dispatched.
*/
public function testDumpDeletedEventDispatched(): void
{
$dump = Dump::factory()->create();
test('dump deleted event dispatched', function () {
$dump = Dump::factory()->create();
$dump->delete();
$dump->delete();
Event::assertDispatched(DumpDeleted::class);
}
Event::assertDispatched(DumpDeleted::class);
});
/**
* When a Dump is updated, a DumpUpdated event shall be dispatched.
*/
public function testDumpUpdatedEventDispatched(): void
{
$dump = Dump::factory()->createOne();
$changes = Dump::factory()->makeOne();
test('dump updated event dispatched', function () {
$dump = Dump::factory()->createOne();
$changes = Dump::factory()->makeOne();
$dump->fill($changes->getAttributes());
$dump->save();
$dump->fill($changes->getAttributes());
$dump->save();
Event::assertDispatched(DumpUpdated::class);
}
Event::assertDispatched(DumpUpdated::class);
});
/**
* The DumpUpdated event shall contain embed fields.
*/
public function testDumpUpdatedEventEmbedFields(): void
{
$dump = Dump::factory()->createOne();
$changes = Dump::factory()->makeOne();
test('dump updated event embed fields', function () {
$dump = Dump::factory()->createOne();
$changes = Dump::factory()->makeOne();
$dump->fill($changes->getAttributes());
$dump->save();
$dump->fill($changes->getAttributes());
$dump->save();
Event::assertDispatched(DumpUpdated::class, function (DumpUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(DumpUpdated::class, function (DumpUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+26 -48
View File
@@ -2,69 +2,47 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Admin;
use App\Events\Admin\Feature\FeatureCreated;
use App\Events\Admin\Feature\FeatureDeleted;
use App\Events\Admin\Feature\FeatureUpdated;
use App\Models\Admin\Feature;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class FeatureTest extends TestCase
{
/**
* When a Feature is created, a FeatureCreated event shall be dispatched.
*/
public function testFeatureCreatedEventDispatched(): void
{
Feature::factory()->create();
test('feature created event dispatched', function () {
Feature::factory()->create();
Event::assertDispatched(FeatureCreated::class);
}
Event::assertDispatched(FeatureCreated::class);
});
/**
* When a Feature is deleted, a FeatureDeleted event shall be dispatched.
*/
public function testFeatureDeletedEventDispatched(): void
{
$feature = Feature::factory()->create();
test('feature deleted event dispatched', function () {
$feature = Feature::factory()->create();
$feature->delete();
$feature->delete();
Event::assertDispatched(FeatureDeleted::class);
}
Event::assertDispatched(FeatureDeleted::class);
});
/**
* When a Feature is updated, a FeatureUpdated event shall be dispatched.
*/
public function testFeatureUpdatedEventDispatched(): void
{
$feature = Feature::factory()->createOne();
test('feature updated event dispatched', function () {
$feature = Feature::factory()->createOne();
$feature->update([
Feature::ATTRIBUTE_VALUE => ! $feature->value,
]);
$feature->update([
Feature::ATTRIBUTE_VALUE => ! $feature->value,
]);
Event::assertDispatched(FeatureUpdated::class);
}
Event::assertDispatched(FeatureUpdated::class);
});
/**
* The FeatureUpdated event shall contain embed fields.
*/
public function testFeatureUpdatedEventEmbedFields(): void
{
$feature = Feature::factory()->createOne();
test('feature updated event embed fields', function () {
$feature = Feature::factory()->createOne();
$feature->update([
Feature::ATTRIBUTE_VALUE => ! $feature->value,
]);
$feature->update([
Feature::ATTRIBUTE_VALUE => ! $feature->value,
]);
Event::assertDispatched(FeatureUpdated::class, function (FeatureUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(FeatureUpdated::class, function (FeatureUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,69 +2,47 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Admin;
use App\Events\Admin\FeaturedTheme\FeaturedThemeCreated;
use App\Events\Admin\FeaturedTheme\FeaturedThemeDeleted;
use App\Events\Admin\FeaturedTheme\FeaturedThemeUpdated;
use App\Models\Admin\FeaturedTheme;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class FeaturedThemeTest extends TestCase
{
/**
* When a Featured Theme is created, a FeaturedThemeCreated event shall be dispatched.
*/
public function testFeaturedThemeCreatedEventDispatched(): void
{
FeaturedTheme::factory()->create();
test('featured theme created event dispatched', function () {
FeaturedTheme::factory()->create();
Event::assertDispatched(FeaturedThemeCreated::class);
}
Event::assertDispatched(FeaturedThemeCreated::class);
});
/**
* When a Featured Theme is deleted, a FeaturedThemeDeleted event shall be dispatched.
*/
public function testFeaturedThemeDeletedEventDispatched(): void
{
$featuredTheme = FeaturedTheme::factory()->create();
test('featured theme deleted event dispatched', function () {
$featuredTheme = FeaturedTheme::factory()->create();
$featuredTheme->delete();
$featuredTheme->delete();
Event::assertDispatched(FeaturedThemeDeleted::class);
}
Event::assertDispatched(FeaturedThemeDeleted::class);
});
/**
* When a Featured Theme is updated, a FeaturedThemeUpdated event shall be dispatched.
*/
public function testFeaturedThemeUpdatedEventDispatched(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
$changes = FeaturedTheme::factory()->makeOne();
test('featured theme updated event dispatched', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
$changes = FeaturedTheme::factory()->makeOne();
$featuredTheme->fill($changes->getAttributes());
$featuredTheme->save();
$featuredTheme->fill($changes->getAttributes());
$featuredTheme->save();
Event::assertDispatched(FeaturedThemeUpdated::class);
}
Event::assertDispatched(FeaturedThemeUpdated::class);
});
/**
* The FeaturedThemeUpdated event shall contain embed fields.
*/
public function testFeaturedThemeUpdatedEventEmbedFields(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
$changes = FeaturedTheme::factory()->makeOne();
test('featured theme updated event embed fields', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
$changes = FeaturedTheme::factory()->makeOne();
$featuredTheme->fill($changes->getAttributes());
$featuredTheme->save();
$featuredTheme->fill($changes->getAttributes());
$featuredTheme->save();
Event::assertDispatched(FeaturedThemeUpdated::class, function (FeaturedThemeUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(FeaturedThemeUpdated::class, function (FeaturedThemeUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Auth;
use App\Events\Auth\User\UserCreated;
use App\Events\Auth\User\UserDeleted;
use App\Events\Auth\User\UserRestored;
@@ -11,87 +9,57 @@ use App\Events\Auth\User\UserUpdated;
use App\Models\Auth\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class UserTest extends TestCase
{
/**
* When a User is created, a UserCreated event shall be dispatched.
*/
public function testUserCreatedEventDispatched(): void
{
User::factory()->createOne();
test('user created event dispatched', function () {
User::factory()->createOne();
Event::assertDispatched(UserCreated::class);
}
Event::assertDispatched(UserCreated::class);
});
/**
* When a User is deleted, a UserDeleted event shall be dispatched.
*/
public function testUserDeletedEventDispatched(): void
{
$user = User::factory()->createOne();
test('user deleted event dispatched', function () {
$user = User::factory()->createOne();
$user->delete();
$user->delete();
Event::assertDispatched(UserDeleted::class);
}
Event::assertDispatched(UserDeleted::class);
});
/**
* When a User is restored, a UserRestored event shall be dispatched.
*/
public function testUserRestoredEventDispatched(): void
{
$user = User::factory()->createOne();
test('user restored event dispatched', function () {
$user = User::factory()->createOne();
$user->restore();
$user->restore();
Event::assertDispatched(UserRestored::class);
}
Event::assertDispatched(UserRestored::class);
});
/**
* When a User is restored, a UserUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testUserRestoresQuietly(): void
{
$user = User::factory()->createOne();
test('user restores quietly', function () {
$user = User::factory()->createOne();
$user->restore();
$user->restore();
Event::assertNotDispatched(UserUpdated::class);
}
Event::assertNotDispatched(UserUpdated::class);
});
/**
* When a User is updated, a UserUpdated event shall be dispatched.
*/
public function testUserUpdatedEventDispatched(): void
{
$user = User::factory()->createOne();
$changes = User::factory()->makeOne();
test('user updated event dispatched', function () {
$user = User::factory()->createOne();
$changes = User::factory()->makeOne();
$user->fill($changes->getAttributes());
$user->save();
$user->fill($changes->getAttributes());
$user->save();
Event::assertDispatched(UserUpdated::class);
}
Event::assertDispatched(UserUpdated::class);
});
/**
* The UserUpdated event shall contain embed fields.
*/
public function testUserUpdatedEventEmbedFields(): void
{
$user = User::factory()->createOne();
$changes = User::factory()->makeOne();
test('user updated event embed fields', function () {
$user = User::factory()->createOne();
$changes = User::factory()->makeOne();
$user->fill($changes->getAttributes());
$user->save();
$user->fill($changes->getAttributes());
$user->save();
Event::assertDispatched(UserUpdated::class, function (UserUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(UserUpdated::class, function (UserUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Document;
use App\Events\Document\Page\PageCreated;
use App\Events\Document\Page\PageDeleted;
use App\Events\Document\Page\PageRestored;
@@ -11,87 +9,57 @@ use App\Events\Document\Page\PageUpdated;
use App\Models\Document\Page;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class PageTest extends TestCase
{
/**
* When a Page is created, an PageCreated event shall be dispatched.
*/
public function testPageCreatedEventDispatched(): void
{
Page::factory()->createOne();
test('page created event dispatched', function () {
Page::factory()->createOne();
Event::assertDispatched(PageCreated::class);
}
Event::assertDispatched(PageCreated::class);
});
/**
* When a Page is deleted, an PageDeleted event shall be dispatched.
*/
public function testPageDeletedEventDispatched(): void
{
$page = Page::factory()->createOne();
test('page deleted event dispatched', function () {
$page = Page::factory()->createOne();
$page->delete();
$page->delete();
Event::assertDispatched(PageDeleted::class);
}
Event::assertDispatched(PageDeleted::class);
});
/**
* When a Page is restored, an PageRestored event shall be dispatched.
*/
public function testPageRestoredEventDispatched(): void
{
$page = Page::factory()->createOne();
test('page restored event dispatched', function () {
$page = Page::factory()->createOne();
$page->restore();
$page->restore();
Event::assertDispatched(PageRestored::class);
}
Event::assertDispatched(PageRestored::class);
});
/**
* When a Page is restored, a PageUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testPageRestoresQuietly(): void
{
$page = Page::factory()->createOne();
test('page restores quietly', function () {
$page = Page::factory()->createOne();
$page->restore();
$page->restore();
Event::assertNotDispatched(PageUpdated::class);
}
Event::assertNotDispatched(PageUpdated::class);
});
/**
* When a Page is updated, an PageUpdated event shall be dispatched.
*/
public function testPageUpdatedEventDispatched(): void
{
$page = Page::factory()->createOne();
$changes = Page::factory()->makeOne();
test('page updated event dispatched', function () {
$page = Page::factory()->createOne();
$changes = Page::factory()->makeOne();
$page->fill($changes->getAttributes());
$page->save();
$page->fill($changes->getAttributes());
$page->save();
Event::assertDispatched(PageUpdated::class);
}
Event::assertDispatched(PageUpdated::class);
});
/**
* The PageUpdated event shall contain embed fields.
*/
public function testPageUpdatedEventEmbedFields(): void
{
$page = Page::factory()->createOne();
$changes = Page::factory()->makeOne();
test('page updated event embed fields', function () {
$page = Page::factory()->createOne();
$changes = Page::factory()->makeOne();
$page->fill($changes->getAttributes());
$page->save();
$page->fill($changes->getAttributes());
$page->save();
Event::assertDispatched(PageUpdated::class, function (PageUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(PageUpdated::class, function (PageUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,69 +2,47 @@
declare(strict_types=1);
namespace Tests\Feature\Events\List;
use App\Events\List\ExternalProfile\ExternalProfileCreated;
use App\Events\List\ExternalProfile\ExternalProfileDeleted;
use App\Events\List\ExternalProfile\ExternalProfileUpdated;
use App\Models\List\ExternalProfile;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ExternalProfileTest extends TestCase
{
/**
* When a profile is created, a ExternalProfileCreated event shall be dispatched.
*/
public function testExternalProfileCreatedEventDispatched(): void
{
ExternalProfile::factory()->createOne();
test('external profile created event dispatched', function () {
ExternalProfile::factory()->createOne();
Event::assertDispatched(ExternalProfileCreated::class);
}
Event::assertDispatched(ExternalProfileCreated::class);
});
/**
* When a profile is deleted, a ExternalProfileDeleted event shall be dispatched.
*/
public function testExternalProfileDeletedEventDispatched(): void
{
$profile = ExternalProfile::factory()->createOne();
test('external profile deleted event dispatched', function () {
$profile = ExternalProfile::factory()->createOne();
$profile->delete();
$profile->delete();
Event::assertDispatched(ExternalProfileDeleted::class);
}
Event::assertDispatched(ExternalProfileDeleted::class);
});
/**
* When a profile is updated, a ExternalProfileUpdated event shall be dispatched.
*/
public function testExternalProfileUpdatedEventDispatched(): void
{
$profile = ExternalProfile::factory()->createOne();
$changes = ExternalProfile::factory()->makeOne();
test('external profile updated event dispatched', function () {
$profile = ExternalProfile::factory()->createOne();
$changes = ExternalProfile::factory()->makeOne();
$profile->fill($changes->getAttributes());
$profile->save();
$profile->fill($changes->getAttributes());
$profile->save();
Event::assertDispatched(ExternalProfileUpdated::class);
}
Event::assertDispatched(ExternalProfileUpdated::class);
});
/**
* The ExternalProfileUpdated event shall contain embed fields.
*/
public function testExternalProfileUpdatedEventEmbedFields(): void
{
$profile = ExternalProfile::factory()->createOne();
$changes = ExternalProfile::factory()->makeOne();
test('external profile updated event embed fields', function () {
$profile = ExternalProfile::factory()->createOne();
$changes = ExternalProfile::factory()->makeOne();
$profile->fill($changes->getAttributes());
$profile->save();
$profile->fill($changes->getAttributes());
$profile->save();
Event::assertDispatched(ExternalProfileUpdated::class, function (ExternalProfileUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(ExternalProfileUpdated::class, function (ExternalProfileUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\List\Playlist;
use App\Contracts\Models\HasHashids;
use App\Events\List\Playlist\Track\TrackCreated;
use App\Events\List\Playlist\Track\TrackDeleted;
@@ -12,89 +10,65 @@ use App\Models\List\Playlist;
use App\Models\List\Playlist\PlaylistTrack;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class TrackTest extends TestCase
{
/**
* When a Playlist Track is created, a TrackCreated event shall be dispatched.
*/
public function testTrackCreatedEventDispatched(): void
{
PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
test('track created event dispatched', function () {
PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
Event::assertDispatched(TrackCreated::class);
}
Event::assertDispatched(TrackCreated::class);
});
/**
* When a Playlist Track is deleted, a TrackDeleted event shall be dispatched.
*/
public function testTrackDeletedEventDispatched(): void
{
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
test('track deleted event dispatched', function () {
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
$track->delete();
$track->delete();
Event::assertDispatched(TrackDeleted::class);
}
Event::assertDispatched(TrackDeleted::class);
});
/**
* When a Track is updated, a TrackUpdated event shall be dispatched.
*/
public function testTrackUpdatedEventDispatched(): void
{
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
test('track updated event dispatched', function () {
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
$changes = PlaylistTrack::factory()
->for(Playlist::factory())
->makeOne();
$changes = PlaylistTrack::factory()
->for(Playlist::factory())
->makeOne();
$track->fill($changes->getAttributes());
$track->save();
$track->fill($changes->getAttributes());
$track->save();
Event::assertDispatched(TrackUpdated::class);
}
Event::assertDispatched(TrackUpdated::class);
});
/**
* The TrackUpdated event shall contain embed fields.
*/
public function testPlaylistUpdatedEventEmbedFields(): void
{
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
test('playlist updated event embed fields', function () {
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
$changes = PlaylistTrack::factory()
->for(Playlist::factory())
->makeOne();
$changes = PlaylistTrack::factory()
->for(Playlist::factory())
->makeOne();
$track->fill($changes->getAttributes());
$track->save();
$track->fill($changes->getAttributes());
$track->save();
Event::assertDispatched(TrackUpdated::class, function (TrackUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(TrackUpdated::class, function (TrackUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
/**
* The Track Created event shall assign hashids to the track.
*/
public function testPlaylistCreatedAssignsHashids(): void
{
Event::fakeExcept(TrackCreated::class);
test('playlist created assigns hashids', function () {
Event::fakeExcept(TrackCreated::class);
PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
PlaylistTrack::factory()
->for(Playlist::factory())
->createOne();
static::assertDatabaseMissing(PlaylistTrack::class, [HasHashids::ATTRIBUTE_HASHID => null]);
}
}
$this->assertDatabaseMissing(PlaylistTrack::class, [HasHashids::ATTRIBUTE_HASHID => null]);
});
+38 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\List;
use App\Contracts\Models\HasHashids;
use App\Events\List\Playlist\PlaylistCreated;
use App\Events\List\Playlist\PlaylistDeleted;
@@ -12,87 +10,59 @@ use App\Models\Auth\User;
use App\Models\List\Playlist;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class PlaylistTest extends TestCase
{
/**
* When a Playlist is created, a PlaylistCreated event shall be dispatched.
*/
public function testPlaylistCreatedEventDispatched(): void
{
Playlist::factory()->createOne();
test('playlist created event dispatched', function () {
Playlist::factory()->createOne();
Event::assertDispatched(PlaylistCreated::class);
}
Event::assertDispatched(PlaylistCreated::class);
});
/**
* When a Playlist is deleted, a PlaylistDeleted event shall be dispatched.
*/
public function testPlaylistDeletedEventDispatched(): void
{
$playlist = Playlist::factory()->createOne();
test('playlist deleted event dispatched', function () {
$playlist = Playlist::factory()->createOne();
$playlist->delete();
$playlist->delete();
Event::assertDispatched(PlaylistDeleted::class);
}
Event::assertDispatched(PlaylistDeleted::class);
});
/**
* When a Playlist is updated, a PlaylistUpdated event shall be dispatched.
*/
public function testPlaylistUpdatedEventDispatched(): void
{
$playlist = Playlist::factory()->createOne();
$changes = Playlist::factory()->makeOne();
test('playlist updated event dispatched', function () {
$playlist = Playlist::factory()->createOne();
$changes = Playlist::factory()->makeOne();
$playlist->fill($changes->getAttributes());
$playlist->save();
$playlist->fill($changes->getAttributes());
$playlist->save();
Event::assertDispatched(PlaylistUpdated::class);
}
Event::assertDispatched(PlaylistUpdated::class);
});
/**
* The PlaylistUpdated event shall contain embed fields.
*/
public function testPlaylistUpdatedEventEmbedFields(): void
{
$playlist = Playlist::factory()->createOne();
$changes = Playlist::factory()->makeOne();
test('playlist updated event embed fields', function () {
$playlist = Playlist::factory()->createOne();
$changes = Playlist::factory()->makeOne();
$playlist->fill($changes->getAttributes());
$playlist->save();
$playlist->fill($changes->getAttributes());
$playlist->save();
Event::assertDispatched(PlaylistUpdated::class, function (PlaylistUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(PlaylistUpdated::class, function (PlaylistUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
/**
* The Playlist Created event shall assign hashids to the playlist without an owner.
*/
public function testPlaylistCreatedAssignsNullableUserHashids(): void
{
Event::fakeExcept(PlaylistCreated::class);
test('playlist created assigns nullable user hashids', function () {
Event::fakeExcept(PlaylistCreated::class);
Playlist::factory()->createOne();
Playlist::factory()->createOne();
static::assertDatabaseMissing(Playlist::class, [HasHashids::ATTRIBUTE_HASHID => null]);
}
$this->assertDatabaseMissing(Playlist::class, [HasHashids::ATTRIBUTE_HASHID => null]);
});
/**
* The Playlist Created event shall assign hashids to the playlist with an owner.
*/
public function testPlaylistCreatedAssignsNonNullUserHashids(): void
{
Event::fakeExcept(PlaylistCreated::class);
test('playlist created assigns non null user hashids', function () {
Event::fakeExcept(PlaylistCreated::class);
Playlist::factory()
->for(User::factory())
->createOne();
Playlist::factory()
->for(User::factory())
->createOne();
static::assertDatabaseMissing(Playlist::class, [HasHashids::ATTRIBUTE_HASHID => null]);
}
}
$this->assertDatabaseMissing(Playlist::class, [HasHashids::ATTRIBUTE_HASHID => null]);
});
@@ -2,41 +2,27 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\List;
use App\Events\Pivot\List\PlaylistImage\PlaylistImageCreated;
use App\Events\Pivot\List\PlaylistImage\PlaylistImageDeleted;
use App\Models\List\Playlist;
use App\Models\Wiki\Image;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class PlaylistImageTest extends TestCase
{
/**
* When a Playlist is attached to an Image or vice versa, a PlaylistImageCreated event shall be dispatched.
*/
public function testPlaylistImageCreatedEventDispatched(): void
{
$playlist = Playlist::factory()->createOne();
$image = Image::factory()->createOne();
test('playlist image created event dispatched', function () {
$playlist = Playlist::factory()->createOne();
$image = Image::factory()->createOne();
$playlist->images()->attach($image);
$playlist->images()->attach($image);
Event::assertDispatched(PlaylistImageCreated::class);
}
Event::assertDispatched(PlaylistImageCreated::class);
});
/**
* When a Playlist is detached from an Image or vice versa, a PlaylistImageDeleted event shall be dispatched.
*/
public function testPlaylistImageDeletedEventDispatched(): void
{
$playlist = Playlist::factory()->createOne();
$image = Image::factory()->createOne();
test('playlist image deleted event dispatched', function () {
$playlist = Playlist::factory()->createOne();
$image = Image::factory()->createOne();
$playlist->images()->attach($image);
$playlist->images()->detach($image);
$playlist->images()->attach($image);
$playlist->images()->detach($image);
Event::assertDispatched(PlaylistImageDeleted::class);
}
}
Event::assertDispatched(PlaylistImageDeleted::class);
});
@@ -2,41 +2,27 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\AnimeImage\AnimeImageCreated;
use App\Events\Pivot\Wiki\AnimeImage\AnimeImageDeleted;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Image;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class AnimeImageTest extends TestCase
{
/**
* When an Anime is attached to an Image or vice versa, an AnimeImageCreated event shall be dispatched.
*/
public function testAnimeImageCreatedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$image = Image::factory()->createOne();
test('anime image created event dispatched', function () {
$anime = Anime::factory()->createOne();
$image = Image::factory()->createOne();
$anime->images()->attach($image);
$anime->images()->attach($image);
Event::assertDispatched(AnimeImageCreated::class);
}
Event::assertDispatched(AnimeImageCreated::class);
});
/**
* When an Anime is detached from an Image or vice versa, an AnimeImageDeleted event shall be dispatched.
*/
public function testAnimeImageDeletedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$image = Image::factory()->createOne();
test('anime image deleted event dispatched', function () {
$anime = Anime::factory()->createOne();
$image = Image::factory()->createOne();
$anime->images()->attach($image);
$anime->images()->detach($image);
$anime->images()->attach($image);
$anime->images()->detach($image);
Event::assertDispatched(AnimeImageDeleted::class);
}
}
Event::assertDispatched(AnimeImageDeleted::class);
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\AnimeResource\AnimeResourceCreated;
use App\Events\Pivot\Wiki\AnimeResource\AnimeResourceDeleted;
use App\Events\Pivot\Wiki\AnimeResource\AnimeResourceUpdated;
@@ -12,86 +10,66 @@ use App\Models\Wiki\ExternalResource;
use App\Pivots\Wiki\AnimeResource;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class AnimeResourceTest extends TestCase
{
/**
* When an Anime is attached to a Resource or vice versa, an AnimeResourceCreated event shall be dispatched.
*/
public function testAnimeResourceCreatedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('anime resource created event dispatched', function () {
$anime = Anime::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$anime->resources()->attach($resource);
$anime->resources()->attach($resource);
Event::assertDispatched(AnimeResourceCreated::class);
}
Event::assertDispatched(AnimeResourceCreated::class);
});
/**
* When an Anime is detached from a Resource or vice versa, an AnimeResourceDeleted event shall be dispatched.
*/
public function testAnimeResourceDeletedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('anime resource deleted event dispatched', function () {
$anime = Anime::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$anime->resources()->attach($resource);
$anime->resources()->detach($resource);
$anime->resources()->attach($resource);
$anime->resources()->detach($resource);
Event::assertDispatched(AnimeResourceDeleted::class);
}
Event::assertDispatched(AnimeResourceDeleted::class);
});
/**
* When an Anime Resource pivot is updated, an AnimeResourceUpdated event shall be dispatched.
*/
public function testAnimeResourceUpdatedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('anime resource updated event dispatched', function () {
$anime = Anime::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$animeResource = AnimeResource::factory()
->for($anime, 'anime')
->for($resource, 'resource')
->createOne();
$animeResource = AnimeResource::factory()
->for($anime, 'anime')
->for($resource, 'resource')
->createOne();
$changes = AnimeResource::factory()
->for($anime, 'anime')
->for($resource, 'resource')
->makeOne();
$changes = AnimeResource::factory()
->for($anime, 'anime')
->for($resource, 'resource')
->makeOne();
$animeResource->fill($changes->getAttributes());
$animeResource->save();
$animeResource->fill($changes->getAttributes());
$animeResource->save();
Event::assertDispatched(AnimeResourceUpdated::class);
}
Event::assertDispatched(AnimeResourceUpdated::class);
});
/**
* The AnimeResourceUpdated event shall contain embed fields.
*/
public function testAnimeResourceUpdatedEventEmbedFields(): void
{
$anime = Anime::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('anime resource updated event embed fields', function () {
$anime = Anime::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$animeResource = AnimeResource::factory()
->for($anime, 'anime')
->for($resource, 'resource')
->createOne();
$animeResource = AnimeResource::factory()
->for($anime, 'anime')
->for($resource, 'resource')
->createOne();
$changes = AnimeResource::factory()
->for($anime, 'anime')
->for($resource, 'resource')
->makeOne();
$changes = AnimeResource::factory()
->for($anime, 'anime')
->for($resource, 'resource')
->makeOne();
$animeResource->fill($changes->getAttributes());
$animeResource->save();
$animeResource->fill($changes->getAttributes());
$animeResource->save();
Event::assertDispatched(AnimeResourceUpdated::class, function (AnimeResourceUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(AnimeResourceUpdated::class, function (AnimeResourceUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,41 +2,27 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\AnimeSeries\AnimeSeriesCreated;
use App\Events\Pivot\Wiki\AnimeSeries\AnimeSeriesDeleted;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Series;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class AnimeSeriesTest extends TestCase
{
/**
* When an Anime is attached to a Series or vice versa, an AnimeSeriesCreated event shall be dispatched.
*/
public function testAnimeSeriesCreatedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$series = Series::factory()->createOne();
test('anime series created event dispatched', function () {
$anime = Anime::factory()->createOne();
$series = Series::factory()->createOne();
$anime->series()->attach($series);
$anime->series()->attach($series);
Event::assertDispatched(AnimeSeriesCreated::class);
}
Event::assertDispatched(AnimeSeriesCreated::class);
});
/**
* When an Anime is detached from a Series or vice versa, an AnimeSeriesDeleted event shall be dispatched.
*/
public function testAnimeSeriesDeletedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$series = Series::factory()->createOne();
test('anime series deleted event dispatched', function () {
$anime = Anime::factory()->createOne();
$series = Series::factory()->createOne();
$anime->series()->attach($series);
$anime->series()->detach($series);
$anime->series()->attach($series);
$anime->series()->detach($series);
Event::assertDispatched(AnimeSeriesDeleted::class);
}
}
Event::assertDispatched(AnimeSeriesDeleted::class);
});
@@ -2,41 +2,27 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\AnimeStudio\AnimeStudioCreated;
use App\Events\Pivot\Wiki\AnimeStudio\AnimeStudioDeleted;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Studio;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class AnimeStudioTest extends TestCase
{
/**
* When an Anime is attached to a Studio or vice versa, an AnimeStudioCreated event shall be dispatched.
*/
public function testAnimeStudioCreatedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$studio = Studio::factory()->createOne();
test('anime studio created event dispatched', function () {
$anime = Anime::factory()->createOne();
$studio = Studio::factory()->createOne();
$anime->studios()->attach($studio);
$anime->studios()->attach($studio);
Event::assertDispatched(AnimeStudioCreated::class);
}
Event::assertDispatched(AnimeStudioCreated::class);
});
/**
* When an Anime is detached from a Studio or vice versa, an AnimeStudioDeleted event shall be dispatched.
*/
public function testAnimeStudioDeletedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$studio = Studio::factory()->createOne();
test('anime studio deleted event dispatched', function () {
$anime = Anime::factory()->createOne();
$studio = Studio::factory()->createOne();
$anime->studios()->attach($studio);
$anime->studios()->detach($studio);
$anime->studios()->attach($studio);
$anime->studios()->detach($studio);
Event::assertDispatched(AnimeStudioDeleted::class);
}
}
Event::assertDispatched(AnimeStudioDeleted::class);
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\AnimeThemeEntryVideo\AnimeThemeEntryVideoCreated;
use App\Events\Pivot\Wiki\AnimeThemeEntryVideo\AnimeThemeEntryVideoDeleted;
use App\Models\List\Playlist;
@@ -13,95 +11,75 @@ use App\Models\Wiki\Anime\AnimeTheme;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use App\Models\Wiki\Video;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class AnimeThemeEntryVideoTest extends TestCase
{
/**
* When a Video is attached to an AnimeThemeEntry or vice versa, an AnimeThemeEntryVideoTest event shall be dispatched.
*/
public function testAnimeThemeEntryVideoCreatedEventDispatched(): void
{
$video = Video::factory()->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('anime theme entry video created event dispatched', function () {
$video = Video::factory()->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$video->animethemeentries()->attach($entry);
$video->animethemeentries()->attach($entry);
Event::assertDispatched(AnimeThemeEntryVideoCreated::class);
}
Event::assertDispatched(AnimeThemeEntryVideoCreated::class);
});
/**
* When a Video is detached from an AnimeThemeEntry or vice versa, an AnimeThemeEntryVideoDeleted event shall be dispatched.
*/
public function testAnimeThemeEntryVideoDeletedEventDispatched(): void
{
$video = Video::factory()->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('anime theme entry video deleted event dispatched', function () {
$video = Video::factory()->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$video->animethemeentries()->attach($entry);
$video->animethemeentries()->detach($entry);
$video->animethemeentries()->attach($entry);
$video->animethemeentries()->detach($entry);
Event::assertDispatched(AnimeThemeEntryVideoDeleted::class);
}
Event::assertDispatched(AnimeThemeEntryVideoDeleted::class);
});
/**
* When a Video is attached to an AnimeThemeEntry, the playlist tracks should be updated.
*/
public function testAnimeThemeEntryVideoCreatedEventUpdatePlaylistTracks(): void
{
$video = Video::factory()->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('anime theme entry video created event update playlist tracks', function () {
$video = Video::factory()->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$video->animethemeentries()->attach($entry);
$video->animethemeentries()->attach($entry);
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->for($video)
->createOne();
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->for($video)
->createOne();
Event::assertDispatched(AnimeThemeEntryVideoCreated::class, function (AnimeThemeEntryVideoCreated $event) use ($entry, $track) {
$event->updatePlaylistTracks();
Event::assertDispatched(AnimeThemeEntryVideoCreated::class, function (AnimeThemeEntryVideoCreated $event) use ($entry, $track) {
$event->updatePlaylistTracks();
return $track->refresh()->animethemeentry()->is($entry);
});
}
return $track->refresh()->animethemeentry()->is($entry);
});
});
/**
* When a Video is detached from an AnimeThemeEntry, the playlist tracks should be updated.
*/
public function testAnimeThemeEntryVideoDeletedEventUpdatePlaylistTracks(): void
{
$video = Video::factory()->createOne();
test('anime theme entry video deleted event update playlist tracks', function () {
$video = Video::factory()->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$secondEntry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$secondEntry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$video->animethemeentries()->attach($entry);
$video->animethemeentries()->attach($entry);
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->for($video)
->for($entry)
->createOne();
$track = PlaylistTrack::factory()
->for(Playlist::factory())
->for($video)
->for($entry)
->createOne();
$video->animethemeentries()->attach($secondEntry);
$video->animethemeentries()->detach($entry);
$video->animethemeentries()->attach($secondEntry);
$video->animethemeentries()->detach($entry);
Event::assertDispatched(AnimeThemeEntryVideoDeleted::class, function (AnimeThemeEntryVideoDeleted $event) use ($secondEntry, $track) {
$event->updatePlaylistTracks();
Event::assertDispatched(AnimeThemeEntryVideoDeleted::class, function (AnimeThemeEntryVideoDeleted $event) use ($secondEntry, $track) {
$event->updatePlaylistTracks();
return $track->refresh()->animethemeentry()->is($secondEntry);
});
}
}
return $track->refresh()->animethemeentry()->is($secondEntry);
});
});
@@ -2,41 +2,27 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\ArtistImage\ArtistImageCreated;
use App\Events\Pivot\Wiki\ArtistImage\ArtistImageDeleted;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Image;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ArtistImageTest extends TestCase
{
/**
* When an Artist is attached to an Image or vice versa, an ArtistImageCreated event shall be dispatched.
*/
public function testArtistImageCreatedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$image = Image::factory()->createOne();
test('artist image created event dispatched', function () {
$artist = Artist::factory()->createOne();
$image = Image::factory()->createOne();
$artist->images()->attach($image);
$artist->images()->attach($image);
Event::assertDispatched(ArtistImageCreated::class);
}
Event::assertDispatched(ArtistImageCreated::class);
});
/**
* When an Artist is detached from an Image or vice versa, an ArtistImageDeleted event shall be dispatched.
*/
public function testArtistImageDeletedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$image = Image::factory()->createOne();
test('artist image deleted event dispatched', function () {
$artist = Artist::factory()->createOne();
$image = Image::factory()->createOne();
$artist->images()->attach($image);
$artist->images()->detach($image);
$artist->images()->attach($image);
$artist->images()->detach($image);
Event::assertDispatched(ArtistImageDeleted::class);
}
}
Event::assertDispatched(ArtistImageDeleted::class);
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\ArtistMember\ArtistMemberCreated;
use App\Events\Pivot\Wiki\ArtistMember\ArtistMemberDeleted;
use App\Events\Pivot\Wiki\ArtistMember\ArtistMemberUpdated;
@@ -11,86 +9,66 @@ use App\Models\Wiki\Artist;
use App\Pivots\Wiki\ArtistMember;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ArtistMemberTest extends TestCase
{
/**
* When an Artist is attached to a Member or vice versa, an ArtistMemberCreated event shall be dispatched.
*/
public function testArtistMemberCreatedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$member = Artist::factory()->createOne();
test('artist member created event dispatched', function () {
$artist = Artist::factory()->createOne();
$member = Artist::factory()->createOne();
$artist->members()->attach($member);
$artist->members()->attach($member);
Event::assertDispatched(ArtistMemberCreated::class);
}
Event::assertDispatched(ArtistMemberCreated::class);
});
/**
* When an Artist is detached from a Member or vice versa, an ArtistMemberDeleted event shall be dispatched.
*/
public function testArtistMemberDeletedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$member = Artist::factory()->createOne();
test('artist member deleted event dispatched', function () {
$artist = Artist::factory()->createOne();
$member = Artist::factory()->createOne();
$artist->members()->attach($member);
$artist->members()->detach($member);
$artist->members()->attach($member);
$artist->members()->detach($member);
Event::assertDispatched(ArtistMemberDeleted::class);
}
Event::assertDispatched(ArtistMemberDeleted::class);
});
/**
* When an Artist Member pivot is updated, an ArtistMemberUpdated event shall be dispatched.
*/
public function testArtistMemberUpdatedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$member = Artist::factory()->createOne();
test('artist member updated event dispatched', function () {
$artist = Artist::factory()->createOne();
$member = Artist::factory()->createOne();
$artistMember = ArtistMember::factory()
->for($artist, 'artist')
->for($member, 'member')
->createOne();
$artistMember = ArtistMember::factory()
->for($artist, 'artist')
->for($member, 'member')
->createOne();
$changes = ArtistMember::factory()
->for($artist, 'artist')
->for($member, 'member')
->makeOne();
$changes = ArtistMember::factory()
->for($artist, 'artist')
->for($member, 'member')
->makeOne();
$artistMember->fill($changes->getAttributes());
$artistMember->save();
$artistMember->fill($changes->getAttributes());
$artistMember->save();
Event::assertDispatched(ArtistMemberUpdated::class);
}
Event::assertDispatched(ArtistMemberUpdated::class);
});
/**
* The ArtistMemberUpdated event shall contain embed fields.
*/
public function testArtistMemberUpdatedEventEmbedFields(): void
{
$artist = Artist::factory()->createOne();
$member = Artist::factory()->createOne();
test('artist member updated event embed fields', function () {
$artist = Artist::factory()->createOne();
$member = Artist::factory()->createOne();
$artistMember = ArtistMember::factory()
->for($artist, 'artist')
->for($member, 'member')
->createOne();
$artistMember = ArtistMember::factory()
->for($artist, 'artist')
->for($member, 'member')
->createOne();
$changes = ArtistMember::factory()
->for($artist, 'artist')
->for($member, 'member')
->makeOne();
$changes = ArtistMember::factory()
->for($artist, 'artist')
->for($member, 'member')
->makeOne();
$artistMember->fill($changes->getAttributes());
$artistMember->save();
$artistMember->fill($changes->getAttributes());
$artistMember->save();
Event::assertDispatched(ArtistMemberUpdated::class, function (ArtistMemberUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(ArtistMemberUpdated::class, function (ArtistMemberUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\ArtistResource\ArtistResourceCreated;
use App\Events\Pivot\Wiki\ArtistResource\ArtistResourceDeleted;
use App\Events\Pivot\Wiki\ArtistResource\ArtistResourceUpdated;
@@ -12,86 +10,66 @@ use App\Models\Wiki\ExternalResource;
use App\Pivots\Wiki\ArtistResource;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ArtistResourceTest extends TestCase
{
/**
* When an Artist is attached to a Resource or vice versa, an ArtistResourceCreated event shall be dispatched.
*/
public function testArtistResourceCreatedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('artist resource created event dispatched', function () {
$artist = Artist::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$artist->resources()->attach($resource);
$artist->resources()->attach($resource);
Event::assertDispatched(ArtistResourceCreated::class);
}
Event::assertDispatched(ArtistResourceCreated::class);
});
/**
* When an Artist is detached from a Resource or vice versa, an ArtistResourceDeleted event shall be dispatched.
*/
public function testArtistResourceDeletedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('artist resource deleted event dispatched', function () {
$artist = Artist::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$artist->resources()->attach($resource);
$artist->resources()->detach($resource);
$artist->resources()->attach($resource);
$artist->resources()->detach($resource);
Event::assertDispatched(ArtistResourceDeleted::class);
}
Event::assertDispatched(ArtistResourceDeleted::class);
});
/**
* When an Artist Resource pivot is updated, an ArtistResourceUpdated event shall be dispatched.
*/
public function testArtistResourceUpdatedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('artist resource updated event dispatched', function () {
$artist = Artist::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$artistResource = ArtistResource::factory()
->for($artist, 'artist')
->for($resource, 'resource')
->createOne();
$artistResource = ArtistResource::factory()
->for($artist, 'artist')
->for($resource, 'resource')
->createOne();
$changes = ArtistResource::factory()
->for($artist, 'artist')
->for($resource, 'resource')
->makeOne();
$changes = ArtistResource::factory()
->for($artist, 'artist')
->for($resource, 'resource')
->makeOne();
$artistResource->fill($changes->getAttributes());
$artistResource->save();
$artistResource->fill($changes->getAttributes());
$artistResource->save();
Event::assertDispatched(ArtistResourceUpdated::class);
}
Event::assertDispatched(ArtistResourceUpdated::class);
});
/**
* The ArtistResourceUpdated event shall contain embed fields.
*/
public function testArtistResourceUpdatedEventEmbedFields(): void
{
$artist = Artist::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('artist resource updated event embed fields', function () {
$artist = Artist::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$artistResource = ArtistResource::factory()
->for($artist, 'artist')
->for($resource, 'resource')
->createOne();
$artistResource = ArtistResource::factory()
->for($artist, 'artist')
->for($resource, 'resource')
->createOne();
$changes = ArtistResource::factory()
->for($artist, 'artist')
->for($resource, 'resource')
->makeOne();
$changes = ArtistResource::factory()
->for($artist, 'artist')
->for($resource, 'resource')
->makeOne();
$artistResource->fill($changes->getAttributes());
$artistResource->save();
$artistResource->fill($changes->getAttributes());
$artistResource->save();
Event::assertDispatched(ArtistResourceUpdated::class, function (ArtistResourceUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(ArtistResourceUpdated::class, function (ArtistResourceUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\ArtistSong\ArtistSongCreated;
use App\Events\Pivot\Wiki\ArtistSong\ArtistSongDeleted;
use App\Events\Pivot\Wiki\ArtistSong\ArtistSongUpdated;
@@ -12,86 +10,66 @@ use App\Models\Wiki\Song;
use App\Pivots\Wiki\ArtistSong;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ArtistSongTest extends TestCase
{
/**
* When an Artist is attached to a Song or vice versa, an ArtistSongCreated event shall be dispatched.
*/
public function testArtistSongCreatedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$song = Song::factory()->createOne();
test('artist song created event dispatched', function () {
$artist = Artist::factory()->createOne();
$song = Song::factory()->createOne();
$artist->songs()->attach($song);
$artist->songs()->attach($song);
Event::assertDispatched(ArtistSongCreated::class);
}
Event::assertDispatched(ArtistSongCreated::class);
});
/**
* When an Artist is detached from a Song or vice versa, an ArtistSongDeleted event shall be dispatched.
*/
public function testArtistSongDeletedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$song = Song::factory()->createOne();
test('artist song deleted event dispatched', function () {
$artist = Artist::factory()->createOne();
$song = Song::factory()->createOne();
$artist->songs()->attach($song);
$artist->songs()->detach($song);
$artist->songs()->attach($song);
$artist->songs()->detach($song);
Event::assertDispatched(ArtistSongDeleted::class);
}
Event::assertDispatched(ArtistSongDeleted::class);
});
/**
* When an Artist Song pivot is updated, an ArtistSongUpdated event shall be dispatched.
*/
public function testArtistSongUpdatedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$song = Song::factory()->createOne();
test('artist song updated event dispatched', function () {
$artist = Artist::factory()->createOne();
$song = Song::factory()->createOne();
$artistSong = ArtistSong::factory()
->for($artist, 'artist')
->for($song, 'song')
->createOne();
$artistSong = ArtistSong::factory()
->for($artist, 'artist')
->for($song, 'song')
->createOne();
$changes = ArtistSong::factory()
->for($artist, 'artist')
->for($song, 'song')
->makeOne();
$changes = ArtistSong::factory()
->for($artist, 'artist')
->for($song, 'song')
->makeOne();
$artistSong->fill($changes->getAttributes());
$artistSong->save();
$artistSong->fill($changes->getAttributes());
$artistSong->save();
Event::assertDispatched(ArtistSongUpdated::class);
}
Event::assertDispatched(ArtistSongUpdated::class);
});
/**
* The ArtistSongUpdated event shall contain embed fields.
*/
public function testArtistSongUpdatedEventEmbedFields(): void
{
$artist = Artist::factory()->createOne();
$song = Song::factory()->createOne();
test('artist song updated event embed fields', function () {
$artist = Artist::factory()->createOne();
$song = Song::factory()->createOne();
$artistSong = ArtistSong::factory()
->for($artist, 'artist')
->for($song, 'song')
->createOne();
$artistSong = ArtistSong::factory()
->for($artist, 'artist')
->for($song, 'song')
->createOne();
$changes = ArtistSong::factory()
->for($artist, 'artist')
->for($song, 'song')
->makeOne();
$changes = ArtistSong::factory()
->for($artist, 'artist')
->for($song, 'song')
->makeOne();
$artistSong->fill($changes->getAttributes());
$artistSong->save();
$artistSong->fill($changes->getAttributes());
$artistSong->save();
Event::assertDispatched(ArtistSongUpdated::class, function (ArtistSongUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(ArtistSongUpdated::class, function (ArtistSongUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\SongResource\SongResourceCreated;
use App\Events\Pivot\Wiki\SongResource\SongResourceDeleted;
use App\Events\Pivot\Wiki\SongResource\SongResourceUpdated;
@@ -12,86 +10,66 @@ use App\Models\Wiki\Song;
use App\Pivots\Wiki\SongResource;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class SongResourceTest extends TestCase
{
/**
* When an Song is attached to a Resource or vice versa, an SongResourceCreated event shall be dispatched.
*/
public function testSongResourceCreatedEventDispatched(): void
{
$song = Song::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('song resource created event dispatched', function () {
$song = Song::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$song->resources()->attach($resource);
$song->resources()->attach($resource);
Event::assertDispatched(SongResourceCreated::class);
}
Event::assertDispatched(SongResourceCreated::class);
});
/**
* When an Song is detached from a Resource or vice versa, an SongResourceDeleted event shall be dispatched.
*/
public function testSongResourceDeletedEventDispatched(): void
{
$song = Song::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('song resource deleted event dispatched', function () {
$song = Song::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$song->resources()->attach($resource);
$song->resources()->detach($resource);
$song->resources()->attach($resource);
$song->resources()->detach($resource);
Event::assertDispatched(SongResourceDeleted::class);
}
Event::assertDispatched(SongResourceDeleted::class);
});
/**
* When an Song Resource pivot is updated, an SongResourceUpdated event shall be dispatched.
*/
public function testSongResourceUpdatedEventDispatched(): void
{
$song = Song::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('song resource updated event dispatched', function () {
$song = Song::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$songResource = SongResource::factory()
->for($song, 'song')
->for($resource, 'resource')
->createOne();
$songResource = SongResource::factory()
->for($song, 'song')
->for($resource, 'resource')
->createOne();
$changes = SongResource::factory()
->for($song, 'song')
->for($resource, 'resource')
->makeOne();
$changes = SongResource::factory()
->for($song, 'song')
->for($resource, 'resource')
->makeOne();
$songResource->fill($changes->getAttributes());
$songResource->save();
$songResource->fill($changes->getAttributes());
$songResource->save();
Event::assertDispatched(SongResourceUpdated::class);
}
Event::assertDispatched(SongResourceUpdated::class);
});
/**
* The SongResourceUpdated event shall contain embed fields.
*/
public function testSongResourceUpdatedEventEmbedFields(): void
{
$song = Song::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('song resource updated event embed fields', function () {
$song = Song::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$songResource = SongResource::factory()
->for($song, 'song')
->for($resource, 'resource')
->createOne();
$songResource = SongResource::factory()
->for($song, 'song')
->for($resource, 'resource')
->createOne();
$changes = SongResource::factory()
->for($song, 'song')
->for($resource, 'resource')
->makeOne();
$changes = SongResource::factory()
->for($song, 'song')
->for($resource, 'resource')
->makeOne();
$songResource->fill($changes->getAttributes());
$songResource->save();
$songResource->fill($changes->getAttributes());
$songResource->save();
Event::assertDispatched(SongResourceUpdated::class, function (SongResourceUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(SongResourceUpdated::class, function (SongResourceUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,41 +2,27 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\StudioImage\StudioImageCreated;
use App\Events\Pivot\Wiki\StudioImage\StudioImageDeleted;
use App\Models\Wiki\Image;
use App\Models\Wiki\Studio;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class StudioImageTest extends TestCase
{
/**
* When a Studio is attached to an Image or vice versa, a StudioImageCreated event shall be dispatched.
*/
public function testStudioImageCreatedEventDispatched(): void
{
$studio = Studio::factory()->createOne();
$image = Image::factory()->createOne();
test('studio image created event dispatched', function () {
$studio = Studio::factory()->createOne();
$image = Image::factory()->createOne();
$studio->images()->attach($image);
$studio->images()->attach($image);
Event::assertDispatched(StudioImageCreated::class);
}
Event::assertDispatched(StudioImageCreated::class);
});
/**
* When a Studio is detached from an Image or vice versa, a StudioImageDeleted event shall be dispatched.
*/
public function testStudioImageDeletedEventDispatched(): void
{
$studio = Studio::factory()->createOne();
$image = Image::factory()->createOne();
test('studio image deleted event dispatched', function () {
$studio = Studio::factory()->createOne();
$image = Image::factory()->createOne();
$studio->images()->attach($image);
$studio->images()->detach($image);
$studio->images()->attach($image);
$studio->images()->detach($image);
Event::assertDispatched(StudioImageDeleted::class);
}
}
Event::assertDispatched(StudioImageDeleted::class);
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Pivot\Wiki;
use App\Events\Pivot\Wiki\StudioResource\StudioResourceCreated;
use App\Events\Pivot\Wiki\StudioResource\StudioResourceDeleted;
use App\Events\Pivot\Wiki\StudioResource\StudioResourceUpdated;
@@ -12,86 +10,66 @@ use App\Models\Wiki\Studio;
use App\Pivots\Wiki\StudioResource;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class StudioResourceTest extends TestCase
{
/**
* When a Studio is attached to a Resource or vice versa, a StudioResourceCreated event shall be dispatched.
*/
public function testStudioResourceCreatedEventDispatched(): void
{
$studio = Studio::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('studio resource created event dispatched', function () {
$studio = Studio::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$studio->resources()->attach($resource);
$studio->resources()->attach($resource);
Event::assertDispatched(StudioResourceCreated::class);
}
Event::assertDispatched(StudioResourceCreated::class);
});
/**
* When a Studio is detached to a Resource or vice versa, a StudioResourceDeleted event shall be dispatched.
*/
public function testStudioResourceDeletedEventDispatched(): void
{
$studio = Studio::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('studio resource deleted event dispatched', function () {
$studio = Studio::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$studio->resources()->attach($resource);
$studio->resources()->detach($resource);
$studio->resources()->attach($resource);
$studio->resources()->detach($resource);
Event::assertDispatched(StudioResourceDeleted::class);
}
Event::assertDispatched(StudioResourceDeleted::class);
});
/**
* When a Studio Resource pivot is updated, a StudioResourceUpdated event shall be dispatched.
*/
public function testStudioResourceUpdatedEventDispatched(): void
{
$studio = Studio::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('studio resource updated event dispatched', function () {
$studio = Studio::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$studioResource = StudioResource::factory()
->for($studio, 'studio')
->for($resource, 'resource')
->createOne();
$studioResource = StudioResource::factory()
->for($studio, 'studio')
->for($resource, 'resource')
->createOne();
$changes = StudioResource::factory()
->for($studio, 'studio')
->for($resource, 'resource')
->makeOne();
$changes = StudioResource::factory()
->for($studio, 'studio')
->for($resource, 'resource')
->makeOne();
$studioResource->fill($changes->getAttributes());
$studioResource->save();
$studioResource->fill($changes->getAttributes());
$studioResource->save();
Event::assertDispatched(StudioResourceUpdated::class);
}
Event::assertDispatched(StudioResourceUpdated::class);
});
/**
* The StudioResourceUpdated event shall contain embed fields.
*/
public function testStudioResourceUpdatedEventEmbedFields(): void
{
$studio = Studio::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
test('studio resource updated event embed fields', function () {
$studio = Studio::factory()->createOne();
$resource = ExternalResource::factory()->createOne();
$studioResource = StudioResource::factory()
->for($studio, 'studio')
->for($resource, 'resource')
->createOne();
$studioResource = StudioResource::factory()
->for($studio, 'studio')
->for($resource, 'resource')
->createOne();
$changes = StudioResource::factory()
->for($studio, 'studio')
->for($resource, 'resource')
->makeOne();
$changes = StudioResource::factory()
->for($studio, 'studio')
->for($resource, 'resource')
->makeOne();
$studioResource->fill($changes->getAttributes());
$studioResource->save();
$studioResource->fill($changes->getAttributes());
$studioResource->save();
Event::assertDispatched(StudioResourceUpdated::class, function (StudioResourceUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(StudioResourceUpdated::class, function (StudioResourceUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+52 -84
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki\Anime;
use App\Events\Wiki\Anime\Synonym\SynonymCreated;
use App\Events\Wiki\Anime\Synonym\SynonymDeleted;
use App\Events\Wiki\Anime\Synonym\SynonymRestored;
@@ -12,105 +10,75 @@ use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeSynonym;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class SynonymTest extends TestCase
{
/**
* When a Synonym is created, a SynonymCreated event shall be dispatched.
*/
public function testSynonymCreatedEventDispatched(): void
{
AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
test('synonym created event dispatched', function () {
AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
Event::assertDispatched(SynonymCreated::class);
}
Event::assertDispatched(SynonymCreated::class);
});
/**
* When a Synonym is deleted, a SynonymDeleted event shall be dispatched.
*/
public function testSynonymDeletedEventDispatched(): void
{
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
test('synonym deleted event dispatched', function () {
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
$synonym->delete();
$synonym->delete();
Event::assertDispatched(SynonymDeleted::class);
}
Event::assertDispatched(SynonymDeleted::class);
});
/**
* When a Synonym is restored, a SynonymRestored event shall be dispatched.
*/
public function testSynonymRestoredEventDispatched(): void
{
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
test('synonym restored event dispatched', function () {
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
$synonym->restore();
$synonym->restore();
Event::assertDispatched(SynonymRestored::class);
}
Event::assertDispatched(SynonymRestored::class);
});
/**
* When a Synonym is restored, a SynonymUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testSynonymRestoresQuietly(): void
{
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
test('synonym restores quietly', function () {
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
$synonym->restore();
$synonym->restore();
Event::assertNotDispatched(SynonymUpdated::class);
}
Event::assertNotDispatched(SynonymUpdated::class);
});
/**
* When a Synonym is updated, a SynonymUpdated event shall be dispatched.
*/
public function testSynonymUpdatedEventDispatched(): void
{
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
test('synonym updated event dispatched', function () {
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
$changes = AnimeSynonym::factory()
->for(Anime::factory())
->makeOne();
$changes = AnimeSynonym::factory()
->for(Anime::factory())
->makeOne();
$synonym->fill($changes->getAttributes());
$synonym->save();
$synonym->fill($changes->getAttributes());
$synonym->save();
Event::assertDispatched(SynonymUpdated::class);
}
Event::assertDispatched(SynonymUpdated::class);
});
/**
* The SynonymUpdated event shall contain embed fields.
*/
public function testSynonymUpdatedEventEmbedFields(): void
{
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
test('synonym updated event embed fields', function () {
$synonym = AnimeSynonym::factory()
->for(Anime::factory())
->createOne();
$changes = AnimeSynonym::factory()
->for(Anime::factory())
->makeOne();
$changes = AnimeSynonym::factory()
->for(Anime::factory())
->makeOne();
$synonym->fill($changes->getAttributes());
$synonym->save();
$synonym->fill($changes->getAttributes());
$synonym->save();
Event::assertDispatched(SynonymUpdated::class, function (SynonymUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(SynonymUpdated::class, function (SynonymUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki\Anime\Theme;
use App\Events\Wiki\Anime\Theme\Entry\EntryCreated;
use App\Events\Wiki\Anime\Theme\Entry\EntryDeleted;
use App\Events\Wiki\Anime\Theme\Entry\EntryRestored;
@@ -13,105 +11,75 @@ use App\Models\Wiki\Anime\AnimeTheme;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class EntryTest extends TestCase
{
/**
* When an Entry is created, an EntryCreated event shall be dispatched.
*/
public function testEntryCreatedEventDispatched(): void
{
AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('entry created event dispatched', function () {
AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
Event::assertDispatched(EntryCreated::class);
}
Event::assertDispatched(EntryCreated::class);
});
/**
* When an Entry is deleted, an EntryDeleted event shall be dispatched.
*/
public function testEntryDeletedEventDispatched(): void
{
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('entry deleted event dispatched', function () {
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$entry->delete();
$entry->delete();
Event::assertDispatched(EntryDeleted::class);
}
Event::assertDispatched(EntryDeleted::class);
});
/**
* When an Entry is restored, an EntryRestored event shall be dispatched.
*/
public function testEntryRestoredEventDispatched(): void
{
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('entry restored event dispatched', function () {
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$entry->restore();
$entry->restore();
Event::assertDispatched(EntryRestored::class);
}
Event::assertDispatched(EntryRestored::class);
});
/**
* When an Entry is restored, an EntryUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testEntryRestoresQuietly(): void
{
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('entry restores quietly', function () {
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$entry->restore();
$entry->restore();
Event::assertNotDispatched(EntryUpdated::class);
}
Event::assertNotDispatched(EntryUpdated::class);
});
/**
* When an Entry is updated, an EntryUpdated event shall be dispatched.
*/
public function testEntryUpdatedEventDispatched(): void
{
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('entry updated event dispatched', function () {
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$changes = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->makeOne();
$changes = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->makeOne();
$entry->fill($changes->getAttributes());
$entry->save();
$entry->fill($changes->getAttributes());
$entry->save();
Event::assertDispatched(EntryUpdated::class);
}
Event::assertDispatched(EntryUpdated::class);
});
/**
* The EntryUpdated event shall contain embed fields.
*/
public function testEntryUpdatedEventEmbedFields(): void
{
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
test('entry updated event embed fields', function () {
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->createOne();
$changes = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->makeOne();
$changes = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->makeOne();
$entry->fill($changes->getAttributes());
$entry->save();
$entry->fill($changes->getAttributes());
$entry->save();
Event::assertDispatched(EntryUpdated::class, function (EntryUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(EntryUpdated::class, function (EntryUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+52 -84
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki\Anime;
use App\Events\Wiki\Anime\Theme\ThemeCreated;
use App\Events\Wiki\Anime\Theme\ThemeDeleted;
use App\Events\Wiki\Anime\Theme\ThemeRestored;
@@ -12,105 +10,75 @@ use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeTheme;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ThemeTest extends TestCase
{
/**
* When a Theme is created, a ThemeCreated event shall be dispatched.
*/
public function testThemeCreatedEventDispatched(): void
{
AnimeTheme::factory()
->for(Anime::factory())
->createOne();
test('theme created event dispatched', function () {
AnimeTheme::factory()
->for(Anime::factory())
->createOne();
Event::assertDispatched(ThemeCreated::class);
}
Event::assertDispatched(ThemeCreated::class);
});
/**
* When a Theme is deleted, a ThemeDeleted event shall be dispatched.
*/
public function testThemeDeletedEventDispatched(): void
{
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
test('theme deleted event dispatched', function () {
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
$theme->delete();
$theme->delete();
Event::assertDispatched(ThemeDeleted::class);
}
Event::assertDispatched(ThemeDeleted::class);
});
/**
* When a Theme is restored, a ThemeRestored event shall be dispatched.
*/
public function testThemeRestoredEventDispatched(): void
{
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
test('theme restored event dispatched', function () {
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
$theme->restore();
$theme->restore();
Event::assertDispatched(ThemeRestored::class);
}
Event::assertDispatched(ThemeRestored::class);
});
/**
* When a Theme is restored, a ThemeUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testThemeRestoresQuietly(): void
{
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
test('theme restores quietly', function () {
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
$theme->restore();
$theme->restore();
Event::assertNotDispatched(ThemeUpdated::class);
}
Event::assertNotDispatched(ThemeUpdated::class);
});
/**
* When a Theme is updated, a ThemeUpdated event shall be dispatched.
*/
public function testThemeUpdatedEventDispatched(): void
{
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
test('theme updated event dispatched', function () {
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
$changes = AnimeTheme::factory()
->for(Anime::factory())
->makeOne();
$changes = AnimeTheme::factory()
->for(Anime::factory())
->makeOne();
$theme->fill($changes->getAttributes());
$theme->save();
$theme->fill($changes->getAttributes());
$theme->save();
Event::assertDispatched(ThemeUpdated::class);
}
Event::assertDispatched(ThemeUpdated::class);
});
/**
* The ThemeUpdated event shall contain embed fields.
*/
public function testThemeUpdatedEventEmbedFields(): void
{
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
test('theme updated event embed fields', function () {
$theme = AnimeTheme::factory()
->for(Anime::factory())
->createOne();
$changes = AnimeTheme::factory()
->for(Anime::factory())
->makeOne();
$changes = AnimeTheme::factory()
->for(Anime::factory())
->makeOne();
$theme->fill($changes->getAttributes());
$theme->save();
$theme->fill($changes->getAttributes());
$theme->save();
Event::assertDispatched(ThemeUpdated::class, function (ThemeUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(ThemeUpdated::class, function (ThemeUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Anime\AnimeCreated;
use App\Events\Wiki\Anime\AnimeDeleted;
use App\Events\Wiki\Anime\AnimeRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Anime\AnimeUpdated;
use App\Models\Wiki\Anime;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class AnimeTest extends TestCase
{
/**
* When an Anime is created, an AnimeCreated event shall be dispatched.
*/
public function testAnimeCreatedEventDispatched(): void
{
Anime::factory()->createOne();
test('anime created event dispatched', function () {
Anime::factory()->createOne();
Event::assertDispatched(AnimeCreated::class);
}
Event::assertDispatched(AnimeCreated::class);
});
/**
* When an Anime is deleted, an AnimeDeleted event shall be dispatched.
*/
public function testAnimeDeletedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
test('anime deleted event dispatched', function () {
$anime = Anime::factory()->createOne();
$anime->delete();
$anime->delete();
Event::assertDispatched(AnimeDeleted::class);
}
Event::assertDispatched(AnimeDeleted::class);
});
/**
* When an Anime is restored, an AnimeRestored event shall be dispatched.
*/
public function testAnimeRestoredEventDispatched(): void
{
$anime = Anime::factory()->createOne();
test('anime restored event dispatched', function () {
$anime = Anime::factory()->createOne();
$anime->restore();
$anime->restore();
Event::assertDispatched(AnimeRestored::class);
}
Event::assertDispatched(AnimeRestored::class);
});
/**
* When an Anime is restored, an AnimeUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testAnimeRestoresQuietly(): void
{
$anime = Anime::factory()->createOne();
test('anime restores quietly', function () {
$anime = Anime::factory()->createOne();
$anime->restore();
$anime->restore();
Event::assertNotDispatched(AnimeUpdated::class);
}
Event::assertNotDispatched(AnimeUpdated::class);
});
/**
* When an Anime is updated, an AnimeUpdated event shall be dispatched.
*/
public function testAnimeUpdatedEventDispatched(): void
{
$anime = Anime::factory()->createOne();
$changes = Anime::factory()->makeOne();
test('anime updated event dispatched', function () {
$anime = Anime::factory()->createOne();
$changes = Anime::factory()->makeOne();
$anime->fill($changes->getAttributes());
$anime->save();
$anime->fill($changes->getAttributes());
$anime->save();
Event::assertDispatched(AnimeUpdated::class);
}
Event::assertDispatched(AnimeUpdated::class);
});
/**
* The AnimeUpdated event shall contain embed fields.
*/
public function testAnimeUpdatedEventEmbedFields(): void
{
$anime = Anime::factory()->createOne();
$changes = Anime::factory()->makeOne();
test('anime updated event embed fields', function () {
$anime = Anime::factory()->createOne();
$changes = Anime::factory()->makeOne();
$anime->fill($changes->getAttributes());
$anime->save();
$anime->fill($changes->getAttributes());
$anime->save();
Event::assertDispatched(AnimeUpdated::class, function (AnimeUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(AnimeUpdated::class, function (AnimeUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Artist\ArtistCreated;
use App\Events\Wiki\Artist\ArtistDeleted;
use App\Events\Wiki\Artist\ArtistRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Artist\ArtistUpdated;
use App\Models\Wiki\Artist;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ArtistTest extends TestCase
{
/**
* When an Artist is created, an ArtistCreated event shall be dispatched.
*/
public function testArtistCreatedEventDispatched(): void
{
Artist::factory()->createOne();
test('artist created event dispatched', function () {
Artist::factory()->createOne();
Event::assertDispatched(ArtistCreated::class);
}
Event::assertDispatched(ArtistCreated::class);
});
/**
* When an Artist is deleted, an ArtistDeleted event shall be dispatched.
*/
public function testArtistDeletedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
test('artist deleted event dispatched', function () {
$artist = Artist::factory()->createOne();
$artist->delete();
$artist->delete();
Event::assertDispatched(ArtistDeleted::class);
}
Event::assertDispatched(ArtistDeleted::class);
});
/**
* When an Artist is restored, an ArtistRestored event shall be dispatched.
*/
public function testArtistRestoredEventDispatched(): void
{
$artist = Artist::factory()->createOne();
test('artist restored event dispatched', function () {
$artist = Artist::factory()->createOne();
$artist->restore();
$artist->restore();
Event::assertDispatched(ArtistRestored::class);
}
Event::assertDispatched(ArtistRestored::class);
});
/**
* When an Artist is restored, an ArtistUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testArtistRestoresQuietly(): void
{
$artist = Artist::factory()->createOne();
test('artist restores quietly', function () {
$artist = Artist::factory()->createOne();
$artist->restore();
$artist->restore();
Event::assertNotDispatched(ArtistUpdated::class);
}
Event::assertNotDispatched(ArtistUpdated::class);
});
/**
* When an Artist is updated, an ArtistUpdated event shall be dispatched.
*/
public function testArtistUpdatedEventDispatched(): void
{
$artist = Artist::factory()->createOne();
$changes = Artist::factory()->makeOne();
test('artist updated event dispatched', function () {
$artist = Artist::factory()->createOne();
$changes = Artist::factory()->makeOne();
$artist->fill($changes->getAttributes());
$artist->save();
$artist->fill($changes->getAttributes());
$artist->save();
Event::assertDispatched(ArtistUpdated::class);
}
Event::assertDispatched(ArtistUpdated::class);
});
/**
* The ArtistUpdated event shall contain embed fields.
*/
public function testArtistUpdatedEventEmbedFields(): void
{
$artist = Artist::factory()->createOne();
$changes = Artist::factory()->makeOne();
test('artist updated event embed fields', function () {
$artist = Artist::factory()->createOne();
$changes = Artist::factory()->makeOne();
$artist->fill($changes->getAttributes());
$artist->save();
$artist->fill($changes->getAttributes());
$artist->save();
Event::assertDispatched(ArtistUpdated::class, function (ArtistUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(ArtistUpdated::class, function (ArtistUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Audio\AudioCreated;
use App\Events\Wiki\Audio\AudioDeleted;
use App\Events\Wiki\Audio\AudioRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Audio\AudioUpdated;
use App\Models\Wiki\Audio;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class AudioTest extends TestCase
{
/**
* When an Audio is created, an AudioCreated event shall be dispatched.
*/
public function testAudioCreatedEventDispatched(): void
{
Audio::factory()->createOne();
test('audio created event dispatched', function () {
Audio::factory()->createOne();
Event::assertDispatched(AudioCreated::class);
}
Event::assertDispatched(AudioCreated::class);
});
/**
* When an Audio is deleted, an AudioDeleted event shall be dispatched.
*/
public function testAudioDeletedEventDispatched(): void
{
$audio = Audio::factory()->createOne();
test('audio deleted event dispatched', function () {
$audio = Audio::factory()->createOne();
$audio->delete();
$audio->delete();
Event::assertDispatched(AudioDeleted::class);
}
Event::assertDispatched(AudioDeleted::class);
});
/**
* When an Audio is restored, an AudioRestored event shall be dispatched.
*/
public function testAudioRestoredEventDispatched(): void
{
$audio = Audio::factory()->createOne();
test('audio restored event dispatched', function () {
$audio = Audio::factory()->createOne();
$audio->restore();
$audio->restore();
Event::assertDispatched(AudioRestored::class);
}
Event::assertDispatched(AudioRestored::class);
});
/**
* When an Audio is restored, an AudioUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testAudioRestoresQuietly(): void
{
$audio = Audio::factory()->createOne();
test('audio restores quietly', function () {
$audio = Audio::factory()->createOne();
$audio->restore();
$audio->restore();
Event::assertNotDispatched(AudioUpdated::class);
}
Event::assertNotDispatched(AudioUpdated::class);
});
/**
* When an Audio is updated, an AudioUpdated event shall be dispatched.
*/
public function testAudioUpdatedEventDispatched(): void
{
$audio = Audio::factory()->createOne();
$changes = Audio::factory()->makeOne();
test('audio updated event dispatched', function () {
$audio = Audio::factory()->createOne();
$changes = Audio::factory()->makeOne();
$audio->fill($changes->getAttributes());
$audio->save();
$audio->fill($changes->getAttributes());
$audio->save();
Event::assertDispatched(AudioUpdated::class);
}
Event::assertDispatched(AudioUpdated::class);
});
/**
* The AudioUpdated event shall contain embed fields.
*/
public function testAudioUpdatedEventEmbedFields(): void
{
$audio = Audio::factory()->createOne();
$changes = Audio::factory()->makeOne();
test('audio updated event embed fields', function () {
$audio = Audio::factory()->createOne();
$changes = Audio::factory()->makeOne();
$audio->fill($changes->getAttributes());
$audio->save();
$audio->fill($changes->getAttributes());
$audio->save();
Event::assertDispatched(AudioUpdated::class, function (AudioUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(AudioUpdated::class, function (AudioUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\ExternalResource\ExternalResourceCreated;
use App\Events\Wiki\ExternalResource\ExternalResourceDeleted;
use App\Events\Wiki\ExternalResource\ExternalResourceRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\ExternalResource\ExternalResourceUpdated;
use App\Models\Wiki\ExternalResource;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ExternalResourceTest extends TestCase
{
/**
* When a Resource is created, an ExternalResourceCreated event shall be dispatched.
*/
public function testExternalResourceCreatedEventDispatched(): void
{
ExternalResource::factory()->createOne();
test('external resource created event dispatched', function () {
ExternalResource::factory()->createOne();
Event::assertDispatched(ExternalResourceCreated::class);
}
Event::assertDispatched(ExternalResourceCreated::class);
});
/**
* When a Resource is deleted, an ExternalResourceDeleted event shall be dispatched.
*/
public function testExternalResourceDeletedEventDispatched(): void
{
$resource = ExternalResource::factory()->createOne();
test('external resource deleted event dispatched', function () {
$resource = ExternalResource::factory()->createOne();
$resource->delete();
$resource->delete();
Event::assertDispatched(ExternalResourceDeleted::class);
}
Event::assertDispatched(ExternalResourceDeleted::class);
});
/**
* When a Resource is restored, an ExternalResourceRestored event shall be dispatched.
*/
public function testExternalResourceRestoredEventDispatched(): void
{
$resource = ExternalResource::factory()->createOne();
test('external resource restored event dispatched', function () {
$resource = ExternalResource::factory()->createOne();
$resource->restore();
$resource->restore();
Event::assertDispatched(ExternalResourceRestored::class);
}
Event::assertDispatched(ExternalResourceRestored::class);
});
/**
* When a Resource is restored, an ExternalResourceUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testExternalResourceRestoresQuietly(): void
{
$resource = ExternalResource::factory()->createOne();
test('external resource restores quietly', function () {
$resource = ExternalResource::factory()->createOne();
$resource->restore();
$resource->restore();
Event::assertNotDispatched(ExternalResourceUpdated::class);
}
Event::assertNotDispatched(ExternalResourceUpdated::class);
});
/**
* When an ExternalResource is updated, an ExternalResourceUpdated event shall be dispatched.
*/
public function testExternalResourceUpdatedEventDispatched(): void
{
$resource = ExternalResource::factory()->createOne();
$changes = ExternalResource::factory()->makeOne();
test('external resource updated event dispatched', function () {
$resource = ExternalResource::factory()->createOne();
$changes = ExternalResource::factory()->makeOne();
$resource->fill($changes->getAttributes());
$resource->save();
$resource->fill($changes->getAttributes());
$resource->save();
Event::assertDispatched(ExternalResourceUpdated::class);
}
Event::assertDispatched(ExternalResourceUpdated::class);
});
/**
* The ExternalResourceUpdated event shall contain embed fields.
*/
public function testExternalResourceUpdatedEventEmbedFields(): void
{
$resource = ExternalResource::factory()->createOne();
$changes = ExternalResource::factory()->makeOne();
test('external resource updated event embed fields', function () {
$resource = ExternalResource::factory()->createOne();
$changes = ExternalResource::factory()->makeOne();
$resource->fill($changes->getAttributes());
$resource->save();
$resource->fill($changes->getAttributes());
$resource->save();
Event::assertDispatched(ExternalResourceUpdated::class, function (ExternalResourceUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(ExternalResourceUpdated::class, function (ExternalResourceUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Group\GroupCreated;
use App\Events\Wiki\Group\GroupDeleted;
use App\Events\Wiki\Group\GroupRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Group\GroupUpdated;
use App\Models\Wiki\Group;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class GroupTest extends TestCase
{
/**
* When a Group is created, a GroupCreated event shall be dispatched.
*/
public function testGroupCreatedEventDispatched(): void
{
Group::factory()->createOne();
test('group created event dispatched', function () {
Group::factory()->createOne();
Event::assertDispatched(GroupCreated::class);
}
Event::assertDispatched(GroupCreated::class);
});
/**
* When a Group is deleted, a GroupDeleted event shall be dispatched.
*/
public function testGroupDeletedEventDispatched(): void
{
$group = Group::factory()->createOne();
test('group deleted event dispatched', function () {
$group = Group::factory()->createOne();
$group->delete();
$group->delete();
Event::assertDispatched(GroupDeleted::class);
}
Event::assertDispatched(GroupDeleted::class);
});
/**
* When a Group is restored, a GroupRestored event shall be dispatched.
*/
public function testGroupRestoredEventDispatched(): void
{
$group = Group::factory()->createOne();
test('group restored event dispatched', function () {
$group = Group::factory()->createOne();
$group->restore();
$group->restore();
Event::assertDispatched(GroupRestored::class);
}
Event::assertDispatched(GroupRestored::class);
});
/**
* When a Group is restored, a GroupUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testGroupRestoresQuietly(): void
{
$group = Group::factory()->createOne();
test('group restores quietly', function () {
$group = Group::factory()->createOne();
$group->restore();
$group->restore();
Event::assertNotDispatched(GroupUpdated::class);
}
Event::assertNotDispatched(GroupUpdated::class);
});
/**
* When a Group is updated, a GroupUpdated event shall be dispatched.
*/
public function testGroupUpdatedEventDispatched(): void
{
$group = Group::factory()->createOne();
$changes = Group::factory()->makeOne();
test('group updated event dispatched', function () {
$group = Group::factory()->createOne();
$changes = Group::factory()->makeOne();
$group->fill($changes->getAttributes());
$group->save();
$group->fill($changes->getAttributes());
$group->save();
Event::assertDispatched(GroupUpdated::class);
}
Event::assertDispatched(GroupUpdated::class);
});
/**
* The GroupUpdated event shall contain embed fields.
*/
public function testGroupUpdatedEventEmbedFields(): void
{
$group = Group::factory()->createOne();
$changes = Group::factory()->makeOne();
test('group updated event embed fields', function () {
$group = Group::factory()->createOne();
$changes = Group::factory()->makeOne();
$group->fill($changes->getAttributes());
$group->save();
$group->fill($changes->getAttributes());
$group->save();
Event::assertDispatched(GroupUpdated::class, function (GroupUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(GroupUpdated::class, function (GroupUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Image\ImageCreated;
use App\Events\Wiki\Image\ImageDeleted;
use App\Events\Wiki\Image\ImageRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Image\ImageUpdated;
use App\Models\Wiki\Image;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ImageTest extends TestCase
{
/**
* When an Image is created, an ImageCreated event shall be dispatched.
*/
public function testImageCreatedEventDispatched(): void
{
Image::factory()->createOne();
test('image created event dispatched', function () {
Image::factory()->createOne();
Event::assertDispatched(ImageCreated::class);
}
Event::assertDispatched(ImageCreated::class);
});
/**
* When an Image is deleted, an ImageDeleted event shall be dispatched.
*/
public function testImageDeletedEventDispatched(): void
{
$image = Image::factory()->createOne();
test('image deleted event dispatched', function () {
$image = Image::factory()->createOne();
$image->delete();
$image->delete();
Event::assertDispatched(ImageDeleted::class);
}
Event::assertDispatched(ImageDeleted::class);
});
/**
* When an Image is restored, an ImageRestored event shall be dispatched.
*/
public function testImageRestoredEventDispatched(): void
{
$image = Image::factory()->createOne();
test('image restored event dispatched', function () {
$image = Image::factory()->createOne();
$image->restore();
$image->restore();
Event::assertDispatched(ImageRestored::class);
}
Event::assertDispatched(ImageRestored::class);
});
/**
* When an Image is restored, an ImageUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testImageRestoresQuietly(): void
{
$image = Image::factory()->createOne();
test('image restores quietly', function () {
$image = Image::factory()->createOne();
$image->restore();
$image->restore();
Event::assertNotDispatched(ImageUpdated::class);
}
Event::assertNotDispatched(ImageUpdated::class);
});
/**
* When an Image is updated, an ImageUpdated event shall be dispatched.
*/
public function testImageUpdatedEventDispatched(): void
{
$image = Image::factory()->createOne();
$changes = Image::factory()->makeOne();
test('image updated event dispatched', function () {
$image = Image::factory()->createOne();
$changes = Image::factory()->makeOne();
$image->fill($changes->getAttributes());
$image->save();
$image->fill($changes->getAttributes());
$image->save();
Event::assertDispatched(ImageUpdated::class);
}
Event::assertDispatched(ImageUpdated::class);
});
/**
* The ImageUpdated event shall contain embed fields.
*/
public function testImageUpdatedEventEmbedFields(): void
{
$image = Image::factory()->createOne();
$changes = Image::factory()->makeOne();
test('image updated event embed fields', function () {
$image = Image::factory()->createOne();
$changes = Image::factory()->makeOne();
$image->fill($changes->getAttributes());
$image->save();
$image->fill($changes->getAttributes());
$image->save();
Event::assertDispatched(ImageUpdated::class, function (ImageUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(ImageUpdated::class, function (ImageUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Series\SeriesCreated;
use App\Events\Wiki\Series\SeriesDeleted;
use App\Events\Wiki\Series\SeriesRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Series\SeriesUpdated;
use App\Models\Wiki\Series;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class SeriesTest extends TestCase
{
/**
* When a Series is created, a SeriesCreated event shall be dispatched.
*/
public function testSeriesCreatedEventDispatched(): void
{
Series::factory()->createOne();
test('series created event dispatched', function () {
Series::factory()->createOne();
Event::assertDispatched(SeriesCreated::class);
}
Event::assertDispatched(SeriesCreated::class);
});
/**
* When a Series is deleted, a SeriesDeleted event shall be dispatched.
*/
public function testSeriesDeletedEventDispatched(): void
{
$series = Series::factory()->createOne();
test('series deleted event dispatched', function () {
$series = Series::factory()->createOne();
$series->delete();
$series->delete();
Event::assertDispatched(SeriesDeleted::class);
}
Event::assertDispatched(SeriesDeleted::class);
});
/**
* When a Series is restored, a SeriesRestored event shall be dispatched.
*/
public function testSeriesRestoredEventDispatched(): void
{
$series = Series::factory()->createOne();
test('series restored event dispatched', function () {
$series = Series::factory()->createOne();
$series->restore();
$series->restore();
Event::assertDispatched(SeriesRestored::class);
}
Event::assertDispatched(SeriesRestored::class);
});
/**
* When a Series is restored, a SeriesUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testSeriesRestoresQuietly(): void
{
$series = Series::factory()->createOne();
test('series restores quietly', function () {
$series = Series::factory()->createOne();
$series->restore();
$series->restore();
Event::assertNotDispatched(SeriesUpdated::class);
}
Event::assertNotDispatched(SeriesUpdated::class);
});
/**
* When a Series is updated, a SeriesUpdated event shall be dispatched.
*/
public function testSeriesUpdatedEventDispatched(): void
{
$series = Series::factory()->createOne();
$changes = Series::factory()->makeOne();
test('series updated event dispatched', function () {
$series = Series::factory()->createOne();
$changes = Series::factory()->makeOne();
$series->fill($changes->getAttributes());
$series->save();
$series->fill($changes->getAttributes());
$series->save();
Event::assertDispatched(SeriesUpdated::class);
}
Event::assertDispatched(SeriesUpdated::class);
});
/**
* The SeriesUpdated event shall contain embed fields.
*/
public function testSeriesUpdatedEventEmbedFields(): void
{
$series = Series::factory()->createOne();
$changes = Series::factory()->makeOne();
test('series updated event embed fields', function () {
$series = Series::factory()->createOne();
$changes = Series::factory()->makeOne();
$series->fill($changes->getAttributes());
$series->save();
$series->fill($changes->getAttributes());
$series->save();
Event::assertDispatched(SeriesUpdated::class, function (SeriesUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(SeriesUpdated::class, function (SeriesUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Song\SongCreated;
use App\Events\Wiki\Song\SongDeleted;
use App\Events\Wiki\Song\SongRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Song\SongUpdated;
use App\Models\Wiki\Song;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class SongTest extends TestCase
{
/**
* When a Song is created, a SongCreated event shall be dispatched.
*/
public function testSongCreatedEventDispatched(): void
{
Song::factory()->createOne();
test('song created event dispatched', function () {
Song::factory()->createOne();
Event::assertDispatched(SongCreated::class);
}
Event::assertDispatched(SongCreated::class);
});
/**
* When a Song is deleted, a SongDeleted event shall be dispatched.
*/
public function testSongDeletedEventDispatched(): void
{
$song = Song::factory()->createOne();
test('song deleted event dispatched', function () {
$song = Song::factory()->createOne();
$song->delete();
$song->delete();
Event::assertDispatched(SongDeleted::class);
}
Event::assertDispatched(SongDeleted::class);
});
/**
* When a Song is restored, a SongRestored event shall be dispatched.
*/
public function testSongRestoredEventDispatched(): void
{
$song = Song::factory()->createOne();
test('song restored event dispatched', function () {
$song = Song::factory()->createOne();
$song->restore();
$song->restore();
Event::assertDispatched(SongRestored::class);
}
Event::assertDispatched(SongRestored::class);
});
/**
* When a Song is restored, a SongUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testSongRestoresQuietly(): void
{
$song = Song::factory()->createOne();
test('song restores quietly', function () {
$song = Song::factory()->createOne();
$song->restore();
$song->restore();
Event::assertNotDispatched(SongUpdated::class);
}
Event::assertNotDispatched(SongUpdated::class);
});
/**
* When a Song is updated, a SongUpdated event shall be dispatched.
*/
public function testSongUpdatedEventDispatched(): void
{
$song = Song::factory()->createOne();
$changes = Song::factory()->makeOne();
test('song updated event dispatched', function () {
$song = Song::factory()->createOne();
$changes = Song::factory()->makeOne();
$song->fill($changes->getAttributes());
$song->save();
$song->fill($changes->getAttributes());
$song->save();
Event::assertDispatched(SongUpdated::class);
}
Event::assertDispatched(SongUpdated::class);
});
/**
* The SongUpdated event shall contain embed fields.
*/
public function testSongUpdatedEventEmbedFields(): void
{
$song = Song::factory()->createOne();
$changes = Song::factory()->makeOne();
test('song updated event embed fields', function () {
$song = Song::factory()->createOne();
$changes = Song::factory()->makeOne();
$song->fill($changes->getAttributes());
$song->save();
$song->fill($changes->getAttributes());
$song->save();
Event::assertDispatched(SongUpdated::class, function (SongUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(SongUpdated::class, function (SongUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Studio\StudioCreated;
use App\Events\Wiki\Studio\StudioDeleted;
use App\Events\Wiki\Studio\StudioRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Studio\StudioUpdated;
use App\Models\Wiki\Studio;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class StudioTest extends TestCase
{
/**
* When a Studio is created, a StudioCreated event shall be dispatched.
*/
public function testStudioCreatedEventDispatched(): void
{
Studio::factory()->createOne();
test('studio created event dispatched', function () {
Studio::factory()->createOne();
Event::assertDispatched(StudioCreated::class);
}
Event::assertDispatched(StudioCreated::class);
});
/**
* When a Studio is deleted, a StudioDeleted event shall be dispatched.
*/
public function testStudioDeletedEventDispatched(): void
{
$studio = Studio::factory()->createOne();
test('studio deleted event dispatched', function () {
$studio = Studio::factory()->createOne();
$studio->delete();
$studio->delete();
Event::assertDispatched(StudioDeleted::class);
}
Event::assertDispatched(StudioDeleted::class);
});
/**
* When a Studio is restored, a StudioRestored event shall be dispatched.
*/
public function testStudioRestoredEventDispatched(): void
{
$studio = Studio::factory()->createOne();
test('studio restored event dispatched', function () {
$studio = Studio::factory()->createOne();
$studio->restore();
$studio->restore();
Event::assertDispatched(StudioRestored::class);
}
Event::assertDispatched(StudioRestored::class);
});
/**
* When a Studio is restored, a StudioUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testStudioRestoresQuietly(): void
{
$studio = Studio::factory()->createOne();
test('studio restores quietly', function () {
$studio = Studio::factory()->createOne();
$studio->restore();
$studio->restore();
Event::assertNotDispatched(StudioUpdated::class);
}
Event::assertNotDispatched(StudioUpdated::class);
});
/**
* When a Studio is updated, a StudioUpdated event shall be dispatched.
*/
public function testStudioUpdatedEventDispatched(): void
{
$studio = Studio::factory()->createOne();
$changes = Studio::factory()->makeOne();
test('studio updated event dispatched', function () {
$studio = Studio::factory()->createOne();
$changes = Studio::factory()->makeOne();
$studio->fill($changes->getAttributes());
$studio->save();
$studio->fill($changes->getAttributes());
$studio->save();
Event::assertDispatched(StudioUpdated::class);
}
Event::assertDispatched(StudioUpdated::class);
});
/**
* The StudioUpdated event shall contain embed fields.
*/
public function testStudioUpdatedEventEmbedFields(): void
{
$studio = Studio::factory()->createOne();
$changes = Studio::factory()->makeOne();
test('studio updated event embed fields', function () {
$studio = Studio::factory()->createOne();
$changes = Studio::factory()->makeOne();
$studio->fill($changes->getAttributes());
$studio->save();
$studio->fill($changes->getAttributes());
$studio->save();
Event::assertDispatched(StudioUpdated::class, function (StudioUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(StudioUpdated::class, function (StudioUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki\Video;
use App\Events\Wiki\Video\Script\VideoScriptCreated;
use App\Events\Wiki\Video\Script\VideoScriptDeleted;
use App\Events\Wiki\Video\Script\VideoScriptRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Video\Script\VideoScriptUpdated;
use App\Models\Wiki\Video\VideoScript;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ScriptTest extends TestCase
{
/**
* When a Script is created, a VideoScriptCreated event shall be dispatched.
*/
public function testVideoScriptCreatedEventDispatched(): void
{
VideoScript::factory()->createOne();
test('video script created event dispatched', function () {
VideoScript::factory()->createOne();
Event::assertDispatched(VideoScriptCreated::class);
}
Event::assertDispatched(VideoScriptCreated::class);
});
/**
* When a Script is deleted, a VideoScriptDeleted event shall be dispatched.
*/
public function testVideoScriptDeletedEventDispatched(): void
{
$script = VideoScript::factory()->createOne();
test('video script deleted event dispatched', function () {
$script = VideoScript::factory()->createOne();
$script->delete();
$script->delete();
Event::assertDispatched(VideoScriptDeleted::class);
}
Event::assertDispatched(VideoScriptDeleted::class);
});
/**
* When a Script is restored, a VideoScriptRestored event shall be dispatched.
*/
public function testVideoScriptRestoredEventDispatched(): void
{
$script = VideoScript::factory()->createOne();
test('video script restored event dispatched', function () {
$script = VideoScript::factory()->createOne();
$script->restore();
$script->restore();
Event::assertDispatched(VideoScriptRestored::class);
}
Event::assertDispatched(VideoScriptRestored::class);
});
/**
* When a Script is restored, a VideoScriptUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testVideoScriptRestoresQuietly(): void
{
$script = VideoScript::factory()->createOne();
test('video script restores quietly', function () {
$script = VideoScript::factory()->createOne();
$script->restore();
$script->restore();
Event::assertNotDispatched(VideoScriptUpdated::class);
}
Event::assertNotDispatched(VideoScriptUpdated::class);
});
/**
* When a Script is updated, a VideoScriptUpdated event shall be dispatched.
*/
public function testVideoScriptUpdatedEventDispatched(): void
{
$script = VideoScript::factory()->createOne();
$changes = VideoScript::factory()->makeOne();
test('video script updated event dispatched', function () {
$script = VideoScript::factory()->createOne();
$changes = VideoScript::factory()->makeOne();
$script->fill($changes->getAttributes());
$script->save();
$script->fill($changes->getAttributes());
$script->save();
Event::assertDispatched(VideoScriptUpdated::class);
}
Event::assertDispatched(VideoScriptUpdated::class);
});
/**
* The VideoScriptUpdated event shall contain embed fields.
*/
public function testVideoScriptUpdatedEventEmbedFields(): void
{
$script = VideoScript::factory()->createOne();
$changes = VideoScript::factory()->makeOne();
test('video script updated event embed fields', function () {
$script = VideoScript::factory()->createOne();
$changes = VideoScript::factory()->makeOne();
$script->fill($changes->getAttributes());
$script->save();
$script->fill($changes->getAttributes());
$script->save();
Event::assertDispatched(VideoScriptUpdated::class, function (VideoScriptUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(VideoScriptUpdated::class, function (VideoScriptUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
+36 -68
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Events\Wiki;
use App\Events\Wiki\Video\VideoCreated;
use App\Events\Wiki\Video\VideoDeleted;
use App\Events\Wiki\Video\VideoRestored;
@@ -11,87 +9,57 @@ use App\Events\Wiki\Video\VideoUpdated;
use App\Models\Wiki\Video;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class VideoTest extends TestCase
{
/**
* When a Video is created, a VideoCreated event shall be dispatched.
*/
public function testVideoCreatedEventDispatched(): void
{
Video::factory()->createOne();
test('video created event dispatched', function () {
Video::factory()->createOne();
Event::assertDispatched(VideoCreated::class);
}
Event::assertDispatched(VideoCreated::class);
});
/**
* When a Video is deleted, a VideoDeleted event shall be dispatched.
*/
public function testVideoDeletedEventDispatched(): void
{
$video = Video::factory()->createOne();
test('video deleted event dispatched', function () {
$video = Video::factory()->createOne();
$video->delete();
$video->delete();
Event::assertDispatched(VideoDeleted::class);
}
Event::assertDispatched(VideoDeleted::class);
});
/**
* When a Video is restored, a VideoRestored event shall be dispatched.
*/
public function testVideoRestoredEventDispatched(): void
{
$video = Video::factory()->createOne();
test('video restored event dispatched', function () {
$video = Video::factory()->createOne();
$video->restore();
$video->restore();
Event::assertDispatched(VideoRestored::class);
}
Event::assertDispatched(VideoRestored::class);
});
/**
* When a Video is restored, a VideoUpdated event shall not be dispatched.
* Note: This is a customization that overrides default framework behavior.
* An updated event is fired on restore.
*/
public function testVideoRestoresQuietly(): void
{
$video = Video::factory()->createOne();
test('video restores quietly', function () {
$video = Video::factory()->createOne();
$video->restore();
$video->restore();
Event::assertNotDispatched(VideoUpdated::class);
}
Event::assertNotDispatched(VideoUpdated::class);
});
/**
* When a Video is updated, a VideoUpdated event shall be dispatched.
*/
public function testVideoUpdatedEventDispatched(): void
{
$video = Video::factory()->createOne();
$changes = Video::factory()->makeOne();
test('video updated event dispatched', function () {
$video = Video::factory()->createOne();
$changes = Video::factory()->makeOne();
$video->fill($changes->getAttributes());
$video->save();
$video->fill($changes->getAttributes());
$video->save();
Event::assertDispatched(VideoUpdated::class);
}
Event::assertDispatched(VideoUpdated::class);
});
/**
* The VideoUpdated event shall contain embed fields.
*/
public function testVideoUpdatedEventEmbedFields(): void
{
$video = Video::factory()->createOne();
$changes = Video::factory()->makeOne();
test('video updated event embed fields', function () {
$video = Video::factory()->createOne();
$changes = Video::factory()->makeOne();
$video->fill($changes->getAttributes());
$video->save();
$video->fill($changes->getAttributes());
$video->save();
Event::assertDispatched(VideoUpdated::class, function (VideoUpdated $event) {
$message = $event->getDiscordMessage();
Event::assertDispatched(VideoUpdated::class, function (VideoUpdated $event) {
$message = $event->getDiscordMessage();
return ! empty(Arr::get($message->embed, 'fields'));
});
}
}
return ! empty(Arr::get($message->embed, 'fields'));
});
});
@@ -2,42 +2,32 @@
declare(strict_types=1);
namespace Tests\Feature\GraphQL\Queries;
use App\Models\Wiki\Anime;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class AnimeQueryTest extends TestCase
{
use WithFaker;
uses(Illuminate\Foundation\Testing\WithFaker::class);
/**
* The animeyears Query shall return a list of years.
*/
public function testAnimeYearsQuery(): void
{
static::markTestSkipped('TODO');
/** @phpstan-ignore-next-line */
$years = Anime::factory()
->count($this->faker->randomDigitNotNull())
->create()
->map(fn (Anime $anime) => $anime->getAttribute(Anime::ATTRIBUTE_YEAR))
->sortBy(fn (int $year) => $year)
->unique()
->values()
->toArray();
test('anime years query', function () {
$this->markTestSkipped('TODO');
$response = $this->graphQL('
/** @phpstan-ignore-next-line */
$years = Anime::factory()
->count(fake()->randomDigitNotNull())
->create()
->map(fn (Anime $anime) => $anime->getAttribute(Anime::ATTRIBUTE_YEAR))
->sortBy(fn (int $year) => $year)
->unique()
->values()
->toArray();
$response = $this->graphQL('
{
animeyears
}
');
$response->assertJson([
'data' => [
'animeyears' => $years,
],
]);
}
}
$response->assertJson([
'data' => [
'animeyears' => $years,
],
]);
});
+43 -66
View File
@@ -2,100 +2,77 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Admin;
use App\Constants\Config\DumpConstants;
use App\Enums\Auth\SpecialPermission;
use App\Features\AllowDumpDownloading;
use App\Models\Admin\Dump;
use App\Models\Auth\User;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Laravel\Pennant\Feature;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class DumpTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* If dump downloading is disabled through the Allow Dump Downloading feature,
* the user shall receive a forbidden exception.
*/
public function testDumpDownloadingNotAllowedForbidden(): void
{
Feature::deactivate(AllowDumpDownloading::class);
uses(Illuminate\Foundation\Testing\WithFaker::class);
$dump = Dump::factory()->createOne();
test('dump downloading not allowed forbidden', function () {
Feature::deactivate(AllowDumpDownloading::class);
$response = $this->get(route('dump.show', ['dump' => $dump]));
$dump = Dump::factory()->createOne();
$response->assertForbidden();
}
$response = get(route('dump.show', ['dump' => $dump]));
/**
* Unsafe dumps shall be forbidden.
*/
public function testDumpDownloadingForbiddenForUnsafeDumps(): void
{
Feature::activate(AllowDumpDownloading::class);
$response->assertForbidden();
});
$dump = Dump::factory()
->unsafe()
->createOne();
test('dump downloading forbidden for unsafe dumps', function () {
Feature::activate(AllowDumpDownloading::class);
$response = $this->get(route('dump.show', ['dump' => $dump]));
$dump = Dump::factory()
->unsafe()
->createOne();
$response->assertForbidden();
}
$response = get(route('dump.show', ['dump' => $dump]));
/**
* Users with the bypass feature flag permission shall be permitted to download dumps
* even if the Allow Dump Downloading feature is disabled.
*/
public function testVideoStreamingPermittedForBypass(): void
{
Feature::activate(AllowDumpDownloading::class, $this->faker->boolean());
$response->assertForbidden();
});
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$filename = Dump::factory()->makeOne()->path.'.sql';
$file = File::fake()->create($filename);
$fsFile = $fs->putFileAs('', $file, $filename);
test('video streaming permitted for bypass', function () {
Feature::activate(AllowDumpDownloading::class, fake()->boolean());
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$filename = Dump::factory()->makeOne()->path.'.sql';
$file = File::fake()->create($filename);
$fsFile = $fs->putFileAs('', $file, $filename);
$user = User::factory()->withPermissions(SpecialPermission::BYPASS_FEATURE_FLAGS->value)->createOne();
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(SpecialPermission::BYPASS_FEATURE_FLAGS->value)->createOne();
$response = $this->get(route('dump.show', ['dump' => $dump]));
Sanctum::actingAs($user);
$response->assertDownload($dump->path);
}
$response = get(route('dump.show', ['dump' => $dump]));
/**
* If dump downloading is enabled, the dump is downloaded from storage through the response.
*/
public function testDownloadedThroughResponse(): void
{
Feature::activate(AllowDumpDownloading::class);
$response->assertDownload($dump->path);
});
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$filename = Dump::factory()->makeOne()->path.'.sql';
$file = File::fake()->create($filename);
$fsFile = $fs->putFileAs('', $file, $filename);
test('downloaded through response', function () {
Feature::activate(AllowDumpDownloading::class);
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$filename = Dump::factory()->makeOne()->path.'.sql';
$file = File::fake()->create($filename);
$fsFile = $fs->putFileAs('', $file, $filename);
$response = $this->get(route('dump.show', ['dump' => $dump]));
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
$response->assertDownload($dump->path);
}
}
$response = get(route('dump.show', ['dump' => $dump]));
$response->assertDownload($dump->path);
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Admin;
use App\Actions\Storage\Admin\Dump\DumpDocumentAction;
use App\Actions\Storage\Admin\Dump\DumpWikiAction;
use App\Constants\Config\DumpConstants;
@@ -11,8 +9,6 @@ use App\Enums\Auth\SpecialPermission;
use App\Features\AllowDumpDownloading;
use App\Models\Admin\Dump;
use App\Models\Auth\User;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
@@ -20,150 +16,124 @@ use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Laravel\Pennant\Feature;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class LatestDocumentDumpTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* If dump downloading is disabled through the Allow Dump Downloading feature,
* the user shall receive a forbidden exception.
*
* @throws Exception
*/
public function testDumpDownloadingNotAllowedForbidden(): void
{
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
uses(Illuminate\Foundation\Testing\WithFaker::class);
Feature::deactivate(AllowDumpDownloading::class);
test('dump downloading not allowed forbidden', function () {
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Feature::deactivate(AllowDumpDownloading::class);
$action = new DumpWikiAction();
$action->handle();
$response = get(route('dump.latest.document.show'));
$response->assertForbidden();
});
test('video streaming permitted for bypass', function () {
Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Feature::activate(AllowDumpDownloading::class, fake()->boolean());
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
$action->handle();
});
$response = $this->get(route('dump.latest.document.show'));
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
$response->assertForbidden();
}
$action->handle();
});
/**
* Users with the bypass feature flag permission shall be permitted to download the latest document dump
* even if the Allow Dump Downloading feature is disabled.
*/
public function testVideoStreamingPermittedForBypass(): void
{
Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$path = Str::of(DumpDocumentAction::FILENAME_PREFIX)
->append(fake()->word())
->append('.sql')
->__toString();
Feature::activate(AllowDumpDownloading::class, $this->faker->boolean());
$file = File::fake()->create($path);
$fsFile = $fs->putFileAs('', $file, $path);
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
$action->handle();
});
$user = User::factory()->withPermissions(SpecialPermission::BYPASS_FEATURE_FLAGS->value)->createOne();
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
Sanctum::actingAs($user);
$action->handle();
});
$response = get(route('dump.latest.document.show'));
$path = Str::of(DumpDocumentAction::FILENAME_PREFIX)
->append($this->faker->word())
->append('.sql')
->__toString();
$response->assertDownload($dump->path);
});
$file = File::fake()->create($path);
$fsFile = $fs->putFileAs('', $file, $path);
test('not found if no document dumps', function () {
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
Feature::activate(AllowDumpDownloading::class);
$user = User::factory()->withPermissions(SpecialPermission::BYPASS_FEATURE_FLAGS->value)->createOne();
$response = get(route('dump.latest.document.show'));
Sanctum::actingAs($user);
$response->assertNotFound();
});
$response = $this->get(route('dump.latest.document.show'));
test('not found if wiki dumps exist', function () {
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$response->assertDownload($dump->path);
}
Feature::activate(AllowDumpDownloading::class);
/**
* If no dumps exist, the user shall receive a not found error.
*/
public function testNotFoundIfNoDocumentDumps(): void
{
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
Feature::activate(AllowDumpDownloading::class);
$action->handle();
});
$response = $this->get(route('dump.latest.document.show'));
$response = get(route('dump.latest.document.show'));
$response->assertNotFound();
}
$response->assertNotFound();
});
/**
* If no document dumps exist, the user shall receive a not found error.
*/
public function testNotFoundIfWikiDumpsExist(): void
{
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
test('latest document dump downloaded', function () {
Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Feature::activate(AllowDumpDownloading::class);
Feature::activate(AllowDumpDownloading::class);
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
$action->handle();
});
$action->handle();
});
$response = $this->get(route('dump.latest.document.show'));
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
$response->assertNotFound();
}
$action->handle();
});
/**
* If document dumps exist, the latest document dump is downloaded from storage through the response.
*/
public function testLatestDocumentDumpDownloaded(): void
{
Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$path = Str::of(DumpDocumentAction::FILENAME_PREFIX)
->append(fake()->word())
->append('.sql')
->__toString();
Feature::activate(AllowDumpDownloading::class);
$file = File::fake()->create($path);
$fsFile = $fs->putFileAs('', $file, $path);
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
$action->handle();
});
$response = get(route('dump.latest.document.show'));
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
$action->handle();
});
$path = Str::of(DumpDocumentAction::FILENAME_PREFIX)
->append($this->faker->word())
->append('.sql')
->__toString();
$file = File::fake()->create($path);
$fsFile = $fs->putFileAs('', $file, $path);
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
$response = $this->get(route('dump.latest.document.show'));
$response->assertDownload($dump->path);
}
}
$response->assertDownload($dump->path);
});
+86 -116
View File
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Admin;
use App\Actions\Storage\Admin\Dump\DumpDocumentAction;
use App\Actions\Storage\Admin\Dump\DumpWikiAction;
use App\Constants\Config\DumpConstants;
@@ -11,8 +9,6 @@ use App\Enums\Auth\SpecialPermission;
use App\Features\AllowDumpDownloading;
use App\Models\Admin\Dump;
use App\Models\Auth\User;
use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
@@ -20,150 +16,124 @@ use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Laravel\Pennant\Feature;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class LatestWikiDumpTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* If dump downloading is disabled through the Allow Dump Downloading feature,
* the user shall receive a forbidden exception.
*
* @throws Exception
*/
public function testDumpDownloadingNotAllowedForbidden(): void
{
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
uses(Illuminate\Foundation\Testing\WithFaker::class);
Feature::deactivate(AllowDumpDownloading::class);
test('dump downloading not allowed forbidden', function () {
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Feature::deactivate(AllowDumpDownloading::class);
$action = new DumpWikiAction();
$action->handle();
$response = get(route('dump.latest.wiki.show'));
$response->assertForbidden();
});
test('video streaming permitted for bypass', function () {
Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Feature::activate(AllowDumpDownloading::class, fake()->boolean());
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
$action->handle();
});
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
$action->handle();
});
$response = $this->get(route('dump.latest.wiki.show'));
$path = Str::of(DumpWikiAction::FILENAME_PREFIX)
->append(fake()->word())
->append('.sql')
->__toString();
$response->assertForbidden();
}
$file = File::fake()->create($path);
$fsFile = $fs->putFileAs('', $file, $path);
/**
* Users with the bypass feature flag permission shall be permitted to download the latest wiki dump
* even if the Allow Dump Downloading feature is disabled.
*/
public function testVideoStreamingPermittedForBypass(): void
{
Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
Feature::activate(AllowDumpDownloading::class, $this->faker->boolean());
$user = User::factory()->withPermissions(SpecialPermission::BYPASS_FEATURE_FLAGS->value)->createOne();
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
Sanctum::actingAs($user);
$action->handle();
});
$response = get(route('dump.latest.wiki.show'));
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
$response->assertDownload($dump->path);
});
$action->handle();
});
test('not found if no wiki dumps', function () {
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$path = Str::of(DumpWikiAction::FILENAME_PREFIX)
->append($this->faker->word())
->append('.sql')
->__toString();
Feature::activate(AllowDumpDownloading::class);
$file = File::fake()->create($path);
$fsFile = $fs->putFileAs('', $file, $path);
$response = get(route('dump.latest.wiki.show'));
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
$response->assertNotFound();
});
$user = User::factory()->withPermissions(SpecialPermission::BYPASS_FEATURE_FLAGS->value)->createOne();
test('not found if document dumps exist', function () {
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Sanctum::actingAs($user);
Feature::activate(AllowDumpDownloading::class);
$response = $this->get(route('dump.latest.wiki.show'));
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
$response->assertDownload($dump->path);
}
$action->handle();
});
/**
* If no dumps exist, the user shall receive a not found error.
*/
public function testNotFoundIfNoWikiDumps(): void
{
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$response = get(route('dump.latest.wiki.show'));
Feature::activate(AllowDumpDownloading::class);
$response->assertNotFound();
});
$response = $this->get(route('dump.latest.wiki.show'));
test('latest wiki dump downloaded', function () {
Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$response->assertNotFound();
}
Feature::activate(AllowDumpDownloading::class);
/**
* If no wiki dumps exist, the user shall receive a not found error.
*/
public function testNotFoundIfDocumentDumpsExist(): void
{
Storage::fake('local');
Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
Feature::activate(AllowDumpDownloading::class);
$action->handle();
});
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
Collection::times(fake()->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
$action->handle();
});
$action->handle();
});
$response = $this->get(route('dump.latest.wiki.show'));
$path = Str::of(DumpWikiAction::FILENAME_PREFIX)
->append(fake()->word())
->append('.sql')
->__toString();
$response->assertNotFound();
}
$file = File::fake()->create($path);
$fsFile = $fs->putFileAs('', $file, $path);
/**
* If wiki dumps exist, the latest wiki dump is downloaded from storage through the response.
*/
public function testLatestWikiDumpDownloaded(): void
{
Storage::fake('local');
$fs = Storage::fake(Config::get(DumpConstants::DISK_QUALIFIED));
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
Feature::activate(AllowDumpDownloading::class);
$response = get(route('dump.latest.wiki.show'));
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpDocumentAction();
$action->handle();
});
Collection::times($this->faker->randomDigitNotNull(), function () {
$action = new DumpWikiAction();
$action->handle();
});
$path = Str::of(DumpWikiAction::FILENAME_PREFIX)
->append($this->faker->word())
->append('.sql')
->__toString();
$file = File::fake()->create($path);
$fsFile = $fs->putFileAs('', $file, $path);
$dump = Dump::factory()->createOne([
Dump::ATTRIBUTE_PATH => $fsFile,
]);
$response = $this->get(route('dump.latest.wiki.show'));
$response->assertDownload($dump->path);
}
}
$response->assertDownload($dump->path);
});
@@ -2,58 +2,42 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Announcement;
use App\Enums\Auth\CrudPermission;
use App\Models\Admin\Announcement;
use App\Models\Auth\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class AnnouncementDestroyTest extends TestCase
{
/**
* The Announcement Destroy Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$announcement = Announcement::factory()->createOne();
use function Pest\Laravel\delete;
$response = $this->delete(route('api.announcement.destroy', ['announcement' => $announcement]));
test('protected', function () {
$announcement = Announcement::factory()->createOne();
$response->assertUnauthorized();
}
$response = delete(route('api.announcement.destroy', ['announcement' => $announcement]));
/**
* The Announcement Destroy Endpoint shall forbid users without the delete announcement permission.
*/
public function testForbidden(): void
{
$announcement = Announcement::factory()->createOne();
$response->assertUnauthorized();
});
$user = User::factory()->createOne();
test('forbidden', function () {
$announcement = Announcement::factory()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->delete(route('api.announcement.destroy', ['announcement' => $announcement]));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = delete(route('api.announcement.destroy', ['announcement' => $announcement]));
/**
* The Announcement Destroy Endpoint shall delete the announcement.
*/
public function testDeleted(): void
{
$announcement = Announcement::factory()->createOne();
$response->assertForbidden();
});
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(Announcement::class))->createOne();
test('deleted', function () {
$announcement = Announcement::factory()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(Announcement::class))->createOne();
$response = $this->delete(route('api.announcement.destroy', ['announcement' => $announcement]));
Sanctum::actingAs($user);
$response->assertOk();
static::assertModelMissing($announcement);
}
}
$response = delete(route('api.announcement.destroy', ['announcement' => $announcement]));
$response->assertOk();
$this->assertModelMissing($announcement);
});
@@ -2,9 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Announcement;
use App\Concerns\Actions\Http\Api\SortsModels;
use App\Contracts\Http\Api\Field\SortableField;
use App\Enums\Http\Api\Sort\Direction;
use App\Http\Api\Criteria\Paging\Criteria;
@@ -21,230 +18,200 @@ use App\Http\Resources\Admin\Collection\AnnouncementCollection;
use App\Http\Resources\Admin\Resource\AnnouncementResource;
use App\Models\Admin\Announcement;
use App\Models\BaseModel;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Tests\TestCase;
class AnnouncementIndexTest extends TestCase
{
use SortsModels;
use WithFaker;
use function Pest\Laravel\get;
/**
* By default, the Announcement Index Endpoint shall return a collection of Announcement Resources.
*/
public function testDefault(): void
{
$announcements = Announcement::factory()->count($this->faker->randomDigitNotNull())->create();
uses(App\Concerns\Actions\Http\Api\SortsModels::class);
$response = $this->get(route('api.announcement.index'));
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcements, new Query())
->response()
->getData()
),
true
)
);
}
test('default', function () {
$announcements = Announcement::factory()->count(fake()->randomDigitNotNull())->create();
/**
* The Announcement Index Endpoint shall return a collection of public Announcement Resources.
*/
public function testPrivate(): void
{
Announcement::factory()
->private()
->count($this->faker->randomDigitNotNull())
->create();
$response = get(route('api.announcement.index'));
$announcements = Announcement::factory()
->count($this->faker->randomDigitNotNull())
->create();
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcements, new Query())
->response()
->getData()
),
true
)
);
});
$response = $this->get(route('api.announcement.index'));
test('private', function () {
Announcement::factory()
->private()
->count(fake()->randomDigitNotNull())
->create();
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcements, new Query())
->response()
->getData()
),
true
)
);
}
$announcements = Announcement::factory()
->count(fake()->randomDigitNotNull())
->create();
/**
* The Announcement Index Endpoint shall be paginated.
*/
public function testPaginated(): void
{
Announcement::factory()->count($this->faker->randomDigitNotNull())->create();
$response = get(route('api.announcement.index'));
$response = $this->get(route('api.announcement.index'));
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcements, new Query())
->response()
->getData()
),
true
)
);
});
$response->assertJsonStructure([
AnnouncementCollection::$wrap,
'links',
'meta',
]);
}
test('paginated', function () {
Announcement::factory()->count(fake()->randomDigitNotNull())->create();
/**
* The Announcement Index Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new AnnouncementSchema();
$response = get(route('api.announcement.index'));
$fields = collect($schema->fields());
$response->assertJsonStructure([
AnnouncementCollection::$wrap,
'links',
'meta',
]);
});
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
test('sparse fieldsets', function () {
$schema = new AnnouncementSchema();
$parameters = [
FieldParser::param() => [
AnnouncementResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$fields = collect($schema->fields());
$announcements = Announcement::factory()->count($this->faker->randomDigitNotNull())->create();
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$response = $this->get(route('api.announcement.index', $parameters));
$parameters = [
FieldParser::param() => [
AnnouncementResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcements, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$announcements = Announcement::factory()->count(fake()->randomDigitNotNull())->create();
/**
* The Announcement Index Endpoint shall support sorting resources.
*/
public function testSorts(): void
{
$schema = new AnnouncementSchema();
$response = get(route('api.announcement.index', $parameters));
/** @var Sort $sort */
$sort = collect($schema->fields())
->filter(fn (Field $field) => $field instanceof SortableField)
->map(fn (SortableField $field) => $field->getSort())
->random();
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcements, new Query($parameters))
->response()
->getData()
),
true
)
);
});
$parameters = [
SortParser::param() => $sort->format(Arr::random(Direction::cases())),
];
test('sorts', function () {
$schema = new AnnouncementSchema();
$query = new Query($parameters);
/** @var Sort $sort */
$sort = collect($schema->fields())
->filter(fn (Field $field) => $field instanceof SortableField)
->map(fn (SortableField $field) => $field->getSort())
->random();
Announcement::factory()->count($this->faker->randomDigitNotNull())->create();
$parameters = [
SortParser::param() => $sort->format(Arr::random(Direction::cases())),
];
$response = $this->get(route('api.announcement.index', $parameters));
$query = new Query($parameters);
$announcements = $this->sort(Announcement::query(), $query, $schema)->get();
Announcement::factory()->count(fake()->randomDigitNotNull())->create();
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcements, $query)
->response()
->getData()
),
true
)
);
}
$response = get(route('api.announcement.index', $parameters));
/**
* The Announcement Index Endpoint shall support filtering by created_at.
*/
public function testCreatedAtFilter(): void
{
$createdFilter = $this->faker->date();
$excludedDate = $this->faker->date();
$announcements = $this->sort(Announcement::query(), $query, $schema)->get();
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_CREATED_AT => $createdFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcements, $query)
->response()
->getData()
),
true
)
);
});
Carbon::withTestNow($createdFilter, function () {
Announcement::factory()->count($this->faker->randomDigitNotNull())->create();
});
test('created at filter', function () {
$createdFilter = fake()->date();
$excludedDate = fake()->date();
Carbon::withTestNow($excludedDate, function () {
Announcement::factory()->count($this->faker->randomDigitNotNull())->create();
});
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_CREATED_AT => $createdFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$announcement = Announcement::query()->where(BaseModel::ATTRIBUTE_CREATED_AT, $createdFilter)->get();
Carbon::withTestNow($createdFilter, function () {
Announcement::factory()->count(fake()->randomDigitNotNull())->create();
});
$response = $this->get(route('api.announcement.index', $parameters));
Carbon::withTestNow($excludedDate, function () {
Announcement::factory()->count(fake()->randomDigitNotNull())->create();
});
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcement, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$announcement = Announcement::query()->where(BaseModel::ATTRIBUTE_CREATED_AT, $createdFilter)->get();
/**
* The Announcement Index Endpoint shall support filtering by updated_at.
*/
public function testUpdatedAtFilter(): void
{
$updatedFilter = $this->faker->date();
$excludedDate = $this->faker->date();
$response = get(route('api.announcement.index', $parameters));
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_UPDATED_AT => $updatedFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcement, new Query($parameters))
->response()
->getData()
),
true
)
);
});
Carbon::withTestNow($updatedFilter, function () {
Announcement::factory()->count($this->faker->randomDigitNotNull())->create();
});
test('updated at filter', function () {
$updatedFilter = fake()->date();
$excludedDate = fake()->date();
Carbon::withTestNow($excludedDate, function () {
Announcement::factory()->count($this->faker->randomDigitNotNull())->create();
});
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_UPDATED_AT => $updatedFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$announcement = Announcement::query()->where(BaseModel::ATTRIBUTE_UPDATED_AT, $updatedFilter)->get();
Carbon::withTestNow($updatedFilter, function () {
Announcement::factory()->count(fake()->randomDigitNotNull())->create();
});
$response = $this->get(route('api.announcement.index', $parameters));
Carbon::withTestNow($excludedDate, function () {
Announcement::factory()->count(fake()->randomDigitNotNull())->create();
});
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcement, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
$announcement = Announcement::query()->where(BaseModel::ATTRIBUTE_UPDATED_AT, $updatedFilter)->get();
$response = get(route('api.announcement.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new AnnouncementCollection($announcement, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,84 +2,67 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Announcement;
use App\Http\Api\Field\Field;
use App\Http\Api\Parser\FieldParser;
use App\Http\Api\Query\Query;
use App\Http\Api\Schema\Admin\AnnouncementSchema;
use App\Http\Resources\Admin\Resource\AnnouncementResource;
use App\Models\Admin\Announcement;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class AnnouncementShowTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* By default, the Announcement Show Endpoint shall return an Announcement Resource.
*/
public function testDefault(): void
{
$announcement = Announcement::factory()->create();
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response = $this->get(route('api.announcement.show', ['announcement' => $announcement]));
test('default', function () {
$announcement = Announcement::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new AnnouncementResource($announcement, new Query())
->response()
->getData()
),
true
)
);
}
$response = get(route('api.announcement.show', ['announcement' => $announcement]));
/**
* The Announcement Show Endpoint shall forbid access to a private announcement.
*/
public function testCannotViewPrivate(): void
{
$announcement = Announcement::factory()->private()->create();
$response->assertJson(
json_decode(
json_encode(
new AnnouncementResource($announcement, new Query())
->response()
->getData()
),
true
)
);
});
$response = $this->get(route('api.announcement.show', ['announcement' => $announcement]));
test('cannot view private', function () {
$announcement = Announcement::factory()->private()->create();
$response->assertForbidden();
}
$response = get(route('api.announcement.show', ['announcement' => $announcement]));
/**
* The Announcement Show Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new AnnouncementSchema();
$response->assertForbidden();
});
$fields = collect($schema->fields());
test('sparse fieldsets', function () {
$schema = new AnnouncementSchema();
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
$fields = collect($schema->fields());
$parameters = [
FieldParser::param() => [
AnnouncementResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$announcement = Announcement::factory()->create();
$parameters = [
FieldParser::param() => [
AnnouncementResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$response = $this->get(route('api.announcement.show', ['announcement' => $announcement] + $parameters));
$announcement = Announcement::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new AnnouncementResource($announcement, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
$response = get(route('api.announcement.show', ['announcement' => $announcement] + $parameters));
$response->assertJson(
json_decode(
json_encode(
new AnnouncementResource($announcement, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,74 +2,54 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Announcement;
use App\Enums\Auth\CrudPermission;
use App\Models\Admin\Announcement;
use App\Models\Auth\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class AnnouncementStoreTest extends TestCase
{
/**
* The Announcement Store Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$announcement = Announcement::factory()->makeOne();
use function Pest\Laravel\post;
$response = $this->post(route('api.announcement.store', $announcement->toArray()));
test('protected', function () {
$announcement = Announcement::factory()->makeOne();
$response->assertUnauthorized();
}
$response = post(route('api.announcement.store', $announcement->toArray()));
/**
* The Announcement Store Endpoint shall forbid users without the create announcement permission.
*/
public function testForbidden(): void
{
$announcement = Announcement::factory()->makeOne();
$response->assertUnauthorized();
});
$user = User::factory()->createOne();
test('forbidden', function () {
$announcement = Announcement::factory()->makeOne();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->post(route('api.announcement.store', $announcement->toArray()));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = post(route('api.announcement.store', $announcement->toArray()));
/**
* The Announcement Store Endpoint shall require the content field.
*/
public function testRequiredFields(): void
{
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(Announcement::class))->createOne();
$response->assertForbidden();
});
Sanctum::actingAs($user);
test('required fields', function () {
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(Announcement::class))->createOne();
$response = $this->post(route('api.announcement.store'));
Sanctum::actingAs($user);
$response->assertJsonValidationErrors([
Announcement::ATTRIBUTE_CONTENT,
]);
}
$response = post(route('api.announcement.store'));
/**
* The Announcement Store Endpoint shall create an announcement.
*/
public function testCreate(): void
{
$parameters = Announcement::factory()->raw();
$response->assertJsonValidationErrors([
Announcement::ATTRIBUTE_CONTENT,
]);
});
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(Announcement::class))->createOne();
test('create', function () {
$parameters = Announcement::factory()->raw();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(Announcement::class))->createOne();
$response = $this->post(route('api.announcement.store', $parameters));
Sanctum::actingAs($user);
$response->assertCreated();
static::assertDatabaseCount(Announcement::class, 1);
}
}
$response = post(route('api.announcement.store', $parameters));
$response->assertCreated();
$this->assertDatabaseCount(Announcement::class, 1);
});
@@ -2,63 +2,47 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Announcement;
use App\Enums\Auth\CrudPermission;
use App\Models\Admin\Announcement;
use App\Models\Auth\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class AnnouncementUpdateTest extends TestCase
{
/**
* The Announcement Update Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$announcement = Announcement::factory()->createOne();
use function Pest\Laravel\put;
$parameters = Announcement::factory()->raw();
test('protected', function () {
$announcement = Announcement::factory()->createOne();
$response = $this->put(route('api.announcement.update', ['announcement' => $announcement] + $parameters));
$parameters = Announcement::factory()->raw();
$response->assertUnauthorized();
}
$response = put(route('api.announcement.update', ['announcement' => $announcement] + $parameters));
/**
* The Announcement Update Endpoint shall forbid users without the update announcement permission.
*/
public function testForbidden(): void
{
$announcement = Announcement::factory()->createOne();
$response->assertUnauthorized();
});
$parameters = Announcement::factory()->raw();
test('forbidden', function () {
$announcement = Announcement::factory()->createOne();
$user = User::factory()->createOne();
$parameters = Announcement::factory()->raw();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->put(route('api.announcement.update', ['announcement' => $announcement] + $parameters));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = put(route('api.announcement.update', ['announcement' => $announcement] + $parameters));
/**
* The Announcement Update Endpoint shall update an announcement.
*/
public function testUpdate(): void
{
$announcement = Announcement::factory()->createOne();
$response->assertForbidden();
});
$parameters = Announcement::factory()->raw();
test('update', function () {
$announcement = Announcement::factory()->createOne();
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(Announcement::class))->createOne();
$parameters = Announcement::factory()->raw();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(Announcement::class))->createOne();
$response = $this->put(route('api.announcement.update', ['announcement' => $announcement] + $parameters));
Sanctum::actingAs($user);
$response->assertOk();
}
}
$response = put(route('api.announcement.update', ['announcement' => $announcement] + $parameters));
$response->assertOk();
});
@@ -2,58 +2,42 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Dump;
use App\Enums\Auth\CrudPermission;
use App\Models\Admin\Dump;
use App\Models\Auth\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class DumpDestroyTest extends TestCase
{
/**
* The Dump Destroy Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$dump = Dump::factory()->createOne();
use function Pest\Laravel\delete;
$response = $this->delete(route('api.dump.destroy', ['dump' => $dump]));
test('protected', function () {
$dump = Dump::factory()->createOne();
$response->assertUnauthorized();
}
$response = delete(route('api.dump.destroy', ['dump' => $dump]));
/**
* The Dump Destroy Endpoint shall forbid users without the delete dump permission.
*/
public function testForbidden(): void
{
$dump = Dump::factory()->createOne();
$response->assertUnauthorized();
});
$user = User::factory()->createOne();
test('forbidden', function () {
$dump = Dump::factory()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->delete(route('api.dump.destroy', ['dump' => $dump]));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = delete(route('api.dump.destroy', ['dump' => $dump]));
/**
* The Dump Destroy Endpoint shall delete the dump.
*/
public function testDeleted(): void
{
$dump = Dump::factory()->createOne();
$response->assertForbidden();
});
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(Dump::class))->createOne();
test('deleted', function () {
$dump = Dump::factory()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(Dump::class))->createOne();
$response = $this->delete(route('api.dump.destroy', ['dump' => $dump]));
Sanctum::actingAs($user);
$response->assertOk();
static::assertModelMissing($dump);
}
}
$response = delete(route('api.dump.destroy', ['dump' => $dump]));
$response->assertOk();
$this->assertModelMissing($dump);
});
@@ -2,9 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Dump;
use App\Concerns\Actions\Http\Api\SortsModels;
use App\Contracts\Http\Api\Field\SortableField;
use App\Enums\Http\Api\Sort\Direction;
use App\Http\Api\Criteria\Paging\Criteria;
@@ -21,230 +18,200 @@ use App\Http\Resources\Admin\Collection\DumpCollection;
use App\Http\Resources\Admin\Resource\DumpResource;
use App\Models\Admin\Dump;
use App\Models\BaseModel;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Tests\TestCase;
class DumpIndexTest extends TestCase
{
use SortsModels;
use WithFaker;
use function Pest\Laravel\get;
/**
* By default, the Dump Index Endpoint shall return a collection of Dump Resources.
*/
public function testDefault(): void
{
$dumps = Dump::factory()->count($this->faker->randomDigitNotNull())->create();
uses(App\Concerns\Actions\Http\Api\SortsModels::class);
$response = $this->get(route('api.dump.index'));
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dumps, new Query())
->response()
->getData()
),
true
)
);
}
test('default', function () {
$dumps = Dump::factory()->count(fake()->randomDigitNotNull())->create();
/**
* The Dump Index Endpoint shall return a collection of safe Dump Resources.
*/
public function testUnsafe(): void
{
Dump::factory()
->unsafe()
->count($this->faker->randomDigitNotNull())
->create();
$response = get(route('api.dump.index'));
$dumps = Dump::factory()
->count($this->faker->randomDigitNotNull())
->create();
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dumps, new Query())
->response()
->getData()
),
true
)
);
});
$response = $this->get(route('api.dump.index'));
test('unsafe', function () {
Dump::factory()
->unsafe()
->count(fake()->randomDigitNotNull())
->create();
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dumps, new Query())
->response()
->getData()
),
true
)
);
}
$dumps = Dump::factory()
->count(fake()->randomDigitNotNull())
->create();
/**
* The Dump Index Endpoint shall be paginated.
*/
public function testPaginated(): void
{
Dump::factory()->count($this->faker->randomDigitNotNull())->create();
$response = get(route('api.dump.index'));
$response = $this->get(route('api.dump.index'));
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dumps, new Query())
->response()
->getData()
),
true
)
);
});
$response->assertJsonStructure([
DumpCollection::$wrap,
'links',
'meta',
]);
}
test('paginated', function () {
Dump::factory()->count(fake()->randomDigitNotNull())->create();
/**
* The Dump Index Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new DumpSchema();
$response = get(route('api.dump.index'));
$fields = collect($schema->fields());
$response->assertJsonStructure([
DumpCollection::$wrap,
'links',
'meta',
]);
});
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
test('sparse fieldsets', function () {
$schema = new DumpSchema();
$parameters = [
FieldParser::param() => [
DumpResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$fields = collect($schema->fields());
$dumps = Dump::factory()->count($this->faker->randomDigitNotNull())->create();
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$response = $this->get(route('api.dump.index', $parameters));
$parameters = [
FieldParser::param() => [
DumpResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dumps, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$dumps = Dump::factory()->count(fake()->randomDigitNotNull())->create();
/**
* The Dump Index Endpoint shall support sorting resources.
*/
public function testSorts(): void
{
$schema = new DumpSchema();
$response = get(route('api.dump.index', $parameters));
/** @var Sort $sort */
$sort = collect($schema->fields())
->filter(fn (Field $field) => $field instanceof SortableField)
->map(fn (SortableField $field) => $field->getSort())
->random();
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dumps, new Query($parameters))
->response()
->getData()
),
true
)
);
});
$parameters = [
SortParser::param() => $sort->format(Arr::random(Direction::cases())),
];
test('sorts', function () {
$schema = new DumpSchema();
$query = new Query($parameters);
/** @var Sort $sort */
$sort = collect($schema->fields())
->filter(fn (Field $field) => $field instanceof SortableField)
->map(fn (SortableField $field) => $field->getSort())
->random();
Dump::factory()->count($this->faker->randomDigitNotNull())->create();
$parameters = [
SortParser::param() => $sort->format(Arr::random(Direction::cases())),
];
$response = $this->get(route('api.dump.index', $parameters));
$query = new Query($parameters);
$dumps = $this->sort(Dump::query(), $query, $schema)->get();
Dump::factory()->count(fake()->randomDigitNotNull())->create();
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dumps, $query)
->response()
->getData()
),
true
)
);
}
$response = get(route('api.dump.index', $parameters));
/**
* The Dump Index Endpoint shall support filtering by created_at.
*/
public function testCreatedAtFilter(): void
{
$createdFilter = $this->faker->date();
$excludedDate = $this->faker->date();
$dumps = $this->sort(Dump::query(), $query, $schema)->get();
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_CREATED_AT => $createdFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dumps, $query)
->response()
->getData()
),
true
)
);
});
Carbon::withTestNow($createdFilter, function () {
Dump::factory()->count($this->faker->randomDigitNotNull())->create();
});
test('created at filter', function () {
$createdFilter = fake()->date();
$excludedDate = fake()->date();
Carbon::withTestNow($excludedDate, function () {
Dump::factory()->count($this->faker->randomDigitNotNull())->create();
});
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_CREATED_AT => $createdFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$dump = Dump::query()->where(BaseModel::ATTRIBUTE_CREATED_AT, $createdFilter)->get();
Carbon::withTestNow($createdFilter, function () {
Dump::factory()->count(fake()->randomDigitNotNull())->create();
});
$response = $this->get(route('api.dump.index', $parameters));
Carbon::withTestNow($excludedDate, function () {
Dump::factory()->count(fake()->randomDigitNotNull())->create();
});
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dump, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$dump = Dump::query()->where(BaseModel::ATTRIBUTE_CREATED_AT, $createdFilter)->get();
/**
* The Dump Index Endpoint shall support filtering by updated_at.
*/
public function testUpdatedAtFilter(): void
{
$updatedFilter = $this->faker->date();
$excludedDate = $this->faker->date();
$response = get(route('api.dump.index', $parameters));
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_UPDATED_AT => $updatedFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dump, new Query($parameters))
->response()
->getData()
),
true
)
);
});
Carbon::withTestNow($updatedFilter, function () {
Dump::factory()->count($this->faker->randomDigitNotNull())->create();
});
test('updated at filter', function () {
$updatedFilter = fake()->date();
$excludedDate = fake()->date();
Carbon::withTestNow($excludedDate, function () {
Dump::factory()->count($this->faker->randomDigitNotNull())->create();
});
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_UPDATED_AT => $updatedFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$dump = Dump::query()->where(BaseModel::ATTRIBUTE_UPDATED_AT, $updatedFilter)->get();
Carbon::withTestNow($updatedFilter, function () {
Dump::factory()->count(fake()->randomDigitNotNull())->create();
});
$response = $this->get(route('api.dump.index', $parameters));
Carbon::withTestNow($excludedDate, function () {
Dump::factory()->count(fake()->randomDigitNotNull())->create();
});
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dump, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
$dump = Dump::query()->where(BaseModel::ATTRIBUTE_UPDATED_AT, $updatedFilter)->get();
$response = get(route('api.dump.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new DumpCollection($dump, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,84 +2,67 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Dump;
use App\Http\Api\Field\Field;
use App\Http\Api\Parser\FieldParser;
use App\Http\Api\Query\Query;
use App\Http\Api\Schema\Admin\DumpSchema;
use App\Http\Resources\Admin\Resource\DumpResource;
use App\Models\Admin\Dump;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class DumpShowTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* By default, the Dump Show Endpoint shall return a Dump Resource.
*/
public function testDefault(): void
{
$dump = Dump::factory()->create();
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response = $this->get(route('api.dump.show', ['dump' => $dump]));
test('default', function () {
$dump = Dump::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new DumpResource($dump, new Query())
->response()
->getData()
),
true
)
);
}
$response = get(route('api.dump.show', ['dump' => $dump]));
/**
* The Dump Show Endpoint shall forbid access to an unsafe dump.
*/
public function testCannotViewUnsafe(): void
{
$dump = Dump::factory()->unsafe()->create();
$response->assertJson(
json_decode(
json_encode(
new DumpResource($dump, new Query())
->response()
->getData()
),
true
)
);
});
$response = $this->get(route('api.dump.show', ['dump' => $dump]));
test('cannot view unsafe', function () {
$dump = Dump::factory()->unsafe()->create();
$response->assertForbidden();
}
$response = get(route('api.dump.show', ['dump' => $dump]));
/**
* The Dump Show Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new DumpSchema();
$response->assertForbidden();
});
$fields = collect($schema->fields());
test('sparse fieldsets', function () {
$schema = new DumpSchema();
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
$fields = collect($schema->fields());
$parameters = [
FieldParser::param() => [
DumpResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$dump = Dump::factory()->create();
$parameters = [
FieldParser::param() => [
DumpResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$response = $this->get(route('api.dump.show', ['dump' => $dump] + $parameters));
$dump = Dump::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new DumpResource($dump, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
$response = get(route('api.dump.show', ['dump' => $dump] + $parameters));
$response->assertJson(
json_decode(
json_encode(
new DumpResource($dump, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,74 +2,54 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Dump;
use App\Enums\Auth\CrudPermission;
use App\Models\Admin\Dump;
use App\Models\Auth\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class DumpStoreTest extends TestCase
{
/**
* The Dump Store Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$dump = Dump::factory()->makeOne();
use function Pest\Laravel\post;
$response = $this->post(route('api.dump.store', $dump->toArray()));
test('protected', function () {
$dump = Dump::factory()->makeOne();
$response->assertUnauthorized();
}
$response = post(route('api.dump.store', $dump->toArray()));
/**
* The Dump Store Endpoint shall forbid users without the create dump permission.
*/
public function testForbidden(): void
{
$dump = Dump::factory()->makeOne();
$response->assertUnauthorized();
});
$user = User::factory()->createOne();
test('forbidden', function () {
$dump = Dump::factory()->makeOne();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->post(route('api.dump.store', $dump->toArray()));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = post(route('api.dump.store', $dump->toArray()));
/**
* The Dump Store Endpoint shall require the path field.
*/
public function testRequiredFields(): void
{
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(Dump::class))->createOne();
$response->assertForbidden();
});
Sanctum::actingAs($user);
test('required fields', function () {
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(Dump::class))->createOne();
$response = $this->post(route('api.dump.store'));
Sanctum::actingAs($user);
$response->assertJsonValidationErrors([
Dump::ATTRIBUTE_PATH,
]);
}
$response = post(route('api.dump.store'));
/**
* The Dump Store Endpoint shall create a dump.
*/
public function testCreate(): void
{
$parameters = Dump::factory()->raw();
$response->assertJsonValidationErrors([
Dump::ATTRIBUTE_PATH,
]);
});
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(Dump::class))->createOne();
test('create', function () {
$parameters = Dump::factory()->raw();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(Dump::class))->createOne();
$response = $this->post(route('api.dump.store', $parameters));
Sanctum::actingAs($user);
$response->assertCreated();
static::assertDatabaseCount(Dump::class, 1);
}
}
$response = post(route('api.dump.store', $parameters));
$response->assertCreated();
$this->assertDatabaseCount(Dump::class, 1);
});
@@ -2,63 +2,47 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Dump;
use App\Enums\Auth\CrudPermission;
use App\Models\Admin\Dump;
use App\Models\Auth\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class DumpUpdateTest extends TestCase
{
/**
* The Dump Update Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$dump = Dump::factory()->createOne();
use function Pest\Laravel\put;
$parameters = Dump::factory()->raw();
test('protected', function () {
$dump = Dump::factory()->createOne();
$response = $this->put(route('api.dump.update', ['dump' => $dump] + $parameters));
$parameters = Dump::factory()->raw();
$response->assertUnauthorized();
}
$response = put(route('api.dump.update', ['dump' => $dump] + $parameters));
/**
* The Dump Update Endpoint shall forbid users without the update dump permission.
*/
public function testForbidden(): void
{
$dump = Dump::factory()->createOne();
$response->assertUnauthorized();
});
$parameters = Dump::factory()->raw();
test('forbidden', function () {
$dump = Dump::factory()->createOne();
$user = User::factory()->createOne();
$parameters = Dump::factory()->raw();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->put(route('api.dump.update', ['dump' => $dump] + $parameters));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = put(route('api.dump.update', ['dump' => $dump] + $parameters));
/**
* The Dump Update Endpoint shall update a dump.
*/
public function testUpdate(): void
{
$dump = Dump::factory()->createOne();
$response->assertForbidden();
});
$parameters = Dump::factory()->raw();
test('update', function () {
$dump = Dump::factory()->createOne();
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(Dump::class))->createOne();
$parameters = Dump::factory()->raw();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(Dump::class))->createOne();
$response = $this->put(route('api.dump.update', ['dump' => $dump] + $parameters));
Sanctum::actingAs($user);
$response->assertOk();
}
}
$response = put(route('api.dump.update', ['dump' => $dump] + $parameters));
$response->assertOk();
});
@@ -2,9 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Feature;
use App\Concerns\Actions\Http\Api\SortsModels;
use App\Contracts\Http\Api\Field\SortableField;
use App\Enums\Http\Api\Sort\Direction;
use App\Http\Api\Criteria\Paging\Criteria;
@@ -21,236 +18,206 @@ use App\Http\Resources\Admin\Collection\FeatureCollection;
use App\Http\Resources\Admin\Resource\FeatureResource;
use App\Models\Admin\Feature;
use App\Models\BaseModel;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Tests\TestCase;
class FeatureIndexTest extends TestCase
{
use SortsModels;
use WithFaker;
use function Pest\Laravel\get;
/**
* By default, the Feature Index Endpoint shall return a collection of Feature Resources.
*/
public function testDefault(): void
{
$features = Feature::factory()->count($this->faker->randomDigitNotNull())->create();
uses(App\Concerns\Actions\Http\Api\SortsModels::class);
$response = $this->get(route('api.feature.index'));
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($features, new Query())
->response()
->getData()
),
true
)
);
}
test('default', function () {
$features = Feature::factory()->count(fake()->randomDigitNotNull())->create();
/**
* The Feature Show Endpoint shall list features of nonnull scope.
*/
public function testNonNullForbidden(): void
{
$nullScopeCount = $this->faker->randomDigitNotNull();
$response = get(route('api.feature.index'));
$features = Feature::factory()
->count($nullScopeCount)
->create();
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($features, new Query())
->response()
->getData()
),
true
)
);
});
Collection::times($this->faker->randomDigitNotNull(), function () {
Feature::factory()->create([
Feature::ATTRIBUTE_SCOPE => $this->faker->word(),
]);
});
test('non null forbidden', function () {
$nullScopeCount = fake()->randomDigitNotNull();
$response = $this->get(route('api.feature.index'));
$features = Feature::factory()
->count($nullScopeCount)
->create();
$response->assertJsonCount($nullScopeCount, FeatureCollection::$wrap);
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($features, new Query())
->response()
->getData()
),
true
)
);
}
/**
* The Feature Index Endpoint shall be paginated.
*/
public function testPaginated(): void
{
Feature::factory()->count($this->faker->randomDigitNotNull())->create();
$response = $this->get(route('api.feature.index'));
$response->assertJsonStructure([
FeatureCollection::$wrap,
'links',
'meta',
Collection::times(fake()->randomDigitNotNull(), function () {
Feature::factory()->create([
Feature::ATTRIBUTE_SCOPE => fake()->word(),
]);
}
});
/**
* The Feature Index Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new FeatureSchema();
$response = get(route('api.feature.index'));
$fields = collect($schema->fields());
$response->assertJsonCount($nullScopeCount, FeatureCollection::$wrap);
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($features, new Query())
->response()
->getData()
),
true
)
);
});
$parameters = [
FieldParser::param() => [
FeatureResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
test('paginated', function () {
Feature::factory()->count(fake()->randomDigitNotNull())->create();
$features = Feature::factory()->count($this->faker->randomDigitNotNull())->create();
$response = get(route('api.feature.index'));
$response = $this->get(route('api.feature.index', $parameters));
$response->assertJsonStructure([
FeatureCollection::$wrap,
'links',
'meta',
]);
});
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($features, new Query($parameters))
->response()
->getData()
),
true
)
);
}
test('sparse fieldsets', function () {
$schema = new FeatureSchema();
/**
* The Feature Index Endpoint shall support sorting resources.
*/
public function testSorts(): void
{
$schema = new FeatureSchema();
$fields = collect($schema->fields());
/** @var Sort $sort */
$sort = collect($schema->fields())
->filter(fn (Field $field) => $field instanceof SortableField)
->map(fn (SortableField $field) => $field->getSort())
->random();
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$parameters = [
SortParser::param() => $sort->format(Arr::random(Direction::cases())),
];
$parameters = [
FieldParser::param() => [
FeatureResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$query = new Query($parameters);
$features = Feature::factory()->count(fake()->randomDigitNotNull())->create();
Feature::factory()->count($this->faker->randomDigitNotNull())->create();
$response = get(route('api.feature.index', $parameters));
$response = $this->get(route('api.feature.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($features, new Query($parameters))
->response()
->getData()
),
true
)
);
});
$features = $this->sort(Feature::query(), $query, $schema)->get();
test('sorts', function () {
$schema = new FeatureSchema();
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($features, $query)
->response()
->getData()
),
true
)
);
}
/** @var Sort $sort */
$sort = collect($schema->fields())
->filter(fn (Field $field) => $field instanceof SortableField)
->map(fn (SortableField $field) => $field->getSort())
->random();
/**
* The Feature Index Endpoint shall support filtering by created_at.
*/
public function testCreatedAtFilter(): void
{
$createdFilter = $this->faker->date();
$excludedDate = $this->faker->date();
$parameters = [
SortParser::param() => $sort->format(Arr::random(Direction::cases())),
];
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_CREATED_AT => $createdFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$query = new Query($parameters);
Carbon::withTestNow($createdFilter, function () {
Feature::factory()->count($this->faker->randomDigitNotNull())->create();
});
Feature::factory()->count(fake()->randomDigitNotNull())->create();
Carbon::withTestNow($excludedDate, function () {
Feature::factory()->count($this->faker->randomDigitNotNull())->create();
});
$response = get(route('api.feature.index', $parameters));
$feature = Feature::query()->where(BaseModel::ATTRIBUTE_CREATED_AT, $createdFilter)->get();
$features = $this->sort(Feature::query(), $query, $schema)->get();
$response = $this->get(route('api.feature.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($features, $query)
->response()
->getData()
),
true
)
);
});
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($feature, new Query($parameters))
->response()
->getData()
),
true
)
);
}
test('created at filter', function () {
$createdFilter = fake()->date();
$excludedDate = fake()->date();
/**
* The Feature Index Endpoint shall support filtering by updated_at.
*/
public function testUpdatedAtFilter(): void
{
$updatedFilter = $this->faker->date();
$excludedDate = $this->faker->date();
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_CREATED_AT => $createdFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_UPDATED_AT => $updatedFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
Carbon::withTestNow($createdFilter, function () {
Feature::factory()->count(fake()->randomDigitNotNull())->create();
});
Carbon::withTestNow($updatedFilter, function () {
Feature::factory()->count($this->faker->randomDigitNotNull())->create();
});
Carbon::withTestNow($excludedDate, function () {
Feature::factory()->count(fake()->randomDigitNotNull())->create();
});
Carbon::withTestNow($excludedDate, function () {
Feature::factory()->count($this->faker->randomDigitNotNull())->create();
});
$feature = Feature::query()->where(BaseModel::ATTRIBUTE_CREATED_AT, $createdFilter)->get();
$feature = Feature::query()->where(BaseModel::ATTRIBUTE_UPDATED_AT, $updatedFilter)->get();
$response = get(route('api.feature.index', $parameters));
$response = $this->get(route('api.feature.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($feature, new Query($parameters))
->response()
->getData()
),
true
)
);
});
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($feature, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
test('updated at filter', function () {
$updatedFilter = fake()->date();
$excludedDate = fake()->date();
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_UPDATED_AT => $updatedFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
Carbon::withTestNow($updatedFilter, function () {
Feature::factory()->count(fake()->randomDigitNotNull())->create();
});
Carbon::withTestNow($excludedDate, function () {
Feature::factory()->count(fake()->randomDigitNotNull())->create();
});
$feature = Feature::query()->where(BaseModel::ATTRIBUTE_UPDATED_AT, $updatedFilter)->get();
$response = get(route('api.feature.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeatureCollection($feature, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,86 +2,69 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Feature;
use App\Http\Api\Field\Field;
use App\Http\Api\Parser\FieldParser;
use App\Http\Api\Query\Query;
use App\Http\Api\Schema\Admin\FeatureSchema;
use App\Http\Resources\Admin\Resource\FeatureResource;
use App\Models\Admin\Feature;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class FeatureShowTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* By default, the Feature Show Endpoint shall return a Feature Resource.
*/
public function testDefault(): void
{
$feature = Feature::factory()->create();
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response = $this->get(route('api.feature.show', ['feature' => $feature]));
test('default', function () {
$feature = Feature::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new FeatureResource($feature, new Query())
->response()
->getData()
),
true
)
);
}
$response = get(route('api.feature.show', ['feature' => $feature]));
/**
* The Feature Show Endpoint shall forbid showing features of nonnull scope.
*/
public function testNonNullForbidden(): void
{
$feature = Feature::factory()->create([
Feature::ATTRIBUTE_SCOPE => $this->faker->word(),
]);
$response->assertJson(
json_decode(
json_encode(
new FeatureResource($feature, new Query())
->response()
->getData()
),
true
)
);
});
$response = $this->get(route('api.feature.show', ['feature' => $feature]));
test('non null forbidden', function () {
$feature = Feature::factory()->create([
Feature::ATTRIBUTE_SCOPE => fake()->word(),
]);
$response->assertForbidden();
}
$response = get(route('api.feature.show', ['feature' => $feature]));
/**
* The Feature Show Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new FeatureSchema();
$response->assertForbidden();
});
$fields = collect($schema->fields());
test('sparse fieldsets', function () {
$schema = new FeatureSchema();
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
$fields = collect($schema->fields());
$parameters = [
FieldParser::param() => [
FeatureResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$feature = Feature::factory()->create();
$parameters = [
FieldParser::param() => [
FeatureResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$response = $this->get(route('api.feature.show', ['feature' => $feature] + $parameters));
$feature = Feature::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new FeatureResource($feature, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
$response = get(route('api.feature.show', ['feature' => $feature] + $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeatureResource($feature, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,69 +2,53 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\Feature;
use App\Enums\Auth\CrudPermission;
use App\Models\Admin\Feature;
use App\Models\Auth\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class FeatureUpdateTest extends TestCase
{
/**
* The Feature Update Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$feature = Feature::factory()->createOne();
use function Pest\Laravel\put;
$parameters = [
Feature::ATTRIBUTE_VALUE => ! $feature->value,
];
test('protected', function () {
$feature = Feature::factory()->createOne();
$response = $this->put(route('api.feature.update', ['feature' => $feature] + $parameters));
$parameters = [
Feature::ATTRIBUTE_VALUE => ! $feature->value,
];
$response->assertUnauthorized();
}
$response = put(route('api.feature.update', ['feature' => $feature] + $parameters));
/**
* The Feature Update Endpoint shall forbid users without the update feature permission.
*/
public function testForbidden(): void
{
$feature = Feature::factory()->createOne();
$response->assertUnauthorized();
});
$parameters = [
Feature::ATTRIBUTE_VALUE => ! $feature->value,
];
test('forbidden', function () {
$feature = Feature::factory()->createOne();
$user = User::factory()->createOne();
$parameters = [
Feature::ATTRIBUTE_VALUE => ! $feature->value,
];
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->put(route('api.feature.update', ['feature' => $feature] + $parameters));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = put(route('api.feature.update', ['feature' => $feature] + $parameters));
/**
* The Feature Update Endpoint shall update a feature.
*/
public function testUpdate(): void
{
$feature = Feature::factory()->createOne();
$response->assertForbidden();
});
$parameters = [
Feature::ATTRIBUTE_VALUE => ! $feature->value,
];
test('update', function () {
$feature = Feature::factory()->createOne();
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(Feature::class))->createOne();
$parameters = [
Feature::ATTRIBUTE_VALUE => ! $feature->value,
];
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(Feature::class))->createOne();
$response = $this->put(route('api.feature.update', ['feature' => $feature] + $parameters));
Sanctum::actingAs($user);
$response->assertOk();
}
}
$response = put(route('api.feature.update', ['feature' => $feature] + $parameters));
$response->assertOk();
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\FeaturedTheme;
use App\Http\Api\Field\Field;
use App\Http\Api\Include\AllowedInclude;
use App\Http\Api\Parser\FieldParser;
@@ -20,199 +18,164 @@ use App\Models\Wiki\Artist;
use App\Models\Wiki\Image;
use App\Models\Wiki\Song;
use App\Models\Wiki\Video;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Collection;
use Tests\TestCase;
class CurrentFeaturedThemeShowTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* The Current Featured Theme Show Endpoint shall return a Not Found exception if there are no featured themes.
*/
public function testNotFoundIfNoFeaturedThemes(): void
{
$response = $this->get(route('api.featuredtheme.current.show'));
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response->assertNotFound();
}
test('not found if no featured themes', function () {
$response = get(route('api.featuredtheme.current.show'));
/**
* The Current Featured Theme Show Endpoint shall return a Not Found exception if the featured theme has no start date.
*/
public function testNotFoundIfThemeStartAtNull(): void
{
$response->assertNotFound();
});
test('not found if theme start at null', function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => null,
]);
$response = get(route('api.featuredtheme.current.show'));
$response->assertNotFound();
});
test('not found if theme end at null', function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_END_AT => null,
]);
$response = get(route('api.featuredtheme.current.show'));
$response->assertNotFound();
});
test('not found if theme start at after now', function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => fake()->dateTimeBetween('+1 day', '+1 year'),
]);
$response = get(route('api.featuredtheme.current.show'));
$response->assertNotFound();
});
test('not found if theme end at before now', function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_END_AT => fake()->dateTimeBetween(),
]);
$response = get(route('api.featuredtheme.current.show'));
$response->assertNotFound();
});
test('default', function () {
Collection::times(fake()->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => null,
]);
});
$response = $this->get(route('api.featuredtheme.current.show'));
$response->assertNotFound();
}
/**
* The Current Featured Theme Show Endpoint shall return a Not Found exception if the featured theme has no end date.
*/
public function testNotFoundIfThemeEndAtNull(): void
{
Collection::times(fake()->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_END_AT => null,
]);
});
$response = $this->get(route('api.featuredtheme.current.show'));
$response->assertNotFound();
}
/**
* The Current Featured Theme Show Endpoint shall return a Not Found exception if the featured theme starts after today.
*/
public function testNotFoundIfThemeStartAtAfterNow(): void
{
Collection::times(fake()->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => $this->faker->dateTimeBetween('+1 day', '+1 year'),
FeaturedTheme::ATTRIBUTE_START_AT => fake()->dateTimeBetween('+1 day', '+1 year'),
]);
});
$response = $this->get(route('api.featuredtheme.current.show'));
$response->assertNotFound();
}
/**
* The Current Featured Theme Show Endpoint shall return a Not Found exception if the featured theme ends before today.
*/
public function testNotFoundIfThemeEndAtBeforeNow(): void
{
Collection::times(fake()->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_END_AT => $this->faker->dateTimeBetween(),
FeaturedTheme::ATTRIBUTE_END_AT => fake()->dateTimeBetween('-1 year', '-1 day'),
]);
});
$response = $this->get(route('api.featuredtheme.current.show'));
$currentTheme = FeaturedTheme::factory()->create();
$response->assertNotFound();
}
$response = get(route('api.featuredtheme.current.show'));
/**
* By default, the Current Featured Theme Show Endpoint shall return a Featured Theme Resource.
*/
public function testDefault(): void
{
Collection::times($this->faker->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => null,
]);
});
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($currentTheme, new Query())
->response()
->getData()
),
true
)
);
});
Collection::times($this->faker->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_END_AT => null,
]);
});
test('allowed include paths', function () {
$schema = new FeaturedThemeSchema();
Collection::times($this->faker->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => $this->faker->dateTimeBetween('+1 day', '+1 year'),
]);
});
$allowedIncludes = collect($schema->allowedIncludes());
Collection::times($this->faker->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_END_AT => $this->faker->dateTimeBetween('-1 year', '-1 day'),
]);
});
$selectedIncludes = $allowedIncludes->random(fake()->numberBetween(1, $allowedIncludes->count()));
$currentTheme = FeaturedTheme::factory()->create();
$includedPaths = $selectedIncludes->map(fn (AllowedInclude $include) => $include->path());
$response = $this->get(route('api.featuredtheme.current.show'));
$parameters = [
IncludeParser::param() => $includedPaths->join(','),
];
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($currentTheme, new Query())
->response()
->getData()
),
true
)
);
}
$currentTheme = FeaturedTheme::factory()
->for(
AnimeThemeEntry::factory()
->for(
AnimeTheme::factory()
->for(Anime::factory()->has(Image::factory()->count(fake()->randomDigitNotNull())))
->for(Song::factory()->has(Artist::factory()->count(fake()->randomDigitNotNull())))
)
)
->for(Video::factory())
->for(User::factory())
->createOne();
/**
* The Featured Theme Show Endpoint shall allow inclusion of related resources.
*/
public function testAllowedIncludePaths(): void
{
$schema = new FeaturedThemeSchema();
$response = get(route('api.featuredtheme.current.show', $parameters));
$allowedIncludes = collect($schema->allowedIncludes());
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($currentTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
});
$selectedIncludes = $allowedIncludes->random($this->faker->numberBetween(1, $allowedIncludes->count()));
test('sparse fieldsets', function () {
$schema = new FeaturedThemeSchema();
$includedPaths = $selectedIncludes->map(fn (AllowedInclude $include) => $include->path());
$fields = collect($schema->fields());
$parameters = [
IncludeParser::param() => $includedPaths->join(','),
];
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$currentTheme = FeaturedTheme::factory()
->for(
AnimeThemeEntry::factory()
->for(
AnimeTheme::factory()
->for(Anime::factory()->has(Image::factory()->count($this->faker->randomDigitNotNull())))
->for(Song::factory()->has(Artist::factory()->count($this->faker->randomDigitNotNull())))
)
)
->for(Video::factory())
->for(User::factory())
->createOne();
$parameters = [
FieldParser::param() => [
FeaturedThemeResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$response = $this->get(route('api.featuredtheme.current.show', $parameters));
$currentTheme = FeaturedTheme::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($currentTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$response = get(route('api.featuredtheme.current.show', $parameters));
/**
* The Current Featured Theme Show Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new FeaturedThemeSchema();
$fields = collect($schema->fields());
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
$parameters = [
FieldParser::param() => [
FeaturedThemeResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$currentTheme = FeaturedTheme::factory()->create();
$response = $this->get(route('api.featuredtheme.current.show', $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($currentTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($currentTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,58 +2,42 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\FeaturedTheme;
use App\Enums\Auth\CrudPermission;
use App\Models\Admin\FeaturedTheme;
use App\Models\Auth\User;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class FeaturedThemeDestroyTest extends TestCase
{
/**
* The Featured Theme Destroy Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
use function Pest\Laravel\delete;
$response = $this->delete(route('api.featuredtheme.destroy', ['featuredtheme' => $featuredTheme]));
test('protected', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
$response->assertUnauthorized();
}
$response = delete(route('api.featuredtheme.destroy', ['featuredtheme' => $featuredTheme]));
/**
* The Featured Theme Destroy Endpoint shall forbid users without the delete featured theme permission.
*/
public function testForbidden(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
$response->assertUnauthorized();
});
$user = User::factory()->createOne();
test('forbidden', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->delete(route('api.featuredtheme.destroy', ['featuredtheme' => $featuredTheme]));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = delete(route('api.featuredtheme.destroy', ['featuredtheme' => $featuredTheme]));
/**
* The FeaturedTheme Destroy Endpoint shall delete the featured theme.
*/
public function testDeleted(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
$response->assertForbidden();
});
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(FeaturedTheme::class))->createOne();
test('deleted', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(FeaturedTheme::class))->createOne();
$response = $this->delete(route('api.featuredtheme.destroy', ['featuredtheme' => $featuredTheme]));
Sanctum::actingAs($user);
$response->assertOk();
static::assertModelMissing($featuredTheme);
}
}
$response = delete(route('api.featuredtheme.destroy', ['featuredtheme' => $featuredTheme]));
$response->assertOk();
$this->assertModelMissing($featuredTheme);
});
@@ -2,9 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\FeaturedTheme;
use App\Concerns\Actions\Http\Api\SortsModels;
use App\Contracts\Http\Api\Field\SortableField;
use App\Enums\Http\Api\Sort\Direction;
use App\Http\Api\Criteria\Paging\Criteria;
@@ -31,266 +28,236 @@ use App\Models\Wiki\Artist;
use App\Models\Wiki\Image;
use App\Models\Wiki\Song;
use App\Models\Wiki\Video;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Tests\TestCase;
class FeaturedThemeIndexTest extends TestCase
{
use SortsModels;
use WithFaker;
use function Pest\Laravel\get;
/**
* By default, the Featured Theme Index Endpoint shall return a collection of Featured Theme Resources.
*/
public function testDefault(): void
{
$publicCount = $this->faker->randomDigitNotNull();
uses(App\Concerns\Actions\Http\Api\SortsModels::class);
$featuredThemes = FeaturedTheme::factory()->count($publicCount)->create();
uses(Illuminate\Foundation\Testing\WithFaker::class);
Collection::times($this->faker->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => $this->faker->dateTimeBetween('+1 day', '+1 year'),
]);
});
test('default', function () {
$publicCount = fake()->randomDigitNotNull();
Collection::times($this->faker->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => null,
]);
});
$featuredThemes = FeaturedTheme::factory()->count($publicCount)->create();
$response = $this->get(route('api.featuredtheme.index'));
$response->assertJsonCount($publicCount, FeaturedThemeCollection::$wrap);
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredThemes, new Query())
->response()
->getData()
),
true
)
);
}
/**
* The Featured Theme Index Endpoint shall be paginated.
*/
public function testPaginated(): void
{
FeaturedTheme::factory()->count($this->faker->randomDigitNotNull())->create();
$response = $this->get(route('api.featuredtheme.index'));
$response->assertJsonStructure([
FeaturedThemeCollection::$wrap,
'links',
'meta',
Collection::times(fake()->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => fake()->dateTimeBetween('+1 day', '+1 year'),
]);
}
});
/**
* The Featured Theme Index Endpoint shall allow inclusion of related resources.
*/
public function testAllowedIncludePaths(): void
{
$schema = new FeaturedThemeSchema();
Collection::times(fake()->randomDigitNotNull(), function () {
FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => null,
]);
});
$allowedIncludes = collect($schema->allowedIncludes());
$response = get(route('api.featuredtheme.index'));
$selectedIncludes = $allowedIncludes->random($this->faker->numberBetween(1, $allowedIncludes->count()));
$response->assertJsonCount($publicCount, FeaturedThemeCollection::$wrap);
$includedPaths = $selectedIncludes->map(fn (AllowedInclude $include) => $include->path());
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredThemes, new Query())
->response()
->getData()
),
true
)
);
});
$parameters = [
IncludeParser::param() => $includedPaths->join(','),
];
test('paginated', function () {
FeaturedTheme::factory()->count(fake()->randomDigitNotNull())->create();
FeaturedTheme::factory()
->for(
AnimeThemeEntry::factory()
->for(
AnimeTheme::factory()
->for(Anime::factory()->has(Image::factory()->count($this->faker->randomDigitNotNull())))
->for(Song::factory()->has(Artist::factory()->count($this->faker->randomDigitNotNull())))
)
)
->for(Video::factory())
->for(User::factory())
->count($this->faker->randomDigitNotNull())
->create();
$response = get(route('api.featuredtheme.index'));
$featuredThemes = FeaturedTheme::with($includedPaths->all())->get();
$response->assertJsonStructure([
FeaturedThemeCollection::$wrap,
'links',
'meta',
]);
});
$response = $this->get(route('api.featuredtheme.index', $parameters));
test('allowed include paths', function () {
$schema = new FeaturedThemeSchema();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredThemes, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$allowedIncludes = collect($schema->allowedIncludes());
/**
* The Featured Theme Index Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new FeaturedThemeSchema();
$selectedIncludes = $allowedIncludes->random(fake()->numberBetween(1, $allowedIncludes->count()));
$fields = collect($schema->fields());
$includedPaths = $selectedIncludes->map(fn (AllowedInclude $include) => $include->path());
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
$parameters = [
IncludeParser::param() => $includedPaths->join(','),
];
$parameters = [
FieldParser::param() => [
FeaturedThemeResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
FeaturedTheme::factory()
->for(
AnimeThemeEntry::factory()
->for(
AnimeTheme::factory()
->for(Anime::factory()->has(Image::factory()->count(fake()->randomDigitNotNull())))
->for(Song::factory()->has(Artist::factory()->count(fake()->randomDigitNotNull())))
)
)
->for(Video::factory())
->for(User::factory())
->count(fake()->randomDigitNotNull())
->create();
$featuredThemes = FeaturedTheme::factory()->count($this->faker->randomDigitNotNull())->create();
$featuredThemes = FeaturedTheme::with($includedPaths->all())->get();
$response = $this->get(route('api.featuredtheme.index', $parameters));
$response = get(route('api.featuredtheme.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredThemes, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredThemes, new Query($parameters))
->response()
->getData()
),
true
)
);
});
/**
* The Featured Theme Index Endpoint shall support sorting resources.
*/
public function testSorts(): void
{
$schema = new FeaturedThemeSchema();
test('sparse fieldsets', function () {
$schema = new FeaturedThemeSchema();
/** @var Sort $sort */
$sort = collect($schema->fields())
->filter(fn (Field $field) => $field instanceof SortableField)
->map(fn (SortableField $field) => $field->getSort())
->random();
$fields = collect($schema->fields());
$parameters = [
SortParser::param() => $sort->format(Arr::random(Direction::cases())),
];
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$query = new Query($parameters);
$parameters = [
FieldParser::param() => [
FeaturedThemeResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
FeaturedTheme::factory()->count($this->faker->randomDigitNotNull())->create();
$featuredThemes = FeaturedTheme::factory()->count(fake()->randomDigitNotNull())->create();
$response = $this->get(route('api.featuredtheme.index', $parameters));
$response = get(route('api.featuredtheme.index', $parameters));
$featuredThemes = $this->sort(FeaturedTheme::query(), $query, $schema)->get();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredThemes, new Query($parameters))
->response()
->getData()
),
true
)
);
});
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredThemes, $query)
->response()
->getData()
),
true
)
);
}
test('sorts', function () {
$schema = new FeaturedThemeSchema();
/**
* The Featured Theme Index Endpoint shall support filtering by created_at.
*/
public function testCreatedAtFilter(): void
{
$createdFilter = $this->faker->date();
$excludedDate = $this->faker->date();
/** @var Sort $sort */
$sort = collect($schema->fields())
->filter(fn (Field $field) => $field instanceof SortableField)
->map(fn (SortableField $field) => $field->getSort())
->random();
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_CREATED_AT => $createdFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$parameters = [
SortParser::param() => $sort->format(Arr::random(Direction::cases())),
];
Carbon::withTestNow($createdFilter, function () {
FeaturedTheme::factory()->count($this->faker->randomDigitNotNull())->create();
});
$query = new Query($parameters);
Carbon::withTestNow($excludedDate, function () {
FeaturedTheme::factory()->count($this->faker->randomDigitNotNull())->create();
});
FeaturedTheme::factory()->count(fake()->randomDigitNotNull())->create();
$featuredTheme = FeaturedTheme::query()->where(BaseModel::ATTRIBUTE_CREATED_AT, $createdFilter)->get();
$response = get(route('api.featuredtheme.index', $parameters));
$response = $this->get(route('api.featuredtheme.index', $parameters));
$featuredThemes = $this->sort(FeaturedTheme::query(), $query, $schema)->get();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredThemes, $query)
->response()
->getData()
),
true
)
);
});
/**
* The Featured Theme Index Endpoint shall support filtering by updated_at.
*/
public function testUpdatedAtFilter(): void
{
$updatedFilter = $this->faker->date();
$excludedDate = $this->faker->date();
test('created at filter', function () {
$createdFilter = fake()->date();
$excludedDate = fake()->date();
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_UPDATED_AT => $updatedFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_CREATED_AT => $createdFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
Carbon::withTestNow($updatedFilter, function () {
FeaturedTheme::factory()->count($this->faker->randomDigitNotNull())->create();
});
Carbon::withTestNow($createdFilter, function () {
FeaturedTheme::factory()->count(fake()->randomDigitNotNull())->create();
});
Carbon::withTestNow($excludedDate, function () {
FeaturedTheme::factory()->count($this->faker->randomDigitNotNull())->create();
});
Carbon::withTestNow($excludedDate, function () {
FeaturedTheme::factory()->count(fake()->randomDigitNotNull())->create();
});
$featuredTheme = FeaturedTheme::query()->where(BaseModel::ATTRIBUTE_UPDATED_AT, $updatedFilter)->get();
$featuredTheme = FeaturedTheme::query()->where(BaseModel::ATTRIBUTE_CREATED_AT, $createdFilter)->get();
$response = $this->get(route('api.featuredtheme.index', $parameters));
$response = get(route('api.featuredtheme.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
});
test('updated at filter', function () {
$updatedFilter = fake()->date();
$excludedDate = fake()->date();
$parameters = [
FilterParser::param() => [
BaseModel::ATTRIBUTE_UPDATED_AT => $updatedFilter,
],
PagingParser::param() => [
OffsetCriteria::SIZE_PARAM => Criteria::MAX_RESULTS,
],
];
Carbon::withTestNow($updatedFilter, function () {
FeaturedTheme::factory()->count(fake()->randomDigitNotNull())->create();
});
Carbon::withTestNow($excludedDate, function () {
FeaturedTheme::factory()->count(fake()->randomDigitNotNull())->create();
});
$featuredTheme = FeaturedTheme::query()->where(BaseModel::ATTRIBUTE_UPDATED_AT, $updatedFilter)->get();
$response = get(route('api.featuredtheme.index', $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeCollection($featuredTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\FeaturedTheme;
use App\Http\Api\Field\Field;
use App\Http\Api\Include\AllowedInclude;
use App\Http\Api\Parser\FieldParser;
@@ -20,122 +18,103 @@ use App\Models\Wiki\Artist;
use App\Models\Wiki\Image;
use App\Models\Wiki\Song;
use App\Models\Wiki\Video;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class FeaturedThemeShowTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* The Featured Theme Show Endpoint shall forbid the user from viewing a featured theme whose start date is in the future.
*/
public function testForbiddenIfFutureStartDate(): void
{
$featuredTheme = FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => $this->faker->dateTimeBetween('+1 day', '+1 year'),
]);
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response = $this->get(route('api.featuredtheme.show', ['featuredtheme' => $featuredTheme]));
test('forbidden if future start date', function () {
$featuredTheme = FeaturedTheme::factory()->create([
FeaturedTheme::ATTRIBUTE_START_AT => fake()->dateTimeBetween('+1 day', '+1 year'),
]);
$response->assertForbidden();
}
$response = get(route('api.featuredtheme.show', ['featuredtheme' => $featuredTheme]));
/**
* By default, the Featured Theme Show Endpoint shall return a Featured Theme Resource.
*/
public function testDefault(): void
{
$featuredTheme = FeaturedTheme::factory()->create();
$response->assertForbidden();
});
$response = $this->get(route('api.featuredtheme.show', ['featuredtheme' => $featuredTheme]));
test('default', function () {
$featuredTheme = FeaturedTheme::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($featuredTheme, new Query())
->response()
->getData()
),
true
)
);
}
$response = get(route('api.featuredtheme.show', ['featuredtheme' => $featuredTheme]));
/**
* The Featured Theme Show Endpoint shall allow inclusion of related resources.
*/
public function testAllowedIncludePaths(): void
{
$schema = new FeaturedThemeSchema();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($featuredTheme, new Query())
->response()
->getData()
),
true
)
);
});
$allowedIncludes = collect($schema->allowedIncludes());
test('allowed include paths', function () {
$schema = new FeaturedThemeSchema();
$selectedIncludes = $allowedIncludes->random($this->faker->numberBetween(1, $allowedIncludes->count()));
$allowedIncludes = collect($schema->allowedIncludes());
$includedPaths = $selectedIncludes->map(fn (AllowedInclude $include) => $include->path());
$selectedIncludes = $allowedIncludes->random(fake()->numberBetween(1, $allowedIncludes->count()));
$parameters = [
IncludeParser::param() => $includedPaths->join(','),
];
$includedPaths = $selectedIncludes->map(fn (AllowedInclude $include) => $include->path());
$featuredTheme = FeaturedTheme::factory()
->for(
AnimeThemeEntry::factory()
->for(
AnimeTheme::factory()
->for(Anime::factory()->has(Image::factory()->count($this->faker->randomDigitNotNull())))
->for(Song::factory()->has(Artist::factory()->count($this->faker->randomDigitNotNull())))
)
)
->for(Video::factory())
->for(User::factory())
->createOne();
$parameters = [
IncludeParser::param() => $includedPaths->join(','),
];
$response = $this->get(route('api.featuredtheme.show', ['featuredtheme' => $featuredTheme] + $parameters));
$featuredTheme = FeaturedTheme::factory()
->for(
AnimeThemeEntry::factory()
->for(
AnimeTheme::factory()
->for(Anime::factory()->has(Image::factory()->count(fake()->randomDigitNotNull())))
->for(Song::factory()->has(Artist::factory()->count(fake()->randomDigitNotNull())))
)
)
->for(Video::factory())
->for(User::factory())
->createOne();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($featuredTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
}
$response = get(route('api.featuredtheme.show', ['featuredtheme' => $featuredTheme] + $parameters));
/**
* The Featured Theme Show Endpoint shall implement sparse fieldsets.
*/
public function testSparseFieldsets(): void
{
$schema = new FeaturedThemeSchema();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($featuredTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
});
$fields = collect($schema->fields());
test('sparse fieldsets', function () {
$schema = new FeaturedThemeSchema();
$includedFields = $fields->random($this->faker->numberBetween(1, $fields->count()));
$fields = collect($schema->fields());
$parameters = [
FieldParser::param() => [
FeaturedThemeResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$includedFields = $fields->random(fake()->numberBetween(1, $fields->count()));
$featuredTheme = FeaturedTheme::factory()->create();
$parameters = [
FieldParser::param() => [
FeaturedThemeResource::$wrap => $includedFields->map(fn (Field $field) => $field->getKey())->join(','),
],
];
$response = $this->get(route('api.featuredtheme.show', ['featuredtheme' => $featuredTheme] + $parameters));
$featuredTheme = FeaturedTheme::factory()->create();
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($featuredTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
}
}
$response = get(route('api.featuredtheme.show', ['featuredtheme' => $featuredTheme] + $parameters));
$response->assertJson(
json_decode(
json_encode(
new FeaturedThemeResource($featuredTheme, new Query($parameters))
->response()
->getData()
),
true
)
);
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\FeaturedTheme;
use App\Enums\Auth\CrudPermission;
use App\Enums\Http\Api\Filter\AllowedDateFormat;
use App\Models\Admin\FeaturedTheme;
@@ -13,131 +11,104 @@ use App\Models\Wiki\Anime\AnimeTheme;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use App\Models\Wiki\Video;
use App\Pivots\Wiki\AnimeThemeEntryVideo;
use Illuminate\Foundation\Testing\WithFaker;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class FeaturedThemeStoreTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\post;
/**
* The Featured Theme Store Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$featuredTheme = FeaturedTheme::factory()->makeOne();
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response = $this->post(route('api.featuredtheme.store', $featuredTheme->toArray()));
test('protected', function () {
$featuredTheme = FeaturedTheme::factory()->makeOne();
$response->assertUnauthorized();
}
$response = post(route('api.featuredtheme.store', $featuredTheme->toArray()));
/**
* The Featured Theme Store Endpoint shall forbid users without the create featured theme permission.
*/
public function testForbidden(): void
{
$featuredTheme = FeaturedTheme::factory()->makeOne();
$response->assertUnauthorized();
});
$user = User::factory()->createOne();
test('forbidden', function () {
$featuredTheme = FeaturedTheme::factory()->makeOne();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->post(route('api.featuredtheme.store', $featuredTheme->toArray()));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = post(route('api.featuredtheme.store', $featuredTheme->toArray()));
/**
* The Featured Theme Store Endpoint shall require the end_at and start_at fields.
*/
public function testRequiredFields(): void
{
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(FeaturedTheme::class))->createOne();
$response->assertForbidden();
});
Sanctum::actingAs($user);
test('required fields', function () {
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(FeaturedTheme::class))->createOne();
$response = $this->post(route('api.featuredtheme.store'));
Sanctum::actingAs($user);
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_END_AT,
FeaturedTheme::ATTRIBUTE_START_AT,
]);
}
$response = post(route('api.featuredtheme.store'));
/**
* The Featured Theme Store Endpoint shall require the start_at field to be before the end_at field and vice versa.
*/
public function testStartAtBeforeEndDate(): void
{
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_START_AT => $this->faker->dateTimeBetween('+1 day', '+1 year')->format(AllowedDateFormat::YMDHISU->value),
FeaturedTheme::ATTRIBUTE_END_AT => $this->faker->dateTimeBetween('-1 year', '-1 day')->format(AllowedDateFormat::YMDHISU->value),
]);
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_END_AT,
FeaturedTheme::ATTRIBUTE_START_AT,
]);
});
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(FeaturedTheme::class))->createOne();
test('start at before end date', function () {
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_START_AT => fake()->dateTimeBetween('+1 day', '+1 year')->format(AllowedDateFormat::YMDHISU->value),
FeaturedTheme::ATTRIBUTE_END_AT => fake()->dateTimeBetween('-1 year', '-1 day')->format(AllowedDateFormat::YMDHISU->value),
]);
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(FeaturedTheme::class))->createOne();
$response = $this->post(route('api.featuredtheme.store', $parameters));
Sanctum::actingAs($user);
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_START_AT,
FeaturedTheme::ATTRIBUTE_END_AT,
]);
}
$response = post(route('api.featuredtheme.store', $parameters));
/**
* The Featured Theme Store Endpoint shall require the entry and video to have an association.
*/
public function testAnimeThemeEntryVideoExists(): void
{
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->create();
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_START_AT,
FeaturedTheme::ATTRIBUTE_END_AT,
]);
});
$video = Video::factory()->create();
test('anime theme entry video exists', function () {
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->create();
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_ENTRY => $entry->getKey(),
FeaturedTheme::ATTRIBUTE_VIDEO => $video->getKey(),
]);
$video = Video::factory()->create();
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(FeaturedTheme::class))->createOne();
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_ENTRY => $entry->getKey(),
FeaturedTheme::ATTRIBUTE_VIDEO => $video->getKey(),
]);
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(FeaturedTheme::class))->createOne();
$response = $this->post(route('api.featuredtheme.store', $parameters));
Sanctum::actingAs($user);
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_ENTRY,
FeaturedTheme::ATTRIBUTE_VIDEO,
]);
}
$response = post(route('api.featuredtheme.store', $parameters));
/**
* The Featured Theme Store Endpoint shall create a featured theme.
*/
public function testCreate(): void
{
$entryVideo = AnimeThemeEntryVideo::factory()
->for(AnimeThemeEntry::factory()->for(AnimeTheme::factory()->for(Anime::factory())))
->for(Video::factory())
->createOne();
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_ENTRY,
FeaturedTheme::ATTRIBUTE_VIDEO,
]);
});
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_ENTRY => $entryVideo->entry_id,
FeaturedTheme::ATTRIBUTE_VIDEO => $entryVideo->video_id,
]);
test('create', function () {
$entryVideo = AnimeThemeEntryVideo::factory()
->for(AnimeThemeEntry::factory()->for(AnimeTheme::factory()->for(Anime::factory())))
->for(Video::factory())
->createOne();
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(FeaturedTheme::class))->createOne();
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_ENTRY => $entryVideo->entry_id,
FeaturedTheme::ATTRIBUTE_VIDEO => $entryVideo->video_id,
]);
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::CREATE->format(FeaturedTheme::class))->createOne();
$response = $this->post(route('api.featuredtheme.store', $parameters));
Sanctum::actingAs($user);
$response->assertCreated();
static::assertDatabaseCount(FeaturedTheme::class, 1);
}
}
$response = post(route('api.featuredtheme.store', $parameters));
$response->assertCreated();
$this->assertDatabaseCount(FeaturedTheme::class, 1);
});
@@ -2,8 +2,6 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Admin\FeaturedTheme;
use App\Enums\Auth\CrudPermission;
use App\Enums\Http\Api\Filter\AllowedDateFormat;
use App\Models\Admin\FeaturedTheme;
@@ -13,123 +11,100 @@ use App\Models\Wiki\Anime\AnimeTheme;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use App\Models\Wiki\Video;
use App\Pivots\Wiki\AnimeThemeEntryVideo;
use Illuminate\Foundation\Testing\WithFaker;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class FeaturedThemeUpdateTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\put;
/**
* The Featured Theme Update Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
uses(Illuminate\Foundation\Testing\WithFaker::class);
$parameters = FeaturedTheme::factory()->raw();
test('protected', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
$response = $this->put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
$parameters = FeaturedTheme::factory()->raw();
$response->assertUnauthorized();
}
$response = put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
/**
* The Featured Theme Update Endpoint shall forbid users without the update featured theme permission.
*/
public function testForbidden(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
$response->assertUnauthorized();
});
$parameters = FeaturedTheme::factory()->raw();
test('forbidden', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
$user = User::factory()->createOne();
$parameters = FeaturedTheme::factory()->raw();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
/**
* The Featured Update Store Endpoint shall require the start_at field to be before the end_at field and vice versa.
*/
public function testStartAtBeforeEndDate(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
$response->assertForbidden();
});
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_START_AT => $this->faker->dateTimeBetween('+1 day', '+1 year')->format(AllowedDateFormat::YMDHISU->value),
FeaturedTheme::ATTRIBUTE_END_AT => $this->faker->dateTimeBetween('-1 year', '-1 day')->format(AllowedDateFormat::YMDHISU->value),
]);
test('start at before end date', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(FeaturedTheme::class))->createOne();
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_START_AT => fake()->dateTimeBetween('+1 day', '+1 year')->format(AllowedDateFormat::YMDHISU->value),
FeaturedTheme::ATTRIBUTE_END_AT => fake()->dateTimeBetween('-1 year', '-1 day')->format(AllowedDateFormat::YMDHISU->value),
]);
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(FeaturedTheme::class))->createOne();
$response = $this->put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
Sanctum::actingAs($user);
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_START_AT,
FeaturedTheme::ATTRIBUTE_END_AT,
]);
}
$response = put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
/**
* The Featured Theme Update Endpoint shall require the entry and video to have an association.
*/
public function testAnimeThemeEntryVideoExists(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_START_AT,
FeaturedTheme::ATTRIBUTE_END_AT,
]);
});
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->create();
test('anime theme entry video exists', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
$video = Video::factory()->create();
$entry = AnimeThemeEntry::factory()
->for(AnimeTheme::factory()->for(Anime::factory()))
->create();
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_ENTRY => $entry->getKey(),
FeaturedTheme::ATTRIBUTE_VIDEO => $video->getKey(),
]);
$video = Video::factory()->create();
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(FeaturedTheme::class))->createOne();
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_ENTRY => $entry->getKey(),
FeaturedTheme::ATTRIBUTE_VIDEO => $video->getKey(),
]);
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(FeaturedTheme::class))->createOne();
$response = $this->put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
Sanctum::actingAs($user);
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_ENTRY,
FeaturedTheme::ATTRIBUTE_VIDEO,
]);
}
$response = put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
/**
* The Featured Theme Update Endpoint shall update a featured theme.
*/
public function testUpdate(): void
{
$featuredTheme = FeaturedTheme::factory()->createOne();
$response->assertJsonValidationErrors([
FeaturedTheme::ATTRIBUTE_ENTRY,
FeaturedTheme::ATTRIBUTE_VIDEO,
]);
});
$entryVideo = AnimeThemeEntryVideo::factory()
->for(AnimeThemeEntry::factory()->for(AnimeTheme::factory()->for(Anime::factory())))
->for(Video::factory())
->createOne();
test('update', function () {
$featuredTheme = FeaturedTheme::factory()->createOne();
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_ENTRY => $entryVideo->entry_id,
FeaturedTheme::ATTRIBUTE_VIDEO => $entryVideo->video_id,
]);
$entryVideo = AnimeThemeEntryVideo::factory()
->for(AnimeThemeEntry::factory()->for(AnimeTheme::factory()->for(Anime::factory())))
->for(Video::factory())
->createOne();
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(FeaturedTheme::class))->createOne();
$parameters = FeaturedTheme::factory()->raw([
FeaturedTheme::ATTRIBUTE_ENTRY => $entryVideo->entry_id,
FeaturedTheme::ATTRIBUTE_VIDEO => $entryVideo->video_id,
]);
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::UPDATE->format(FeaturedTheme::class))->createOne();
$response = $this->put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
Sanctum::actingAs($user);
$response->assertOk();
}
}
$response = put(route('api.featuredtheme.update', ['featuredtheme' => $featuredTheme] + $parameters));
$response->assertOk();
});
@@ -2,83 +2,66 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Auth\User\Me\List\ExternalProfile;
use App\Enums\Auth\CrudPermission;
use App\Http\Api\Query\Query;
use App\Http\Resources\List\Collection\ExternalProfileCollection;
use App\Models\Auth\User;
use App\Models\List\ExternalProfile;
use Illuminate\Foundation\Testing\WithFaker;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class MyExternalProfileIndexTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* The My External Profile Index Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$response = $this->get(route('api.me.externalprofile.index'));
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response->assertUnauthorized();
}
test('protected', function () {
$response = get(route('api.me.externalprofile.index'));
/**
* The My External Profile Index Endpoint shall forbid users without the view external profile permission.
*/
public function testForbiddenIfMissingPermission(): void
{
$user = User::factory()->createOne();
$response->assertUnauthorized();
});
Sanctum::actingAs($user);
test('forbidden if missing permission', function () {
$user = User::factory()->createOne();
$response = $this->get(route('api.me.externalprofile.index'));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = get(route('api.me.externalprofile.index'));
/**
* The My External Profile Index Endpoint shall return profiles owned by the user.
*/
public function testOnlySeesOwnedProfiles(): void
{
ExternalProfile::factory()
->for(User::factory())
->count($this->faker->randomDigitNotNull())
->create();
$response->assertForbidden();
});
ExternalProfile::factory()
->count($this->faker->randomDigitNotNull())
->create();
test('only sees owned profiles', function () {
ExternalProfile::factory()
->for(User::factory())
->count(fake()->randomDigitNotNull())
->create();
$user = User::factory()->withPermissions(CrudPermission::VIEW->format(ExternalProfile::class))->createOne();
ExternalProfile::factory()
->count(fake()->randomDigitNotNull())
->create();
$profileCount = $this->faker->randomDigitNotNull();
$user = User::factory()->withPermissions(CrudPermission::VIEW->format(ExternalProfile::class))->createOne();
$profiles = ExternalProfile::factory()
->for($user)
->count($profileCount)
->create();
$profileCount = fake()->randomDigitNotNull();
Sanctum::actingAs($user);
$profiles = ExternalProfile::factory()
->for($user)
->count($profileCount)
->create();
$response = $this->get(route('api.me.externalprofile.index'));
Sanctum::actingAs($user);
$response->assertJsonCount($profileCount, ExternalProfileCollection::$wrap);
$response = get(route('api.me.externalprofile.index'));
$response->assertJson(
json_decode(
json_encode(
new ExternalProfileCollection($profiles, new Query())
->response()
->getData()
),
true
)
);
}
}
$response->assertJsonCount($profileCount, ExternalProfileCollection::$wrap);
$response->assertJson(
json_decode(
json_encode(
new ExternalProfileCollection($profiles, new Query())
->response()
->getData()
),
true
)
);
});
@@ -2,83 +2,66 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Auth\User\Me\List\Playlist;
use App\Enums\Auth\CrudPermission;
use App\Http\Api\Query\Query;
use App\Http\Resources\List\Collection\PlaylistCollection;
use App\Models\Auth\User;
use App\Models\List\Playlist;
use Illuminate\Foundation\Testing\WithFaker;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class MyPlaylistIndexTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* The My Playlist Index Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$response = $this->get(route('api.me.playlist.index'));
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response->assertUnauthorized();
}
test('protected', function () {
$response = get(route('api.me.playlist.index'));
/**
* The My Playlist Index Endpoint shall forbid users without the view playlist permission.
*/
public function testForbiddenIfMissingPermission(): void
{
$user = User::factory()->createOne();
$response->assertUnauthorized();
});
Sanctum::actingAs($user);
test('forbidden if missing permission', function () {
$user = User::factory()->createOne();
$response = $this->get(route('api.me.playlist.index'));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = get(route('api.me.playlist.index'));
/**
* The My Playlist Index Endpoint shall return playlists owned by the user.
*/
public function testOnlySeesOwnedPlaylists(): void
{
Playlist::factory()
->for(User::factory())
->count($this->faker->randomDigitNotNull())
->create();
$response->assertForbidden();
});
Playlist::factory()
->count($this->faker->randomDigitNotNull())
->create();
test('only sees owned playlists', function () {
Playlist::factory()
->for(User::factory())
->count(fake()->randomDigitNotNull())
->create();
$user = User::factory()->withPermissions(CrudPermission::VIEW->format(Playlist::class))->createOne();
Playlist::factory()
->count(fake()->randomDigitNotNull())
->create();
$playlistCount = $this->faker->randomDigitNotNull();
$user = User::factory()->withPermissions(CrudPermission::VIEW->format(Playlist::class))->createOne();
$playlists = Playlist::factory()
->for($user)
->count($playlistCount)
->create();
$playlistCount = fake()->randomDigitNotNull();
Sanctum::actingAs($user);
$playlists = Playlist::factory()
->for($user)
->count($playlistCount)
->create();
$response = $this->get(route('api.me.playlist.index'));
Sanctum::actingAs($user);
$response->assertJsonCount($playlistCount, PlaylistCollection::$wrap);
$response = get(route('api.me.playlist.index'));
$response->assertJson(
json_decode(
json_encode(
new PlaylistCollection($playlists, new Query())
->response()
->getData()
),
true
)
);
}
}
$response->assertJsonCount($playlistCount, PlaylistCollection::$wrap);
$response->assertJson(
json_decode(
json_encode(
new PlaylistCollection($playlists, new Query())
->response()
->getData()
),
true
)
);
});
@@ -2,49 +2,36 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Auth\User\Me;
use App\Http\Api\Query\Query;
use App\Http\Resources\Auth\Resource\UserResource;
use App\Models\Auth\User;
use Illuminate\Foundation\Testing\WithFaker;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class MyShowTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* The My Show Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$response = $this->get(route('api.me.show'));
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response->assertUnauthorized();
}
test('protected', function () {
$response = get(route('api.me.show'));
/**
* The My Show Endpoint shall return the resource of the current user.
*/
public function testDefault(): void
{
$user = User::factory()->createOne();
$response->assertUnauthorized();
});
Sanctum::actingAs($user);
test('default', function () {
$user = User::factory()->createOne();
$response = $this->get(route('api.me.show'));
Sanctum::actingAs($user);
$response->assertJson(
json_decode(
json_encode(
new UserResource($user, new Query())
->response()
->getData()
),
true
)
);
}
}
$response = get(route('api.me.show'));
$response->assertJson(
json_decode(
json_encode(
new UserResource($user, new Query())
->response()
->getData()
),
true
)
);
});
@@ -2,81 +2,64 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Auth\User\Me\Notification;
use App\Enums\Auth\CrudPermission;
use App\Http\Api\Query\Query;
use App\Http\Resources\User\Collection\NotificationCollection;
use App\Models\Auth\User;
use App\Models\User\Notification;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\WithFaker;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class MyNotificationIndexTest extends TestCase
{
use WithFaker;
use function Pest\Laravel\get;
/**
* The My Notification Index Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$response = $this->get(route('api.me.notification.index'));
uses(Illuminate\Foundation\Testing\WithFaker::class);
$response->assertUnauthorized();
}
test('protected', function () {
$response = get(route('api.me.notification.index'));
/**
* The My Notification Index Endpoint shall forbid users without the view notification permission.
*/
public function testForbiddenIfMissingPermission(): void
{
$user = User::factory()->createOne();
$response->assertUnauthorized();
});
Sanctum::actingAs($user);
test('forbidden if missing permission', function () {
$user = User::factory()->createOne();
$response = $this->get(route('api.me.notification.index'));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = get(route('api.me.notification.index'));
/**
* The My Notification Index Endpoint shall return notifications owned by the user.
*/
public function testOnlySeesOwnedNotifications(): void
{
Notification::factory()
->for(User::factory(), Notification::RELATION_NOTIFIABLE)
->count($this->faker->randomDigitNotNull())
->create();
$response->assertForbidden();
});
$user = User::factory()->withPermissions(CrudPermission::VIEW->format(Notification::class))->createOne();
test('only sees owned notifications', function () {
Notification::factory()
->for(User::factory(), Notification::RELATION_NOTIFIABLE)
->count(fake()->randomDigitNotNull())
->create();
$notificationCount = $this->faker->randomDigitNotNull();
$user = User::factory()->withPermissions(CrudPermission::VIEW->format(Notification::class))->createOne();
$notifications = Notification::factory()
->for($user, Notification::RELATION_NOTIFIABLE)
->count($notificationCount)
->create()
->sortBy(Model::CREATED_AT);
$notificationCount = fake()->randomDigitNotNull();
Sanctum::actingAs($user);
$notifications = Notification::factory()
->for($user, Notification::RELATION_NOTIFIABLE)
->count($notificationCount)
->create()
->sortBy(Model::CREATED_AT);
$response = $this->get(route('api.me.notification.index'));
Sanctum::actingAs($user);
$response->assertJsonCount($notificationCount, NotificationCollection::$wrap);
$response = get(route('api.me.notification.index'));
$response->assertJson(
json_decode(
json_encode(
new NotificationCollection($notifications, new Query())
->response()
->getData()
),
true
)
);
}
}
$response->assertJsonCount($notificationCount, NotificationCollection::$wrap);
$response->assertJson(
json_decode(
json_encode(
new NotificationCollection($notifications, new Query())
->response()
->getData()
),
true
)
);
});
@@ -2,74 +2,54 @@
declare(strict_types=1);
namespace Tests\Feature\Http\Api\Document\Page;
use App\Enums\Auth\CrudPermission;
use App\Models\Auth\User;
use App\Models\Document\Page;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class PageDestroyTest extends TestCase
{
/**
* The Page Destroy Endpoint shall be protected by sanctum.
*/
public function testProtected(): void
{
$page = Page::factory()->createOne();
use function Pest\Laravel\delete;
$response = $this->delete(route('api.page.destroy', ['page' => $page]));
test('protected', function () {
$page = Page::factory()->createOne();
$response->assertUnauthorized();
}
$response = delete(route('api.page.destroy', ['page' => $page]));
/**
* The Page Destroy Endpoint shall forbid users without the delete page permission.
*/
public function testForbidden(): void
{
$page = Page::factory()->createOne();
$response->assertUnauthorized();
});
$user = User::factory()->createOne();
test('forbidden', function () {
$page = Page::factory()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->createOne();
$response = $this->delete(route('api.page.destroy', ['page' => $page]));
Sanctum::actingAs($user);
$response->assertForbidden();
}
$response = delete(route('api.page.destroy', ['page' => $page]));
/**
* The Page Destroy Endpoint shall forbid users from updating a page that is trashed.
*/
public function testTrashed(): void
{
$page = Page::factory()->trashed()->createOne();
$response->assertForbidden();
});
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(Page::class))->createOne();
test('trashed', function () {
$page = Page::factory()->trashed()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(Page::class))->createOne();
$response = $this->delete(route('api.page.destroy', ['page' => $page]));
Sanctum::actingAs($user);
$response->assertNotFound();
}
$response = delete(route('api.page.destroy', ['page' => $page]));
/**
* The Page Destroy Endpoint shall delete the page.
*/
public function testDeleted(): void
{
$page = Page::factory()->createOne();
$response->assertNotFound();
});
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(Page::class))->createOne();
test('deleted', function () {
$page = Page::factory()->createOne();
Sanctum::actingAs($user);
$user = User::factory()->withPermissions(CrudPermission::DELETE->format(Page::class))->createOne();
$response = $this->delete(route('api.page.destroy', ['page' => $page]));
Sanctum::actingAs($user);
$response->assertOk();
static::assertSoftDeleted($page);
}
}
$response = delete(route('api.page.destroy', ['page' => $page]));
$response->assertOk();
$this->assertSoftDeleted($page);
});

Some files were not shown because too many files have changed in this diff Show More