Skip to content

Commit

Permalink
Merge pull request #5596 from Laravel-Backpack/add-search-tests
Browse files Browse the repository at this point in the history
Add tests to Search trait
  • Loading branch information
pxpm committed Aug 2, 2024
2 parents fe0ac36 + b36c802 commit 89f4c31
Show file tree
Hide file tree
Showing 6 changed files with 379 additions and 15 deletions.
10 changes: 5 additions & 5 deletions src/app/Library/CrudPanel/Traits/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function applySearchLogicForColumn($query, $column, $searchTerm)
$searchLogic = $column['searchLogic'];

// if a closure was passed, execute it
if (is_callable($searchLogic)) {
if ($searchLogic instanceof \Closure) {
return $searchLogic($query, $column, $searchTerm);
}

Expand All @@ -55,7 +55,7 @@ public function applySearchLogicForColumn($query, $column, $searchTerm)
}

// if false was passed, don't search this column
if ($searchLogic == false) {
if ($searchLogic === false) {
return;
}
}
Expand Down Expand Up @@ -90,7 +90,6 @@ public function applySearchLogicForColumn($query, $column, $searchTerm)
break;

default:
return;
break;
}
}
Expand All @@ -101,13 +100,14 @@ public function applySearchLogicForColumn($query, $column, $searchTerm)
*/
public function applyDatatableOrder()
{
if (request()->input('order')) {
if ($this->getRequest()->input('order')) {
// clear any past orderBy rules
$this->query->getQuery()->orders = null;
foreach ((array) request()->input('order') as $order) {
foreach ((array) $this->getRequest()->input('order') as $order) {
$column_number = (int) $order['column'];
$column_direction = (strtolower((string) $order['dir']) == 'asc' ? 'ASC' : 'DESC');
$column = $this->findColumnById($column_number);

if ($column['tableColumn'] && ! isset($column['orderLogic'])) {
if (method_exists($this->model, 'translationEnabled') &&
$this->model->translationEnabled() &&
Expand Down
11 changes: 11 additions & 0 deletions tests/BaseTestClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ protected function makeAnArticleModel(array $attributes = [])
return \Backpack\CRUD\Tests\config\Models\Article::make($attributes);
}

protected function makeAUserModel(array $attributes = [])
{
$attributes = array_merge([
'id' => 1,
'name' => 'user',
'email' => 'user@email.com',
], $attributes);

return \Backpack\CRUD\Tests\config\Models\User::make($attributes);
}

// allow us to run crud panel private/protected methods like `inferFieldTypeFromDbColumnType`
public function invokeMethod(&$object, $methodName, array $parameters = [])
{
Expand Down
321 changes: 321 additions & 0 deletions tests/Unit/CrudPanel/CrudPanelSearchTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
<?php

namespace Backpack\CRUD\Tests\Unit\CrudPanel;

use Backpack\CRUD\Tests\config\Models\User;
use Backpack\CRUD\Tests\config\Models\UserWithTranslations;
use PHPUnit\Framework\Attributes\DataProvider;

/**
* @covers Backpack\CRUD\app\Library\CrudPanel\Traits\Search
*/
class CrudPanelSearchTest extends \Backpack\CRUD\Tests\config\CrudPanel\BaseCrudPanel
{
private string $expectedDefaultColumnValue = '<span>'.PHP_EOL.' user'.PHP_EOL.' </span>';

public function setUp(): void
{
parent::setUp();
$this->crudPanel->setModel(User::class);
}

#[DataProvider('columnsDefaultSearchLogic')]
public function testItCanApplyCustomSearchLogicOnColumns($searchTerm, $columnType, $resultSql)
{
$this->crudPanel->addColumn([
'name' => 'test',
'type' => $columnType,
'searchLogic' => $columnType,
'tableColumn' => true,
'entity' => $columnType === 'select' ? 'accountDetails' : ($columnType === 'select_multiple' ? 'articles' : false),
'relation_type' => $columnType === 'select' ? 'HasOne' : ($columnType === 'select_multiple' ? 'HasMany' : false),
]);

$this->crudPanel->applySearchTerm($searchTerm);

$this->assertEquals($resultSql, $this->crudPanel->query->toRawSql());
}

public function testItDoesNotAttemptToSearchTheColumnIfSearchLogicIsDisabled()
{
$this->crudPanel->addColumn([
'name' => 'test',
'type' => 'text',
'searchLogic' => false,
'tableColumn' => true,
]);

$this->crudPanel->applySearchTerm('test');

$this->assertEquals('select * from "users"', $this->crudPanel->query->toRawSql());
}

public function testItDoesNotAttemptToApplyDefaultLogicIfColumnIsNotATableColumn()
{
$this->crudPanel->addColumn([
'name' => 'test',
'type' => 'text',
'searchLogic' => 'text',
'tableColumn' => false,
]);

$this->crudPanel->applySearchTerm('test');

$this->assertEquals('select * from "users"', $this->crudPanel->query->toRawSql());
}

public function testItValidateDateAndDatetimeSearchTermsAndDoesNotApplySearchIfValidationFails()
{
$this->crudPanel->addColumn([
'name' => 'test',
'type' => 'date',
'searchLogic' => 'date',
'tableColumn' => true,
]);

$this->crudPanel->addColumn([
'name' => 'test',
'type' => 'datetime',
'searchLogic' => 'datetime',
'tableColumn' => true,
]);

$this->crudPanel->applySearchTerm('invalid-date');

$this->assertEquals('select * from "users"', $this->crudPanel->query->toRawSql());
}

public function testItCanApplySearchLogicFromClosure()
{
$this->crudPanel->addColumn([
'name' => 'test',
'type' => 'my_custom_type',
'searchLogic' => function ($query, $column, $searchTerm) {
$query->where($column['name'], 'like', "%{$searchTerm}%");
},
'tableColumn' => true,
]);

$this->crudPanel->applySearchTerm('test');

$this->assertEquals('select * from "users" where ("test" like \'%test%\')', $this->crudPanel->query->toRawSql());
}

public function testItCanGetAndSetPersistentTable()
{
$this->crudPanel->enablePersistentTable(true);

$this->assertTrue($this->crudPanel->getPersistentTable());

$this->crudPanel->disablePersistentTable();

$this->assertFalse($this->crudPanel->getPersistentTable());
}

public function testItCanGetPersistentTableFromConfig()
{
$this->assertNull($this->crudPanel->getPersistentTable());
}

public function testItCanGetAndSetTheResponsiveTable()
{
$this->crudPanel->enableResponsiveTable(true);

$this->assertTrue($this->crudPanel->getResponsiveTable());

$this->crudPanel->disableResponsiveTable();

$this->assertFalse($this->crudPanel->getResponsiveTable());
}

public function testItCanGetPersistentTableDurationFromOperationSetting()
{
$this->crudPanel->setOperationSetting('persistentTableDuration', 10);

$this->assertEquals(10, $this->crudPanel->getPersistentTableDuration());
}

public function testItCanGetPersistentTableDurantionFromConfig()
{
$this->assertEquals(false, $this->crudPanel->getPersistentTableDuration());

config(['backpack.crud.operations.list.persistentTableDuration' => 10]);

$this->assertEquals(10, $this->crudPanel->getPersistentTableDuration());
}

public function testItCanGetResponsiveTableFromConfig()
{
$this->assertEquals(false, $this->crudPanel->getResponsiveTable());

config(['backpack.crud.operations.list.responsiveTable' => true]);

$this->assertTrue($this->crudPanel->getResponsiveTable());
}

public function testItCanGetTheRenderedViewsForTheColumns()
{
$this->crudPanel->addColumn([
'name' => 'name',
'type' => 'test',
]);

$entries = [$this->makeAUserModel()];

$rowColumnsHtml = trim($this->crudPanel->getEntriesAsJsonForDatatables($entries, 1, 0)['data'][0][0]);

$this->assertEquals($this->expectedDefaultColumnValue, $rowColumnsHtml);
}

public function testItRendersTheDetailsRow()
{
$this->crudPanel->addColumn([
'name' => 'name',
'type' => 'test',
]);

$this->crudPanel->setOperationSetting('detailsRow', true);
$entries = [$this->makeAUserModel()];

$rowColumnsHtml = $this->crudPanel->getEntriesAsJsonForDatatables($entries, 1, 0)['data'][0][0];

$this->assertStringContainsString('details-row-button', $rowColumnsHtml);
}

public function testItRendersTheBulkActions()
{
$this->crudPanel->addColumn([
'name' => 'name',
'type' => 'test',
]);

$this->crudPanel->setOperationSetting('bulkActions', true);
$entries = [$this->makeAUserModel()];

$rowColumnsHtml = $this->crudPanel->getEntriesAsJsonForDatatables($entries, 1, 0)['data'][0][0];

$this->assertStringContainsString('crud_bulk_actions_line_checkbox', $rowColumnsHtml);
}

public function testItRendersTheLineStackButtons()
{
$this->crudPanel->addColumn([
'name' => 'name',
'type' => 'test',
]);

$this->crudPanel->button('test')->stack('line')->type('view')->content('backpack.theme-coreuiv2::buttons.test');
$entries = [$this->makeAUserModel()];

$rowColumnsHtml = $this->crudPanel->getEntriesAsJsonForDatatables($entries, 1, 0)['data'][0][1];

$this->assertStringContainsString('btn-secondary', $rowColumnsHtml);
}

public function testItAppliesCustomOrderByPrimaryKeyForDatatables()
{
$this->crudPanel->applyDatatableOrder();

$this->assertEquals('select * from "users" order by "id" desc', $this->crudPanel->query->toRawSql());
}

public function testItCanApplyACustomSearchLogic()
{
$this->crudPanel->addColumn([
'name' => 'name',
'type' => 'text',
'tableColumn' => true,
'orderLogic' => function ($query, $column, $searchTerm) {
$query->orderBy('name', 'asc');
},
]);

$this->setupUserCreateRequest();
$this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]);

$this->crudPanel->applyDatatableOrder();

$this->assertEquals('select * from "users" order by "name" asc, "id" desc', $this->crudPanel->query->toRawSql());
}

public function testItDoesNotReplacePrimaryKeyIfItAlreadyExists()
{
$this->crudPanel->addColumn([
'name' => 'name',
'type' => 'text',
'tableColumn' => true,
'orderLogic' => function ($query, $column, $searchTerm) {
$query->orderBy('id', 'asc');
},
]);

$this->setupUserCreateRequest();
$this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]);

$this->crudPanel->applyDatatableOrder();

$this->assertEquals('select * from "users" order by "id" asc', $this->crudPanel->query->toRawSql());
}

public function testItCanApplyDatatableOrderFromRequest()
{
$this->crudPanel->addColumn([
'name' => 'name',
'type' => 'test',
'tableColumn' => true,
]);
$this->setupUserCreateRequest();
$this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]);

$this->crudPanel->applyDatatableOrder();

$this->assertEquals('select * from "users" order by "name" asc, "id" desc', $this->crudPanel->query->toRawSql());
}

public function testItCanApplySearchLogicForTranslatableJsonColumns()
{
$this->crudPanel->setModel(UserWithTranslations::class);

$this->crudPanel->addColumn([
'name' => 'json',
'type' => 'json',
'tableColumn' => true,
]);
$this->setupUserCreateRequest();
$this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]);

$this->crudPanel->applyDatatableOrder();

$this->assertEquals('select * from "users" order by json_extract("json", \'$."en"\') asc, "id" desc', $this->crudPanel->query->toRawSql());
}

public function testItCanApplySearchLogicForTranslatableColumns()
{
$this->crudPanel->setModel(UserWithTranslations::class);

$this->crudPanel->addColumn([
'name' => 'name',
'type' => 'text',
'tableColumn' => true,
]);
$this->setupUserCreateRequest();
$this->crudPanel->getRequest()->merge(['order' => [['column' => 0, 'dir' => 'asc']]]);

$this->crudPanel->applyDatatableOrder();

$this->assertEquals('select * from "users" order by "name" asc, "id" desc', $this->crudPanel->query->toRawSql());
}

public static function columnsDefaultSearchLogic()
{
return [
['test', 'text', 'select * from "users" where ("users"."test" like \'%test%\')'],
['test', 'email', 'select * from "users" where ("users"."test" like \'%test%\')'],
['test', 'textarea', 'select * from "users" where ("users"."test" like \'%test%\')'],
['2023-12-24', 'date', 'select * from "users" where (strftime(\'%Y-%m-%d\', "users"."test") = cast(\'2023-12-24\' as text))'],
['2023-12-24', 'datetime', 'select * from "users" where (strftime(\'%Y-%m-%d\', "users"."test") = cast(\'2023-12-24\' as text))'],
['test', 'select', 'select * from "users" where (exists (select * from "account_details" where "users"."id" = "account_details"."user_id" and "account_details"."nickname" like \'%test%\'))'],
['test', 'select_multiple', 'select * from "users" where (exists (select * from "articles" where "users"."id" = "articles"."user_id" and "articles"."content" like \'%test%\'))'],
];
}
}
Loading

0 comments on commit 89f4c31

Please sign in to comment.