-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add charge title autocomplete endpoint (#146)
- Loading branch information
Showing
8 changed files
with
238 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Controller\Charges; | ||
|
||
use App\Controller\AuthAwareController; | ||
use App\Repository\ChargeRepository; | ||
use App\View\ChargeTitlesView; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Spiral\Auth\AuthScope; | ||
use Spiral\Http\ResponseWrapper; | ||
use Spiral\Router\Annotation\Route; | ||
|
||
final class SuggestionsController extends AuthAwareController | ||
{ | ||
public function __construct( | ||
AuthScope $auth, | ||
protected ResponseWrapper $response, | ||
private readonly ChargeRepository $chargeRepository, | ||
private readonly ChargeTitlesView $chargeTitlesView, | ||
) { | ||
parent::__construct($auth); | ||
} | ||
|
||
#[Route(route: '/charges/title/suggestions/<query>', name: 'charges.title.suggestions', methods: 'GET', group: 'auth')] | ||
public function suggestions(string $query = ''): ResponseInterface | ||
{ | ||
return $this->chargeTitlesView->json( | ||
$this->chargeRepository->searchTitle((int) $this->user->id, urldecode($query)) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\View; | ||
|
||
use Spiral\Core\Container\SingletonInterface; | ||
use Spiral\Http\ResponseWrapper; | ||
|
||
class ChargeTitleView implements SingletonInterface | ||
{ | ||
public function __construct( | ||
protected ResponseWrapper $response, | ||
) { | ||
} | ||
|
||
public function map(?array $chargeTitle): ?array | ||
{ | ||
if ($chargeTitle === null || ($chargeTitle['title'] ?? null) === null) { | ||
return null; | ||
} | ||
|
||
return [ | ||
'type' => 'chargeTitle', | ||
'title' => $chargeTitle['title'] ?? null, | ||
'count' => $chargeTitle['count'] ?? 0, | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\View; | ||
|
||
use Psr\Http\Message\ResponseInterface; | ||
use Spiral\Core\Container\SingletonInterface; | ||
use Spiral\Http\ResponseWrapper; | ||
|
||
class ChargeTitlesView implements SingletonInterface | ||
{ | ||
public function __construct( | ||
protected ResponseWrapper $response, | ||
protected ChargeTitleView $chargeTitleView, | ||
) { | ||
} | ||
|
||
public function json(array $titles): ResponseInterface | ||
{ | ||
return $this->response->json([ | ||
'data' => $this->map($titles), | ||
]); | ||
} | ||
|
||
public function map(array $titles): array | ||
{ | ||
return array_map([$this->chargeTitleView, 'map'], $titles); | ||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
tests/Feature/Controller/Charges/SuggestionsControllerTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Feature\Controller\Charges; | ||
|
||
use Tests\DatabaseTransaction; | ||
use Tests\Factories\ChargeFactory; | ||
use Tests\Factories\TagFactory; | ||
use Tests\Factories\UserFactory; | ||
use Tests\Factories\WalletFactory; | ||
use Tests\Fixtures; | ||
use Tests\TestCase; | ||
|
||
class SuggestionsControllerTest extends TestCase implements DatabaseTransaction | ||
{ | ||
protected UserFactory $userFactory; | ||
|
||
protected WalletFactory $walletFactory; | ||
|
||
protected ChargeFactory $chargeFactory; | ||
|
||
protected TagFactory $tagFactory; | ||
|
||
protected function setUp(): void | ||
{ | ||
parent::setUp(); | ||
|
||
$this->userFactory = $this->getContainer()->get(UserFactory::class); | ||
$this->walletFactory = $this->getContainer()->get(WalletFactory::class); | ||
$this->chargeFactory = $this->getContainer()->get(ChargeFactory::class); | ||
} | ||
|
||
public function testSuggestionsRequireAuth() | ||
{ | ||
$query = Fixtures::string(); | ||
|
||
$response = $this->get("/charges/title/suggestions/{$query}"); | ||
|
||
$response->assertUnauthorized(); | ||
} | ||
|
||
public function testSuggestionsReturnSuggestedTitles() | ||
{ | ||
$auth = $this->makeAuth($user = $this->userFactory->create()); | ||
$sharedUser = $this->userFactory->create(); | ||
$otherUser = $this->userFactory->create(); | ||
|
||
$otherWallet = $this->walletFactory->forUser($otherUser)->create(); | ||
|
||
$wallet = WalletFactory::make(); | ||
$wallet->users->add($sharedUser); | ||
$wallet = $this->walletFactory->forUser($user)->create($wallet); | ||
|
||
$chargeUser1 = ChargeFactory::make(); | ||
$chargeUser2 = ChargeFactory::make(); | ||
$chargeUser3 = ChargeFactory::make(); | ||
$chargeUser4 = ChargeFactory::make(); | ||
$chargeUser5 = ChargeFactory::make(); | ||
$chargeUser6 = ChargeFactory::make(); | ||
$chargeSharedUser = ChargeFactory::make(); | ||
$chargeOtherUser = ChargeFactory::make(); | ||
|
||
$chargeUser1->title = 'Charge title 1'; | ||
$chargeUser2->title = 'Charge title 2'; | ||
$chargeUser3->title = 'Other charge title 3'; | ||
$chargeUser4->title = 'Other charge title 4'; | ||
$chargeUser5->title = 'Other charge title 5'; | ||
$chargeUser6->title = 'Other item outside 5'; | ||
$chargeSharedUser->title = 'Charge title shared 1'; | ||
$chargeOtherUser->title = 'Charge title other 1'; | ||
$query = 'charge'; | ||
|
||
$this->chargeFactory->forUser($user)->forWallet($wallet)->create($chargeUser1); | ||
$this->chargeFactory->forUser($user)->forWallet($wallet)->create($chargeUser2); | ||
$this->chargeFactory->forUser($user)->forWallet($wallet)->create($chargeUser3); | ||
$this->chargeFactory->forUser($user)->forWallet($wallet)->create($chargeUser4); | ||
$this->chargeFactory->forUser($user)->forWallet($wallet)->create($chargeUser5); | ||
$this->chargeFactory->forUser($user)->forWallet($wallet)->create($chargeUser6); | ||
$this->chargeFactory->forUser($sharedUser)->forWallet($wallet)->create($chargeSharedUser); | ||
$this->chargeFactory->forUser($otherUser)->forWallet($otherWallet)->create($chargeOtherUser); | ||
|
||
$response = $this->withAuth($auth)->get("/charges/title/suggestions/{$query}"); | ||
|
||
$response->assertOk(); | ||
|
||
$body = $this->getJsonResponseBody($response); | ||
|
||
$this->assertIsArray($body); | ||
$this->assertArrayHasKey('data', $body); | ||
|
||
$this->assertCount(6, $body['data']); | ||
|
||
foreach ([$chargeSharedUser, $chargeUser1, $chargeUser2, $chargeUser3, $chargeUser5, $chargeUser4] as $charge) { | ||
$this->assertArrayContains($charge->title, $body, 'data.*.title'); | ||
} | ||
|
||
foreach ([$chargeUser6, $chargeOtherUser] as $charge) { | ||
$this->assertArrayNotContains($charge->title, $body, 'data.*.title'); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Feature\View; | ||
|
||
use App\View\ChargeTitleView; | ||
use Tests\TestCase; | ||
|
||
class ChargeTitleViewTest extends TestCase | ||
{ | ||
public function testMapEmpty(): void | ||
{ | ||
$view = $this->getContainer()->get(ChargeTitleView::class); | ||
|
||
$this->assertNull($view->map(null)); | ||
} | ||
} |