mirror of
https://github.com/sp-tarkov/forge.git
synced 2025-02-12 20:20:41 -05:00
API Filters Clean-up
Generalized similar API filter methods and moved them into a FilterMethods trait. Rewrote ModFilter and UserFilter methods to use the general trait methods.
This commit is contained in:
parent
2199e34569
commit
d70a38bf08
@ -4,13 +4,17 @@ namespace App\Http\Filters\V1;
|
|||||||
|
|
||||||
use App\Models\Mod;
|
use App\Models\Mod;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends QueryFilter<Mod>
|
* @extends QueryFilter<Mod>
|
||||||
*/
|
*/
|
||||||
class ModFilter extends QueryFilter
|
class ModFilter extends QueryFilter
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The sortable fields.
|
||||||
|
*
|
||||||
|
* @var array<string>
|
||||||
|
*/
|
||||||
protected array $sortable = [
|
protected array $sortable = [
|
||||||
'name',
|
'name',
|
||||||
'slug',
|
'slug',
|
||||||
@ -24,9 +28,6 @@ class ModFilter extends QueryFilter
|
|||||||
'published_at',
|
'published_at',
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: Many of these are repeated across UserFilter and ModFilter. Consider refactoring into a shared trait.
|
|
||||||
// Also, consider using common filter types and making the field names dynamic.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter by ID.
|
* Filter by ID.
|
||||||
*
|
*
|
||||||
@ -34,9 +35,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function id(string $value): Builder
|
public function id(string $value): Builder
|
||||||
{
|
{
|
||||||
$ids = array_map('trim', explode(',', $value));
|
return $this->filterWhereIn('id', $value);
|
||||||
|
|
||||||
return $this->builder->whereIn('id', $ids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,9 +45,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function hub_id(string $value): Builder
|
public function hub_id(string $value): Builder
|
||||||
{
|
{
|
||||||
$ids = array_map('trim', explode(',', $value));
|
return $this->filterWhereIn('hub_id', $value);
|
||||||
|
|
||||||
return $this->builder->whereIn('hub_id', $ids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,10 +55,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function name(string $value): Builder
|
public function name(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%).
|
return $this->filterByWildcardLike('name', $value);
|
||||||
$like = Str::replace('*', '%', $value);
|
|
||||||
|
|
||||||
return $this->builder->where('name', 'like', $like);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,10 +65,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function slug(string $value): Builder
|
public function slug(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%).
|
return $this->filterByWildcardLike('slug', $value);
|
||||||
$like = Str::replace('*', '%', $value);
|
|
||||||
|
|
||||||
return $this->builder->where('slug', 'like', $like);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,10 +75,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function teaser(string $value): Builder
|
public function teaser(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%).
|
return $this->filterByWildcardLike('teaser', $value);
|
||||||
$like = Str::replace('*', '%', $value);
|
|
||||||
|
|
||||||
return $this->builder->where('teaser', 'like', $like);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,10 +85,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function source_code_link(string $value): Builder
|
public function source_code_link(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%).
|
return $this->filterByWildcardLike('source_code_link', $value);
|
||||||
$like = Str::replace('*', '%', $value);
|
|
||||||
|
|
||||||
return $this->builder->where('source_code_link', 'like', $like);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,13 +95,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function created_at(string $value): Builder
|
public function created_at(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API allows for a range of dates to be passed as a comma-separated list.
|
return $this->filterByDate('created_at', $value);
|
||||||
$dates = array_map('trim', explode(',', $value));
|
|
||||||
if (count($dates) > 1) {
|
|
||||||
return $this->builder->whereBetween('created_at', $dates);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder->whereDate('created_at', $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,13 +105,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function updated_at(string $value): Builder
|
public function updated_at(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API allows for a range of dates to be passed as a comma-separated list.
|
return $this->filterByDate('updated_at', $value);
|
||||||
$dates = array_map('trim', explode(',', $value));
|
|
||||||
if (count($dates) > 1) {
|
|
||||||
return $this->builder->whereBetween('updated_at', $dates);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder->whereDate('updated_at', $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,13 +115,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function published_at(string $value): Builder
|
public function published_at(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API allows for a range of dates to be passed as a comma-separated list.
|
return $this->filterByDate('published_at', $value);
|
||||||
$dates = array_map('trim', explode(',', $value));
|
|
||||||
if (count($dates) > 1) {
|
|
||||||
return $this->builder->whereBetween('published_at', $dates);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder->whereDate('published_at', $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,15 +125,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function featured(string $value): Builder
|
public function featured(string $value): Builder
|
||||||
{
|
{
|
||||||
// We need to convert the string user input to a boolean, or null if it's not a valid "truthy/falsy" value.
|
return $this->filterByBoolean('featured', $value);
|
||||||
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
|
||||||
|
|
||||||
// This column is not nullable.
|
|
||||||
if ($value === null) {
|
|
||||||
return $this->builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder->where('featured', $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -176,15 +135,7 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function contains_ads(string $value): Builder
|
public function contains_ads(string $value): Builder
|
||||||
{
|
{
|
||||||
// We need to convert the string user input to a boolean, or null if it's not a valid "truthy/falsy" value.
|
return $this->filterByBoolean('contains_ads', $value);
|
||||||
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
|
||||||
|
|
||||||
// This column is not nullable.
|
|
||||||
if ($value === null) {
|
|
||||||
return $this->builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder->where('contains_ads', $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,14 +145,6 @@ class ModFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function contains_ai_content(string $value): Builder
|
public function contains_ai_content(string $value): Builder
|
||||||
{
|
{
|
||||||
// We need to convert the string user input to a boolean, or null if it's not a valid "truthy/falsy" value.
|
return $this->filterByBoolean('contains_ai_content', $value);
|
||||||
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
|
||||||
|
|
||||||
// This column is not nullable.
|
|
||||||
if ($value === null) {
|
|
||||||
return $this->builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder->where('contains_ai_content', $value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,23 @@
|
|||||||
|
|
||||||
namespace App\Http\Filters\V1;
|
namespace App\Http\Filters\V1;
|
||||||
|
|
||||||
|
use App\Traits\V1\FilterMethods;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template TModelClass of Model
|
* @template TModelClass of Model
|
||||||
*/
|
*/
|
||||||
abstract class QueryFilter
|
abstract class QueryFilter
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Include general filter methods.
|
||||||
|
*
|
||||||
|
* @use FilterMethods<TModelClass>
|
||||||
|
*/
|
||||||
|
use FilterMethods;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The query builder instance.
|
* The query builder instance.
|
||||||
*
|
*
|
||||||
@ -19,18 +26,45 @@ abstract class QueryFilter
|
|||||||
*/
|
*/
|
||||||
protected Builder $builder;
|
protected Builder $builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The request instance.
|
||||||
|
*/
|
||||||
protected Request $request;
|
protected Request $request;
|
||||||
|
|
||||||
/** @var array<string> */
|
/**
|
||||||
|
* The sortable fields.
|
||||||
|
*
|
||||||
|
* @var array<string>
|
||||||
|
*/
|
||||||
protected array $sortable = [];
|
protected array $sortable = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new QueryFilter instance.
|
||||||
|
*/
|
||||||
public function __construct(Request $request)
|
public function __construct(Request $request)
|
||||||
{
|
{
|
||||||
$this->request = $request;
|
$this->request = $request;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the filter to the query builder.
|
* Iterate over each of the filter options and call the appropriate method if it exists.
|
||||||
|
*
|
||||||
|
* @param array<string, string> $filters
|
||||||
|
* @return Builder<TModelClass>
|
||||||
|
*/
|
||||||
|
public function filter(array $filters): Builder
|
||||||
|
{
|
||||||
|
foreach ($filters as $attribute => $value) {
|
||||||
|
if (method_exists($this, $attribute)) {
|
||||||
|
$this->$attribute($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over all request data and call the appropriate method if it exists.
|
||||||
*
|
*
|
||||||
* @param Builder<TModelClass> $builder
|
* @param Builder<TModelClass> $builder
|
||||||
* @return Builder<TModelClass>
|
* @return Builder<TModelClass>
|
||||||
@ -47,25 +81,4 @@ abstract class QueryFilter
|
|||||||
|
|
||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply the sort type to the query.
|
|
||||||
*
|
|
||||||
* @return Builder<TModelClass>
|
|
||||||
*/
|
|
||||||
protected function sort(string $values): Builder
|
|
||||||
{
|
|
||||||
$sortables = array_map('trim', explode(',', $values));
|
|
||||||
|
|
||||||
foreach ($sortables as $sortable) {
|
|
||||||
$direction = Str::startsWith($sortable, '-') ? 'desc' : 'asc';
|
|
||||||
$column = Str::of($sortable)->remove('-')->value();
|
|
||||||
|
|
||||||
if (in_array($column, $this->sortable)) {
|
|
||||||
$this->builder->orderBy($column, $direction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ namespace App\Http\Filters\V1;
|
|||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends QueryFilter<User>
|
* @extends QueryFilter<User>
|
||||||
@ -22,9 +21,6 @@ class UserFilter extends QueryFilter
|
|||||||
'updated_at',
|
'updated_at',
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: Many of these are repeated across UserFilter and ModFilter. Consider refactoring into a shared trait.
|
|
||||||
// Also, consider using common filter types and making the field names dynamic.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter by ID.
|
* Filter by ID.
|
||||||
*
|
*
|
||||||
@ -32,9 +28,7 @@ class UserFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function id(string $value): Builder
|
public function id(string $value): Builder
|
||||||
{
|
{
|
||||||
$ids = array_map('trim', explode(',', $value));
|
return $this->filterWhereIn('id', $value);
|
||||||
|
|
||||||
return $this->builder->whereIn('id', $ids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,10 +38,7 @@ class UserFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function name(string $value): Builder
|
public function name(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API handles the wildcard character as an asterisk (*), but the database uses the percentage sign (%).
|
return $this->filterByWildcardLike('name', $value);
|
||||||
$like = Str::replace('*', '%', $value);
|
|
||||||
|
|
||||||
return $this->builder->where('name', 'like', $like);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,13 +48,7 @@ class UserFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function created_at(string $value): Builder
|
public function created_at(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API allows for a range of dates to be passed as a comma-separated list.
|
return $this->filterByDate('created_at', $value);
|
||||||
$dates = array_map('trim', explode(',', $value));
|
|
||||||
if (count($dates) > 1) {
|
|
||||||
return $this->builder->whereBetween('created_at', $dates);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder->whereDate('created_at', $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,12 +58,6 @@ class UserFilter extends QueryFilter
|
|||||||
*/
|
*/
|
||||||
public function updated_at(string $value): Builder
|
public function updated_at(string $value): Builder
|
||||||
{
|
{
|
||||||
// The API allows for a range of dates to be passed as a comma-separated list.
|
return $this->filterByDate('updated_at', $value);
|
||||||
$dates = array_map('trim', explode(',', $value));
|
|
||||||
if (count($dates) > 1) {
|
|
||||||
return $this->builder->whereBetween('updated_at', $dates);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->builder->whereDate('updated_at', $value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ class ModVersion extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the parent mod's updated_at timestamp when the mod version is updated.
|
* Update the parent mod's updated_at timestamp when the mod version is updated.
|
||||||
|
*
|
||||||
|
* @var array<string>
|
||||||
*/
|
*/
|
||||||
protected $touches = ['mod'];
|
protected $touches = ['mod'];
|
||||||
|
|
||||||
|
106
app/Traits/V1/FilterMethods.php
Normal file
106
app/Traits/V1/FilterMethods.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits\V1;
|
||||||
|
|
||||||
|
use App\Http\Filters\V1\QueryFilter;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template TModelClass of Model
|
||||||
|
*
|
||||||
|
* @mixin QueryFilter<TModelClass>
|
||||||
|
*/
|
||||||
|
trait FilterMethods
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Filter using a whereIn clause.
|
||||||
|
*
|
||||||
|
* @return Builder<TModelClass>
|
||||||
|
*/
|
||||||
|
public function filterWhereIn(string $column, string $value): Builder
|
||||||
|
{
|
||||||
|
$ids = array_map('trim', explode(',', $value));
|
||||||
|
|
||||||
|
$result = $this->builder->whereIn($column, $ids);
|
||||||
|
|
||||||
|
/** @var Builder<TModelClass> $result */
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter using a LIKE clause with a wildcard characters.
|
||||||
|
*
|
||||||
|
* @return Builder<TModelClass>
|
||||||
|
*/
|
||||||
|
public function filterByWildcardLike(string $column, string $value): Builder
|
||||||
|
{
|
||||||
|
$like = Str::replace('*', '%', $value);
|
||||||
|
|
||||||
|
$result = $this->builder->where($column, 'like', $like);
|
||||||
|
|
||||||
|
/** @var Builder<TModelClass> $result */
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by date range or specific date.
|
||||||
|
*
|
||||||
|
* @return Builder<TModelClass>
|
||||||
|
*/
|
||||||
|
public function filterByDate(string $column, string $value): Builder
|
||||||
|
{
|
||||||
|
$dates = array_map('trim', explode(',', $value));
|
||||||
|
|
||||||
|
if (count($dates) > 1) {
|
||||||
|
$result = $this->builder->whereBetween($column, $dates);
|
||||||
|
} else {
|
||||||
|
$result = $this->builder->whereDate($column, $dates[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Builder<TModelClass> $result */
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by boolean value.
|
||||||
|
*
|
||||||
|
* @return Builder<TModelClass>
|
||||||
|
*/
|
||||||
|
public function filterByBoolean(string $column, string $value): Builder
|
||||||
|
{
|
||||||
|
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
||||||
|
if ($value === null) {
|
||||||
|
$result = $this->builder; // The unmodified builder
|
||||||
|
} else {
|
||||||
|
$result = $this->builder->where($column, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Builder<TModelClass> $result */
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the sort type to the query.
|
||||||
|
*
|
||||||
|
* @return Builder<TModelClass>
|
||||||
|
*/
|
||||||
|
protected function sort(string $values): Builder
|
||||||
|
{
|
||||||
|
$result = $this->builder;
|
||||||
|
$sortables = array_map('trim', explode(',', $values));
|
||||||
|
|
||||||
|
foreach ($sortables as $sortable) {
|
||||||
|
$direction = Str::startsWith($sortable, '-') ? 'desc' : 'asc';
|
||||||
|
$column = Str::of($sortable)->remove('-')->value();
|
||||||
|
|
||||||
|
if (in_array($column, $this->sortable)) {
|
||||||
|
$result = $this->builder->orderBy($column, $direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Builder<TModelClass> $result */
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
54
tests/Feature/Api/V1/ModFilterTest.php
Normal file
54
tests/Feature/Api/V1/ModFilterTest.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Filters\V1\ModFilter;
|
||||||
|
use App\Models\Mod;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
Mod::factory()->create(['name' => 'Mod C', 'slug' => 'mod-c', 'featured' => true]);
|
||||||
|
Mod::factory()->create(['name' => 'Mod B', 'slug' => 'mod-b', 'featured' => false]);
|
||||||
|
Mod::factory()->create(['name' => 'Mod A', 'slug' => 'mod-a', 'featured' => true]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can filter mods by id', function () {
|
||||||
|
$request = new Request(['id' => '1,2']);
|
||||||
|
$filter = new ModFilter($request);
|
||||||
|
$query = $filter->apply(Mod::query());
|
||||||
|
|
||||||
|
expect($query->get()->pluck('id')->toArray())->toBe([1, 2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can filter mods by name with wildcard', function () {
|
||||||
|
$request = new Request(['name' => 'Mod*']);
|
||||||
|
$filter = new ModFilter($request);
|
||||||
|
$query = $filter->apply(Mod::query());
|
||||||
|
|
||||||
|
expect($query->get()->pluck('name')->toArray())->toContain('Mod A', 'Mod B', 'Mod C');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can filter mods by featured status', function () {
|
||||||
|
$request = new Request(['featured' => 'true']);
|
||||||
|
$filter = new ModFilter($request);
|
||||||
|
$query = $filter->apply(Mod::query());
|
||||||
|
|
||||||
|
expect($query->get()->pluck('name')->toArray())->toContain('Mod A', 'Mod C');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can sort mods by name in ascending order', function () {
|
||||||
|
$request = new Request(['sort' => 'name']);
|
||||||
|
$filter = new ModFilter($request);
|
||||||
|
$query = $filter->apply(Mod::query());
|
||||||
|
|
||||||
|
expect($query->get()->pluck('name')->toArray())->toBe(['Mod A', 'Mod B', 'Mod C']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can sort mods by name in descending order', function () {
|
||||||
|
$request = new Request(['sort' => '-name']);
|
||||||
|
$filter = new ModFilter($request);
|
||||||
|
$query = $filter->apply(Mod::query());
|
||||||
|
|
||||||
|
expect($query->get()->pluck('name')->toArray())->toBe(['Mod C', 'Mod B', 'Mod A']);
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user