Skip to content
This repository was archived by the owner on Jun 29, 2021. It is now read-only.

Commit 1784a7d

Browse files
author
José Postiga
committed
feat(Links): add index endpoint
1 parent b92a0f3 commit 1784a7d

File tree

7 files changed

+156
-0
lines changed

7 files changed

+156
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace Domains\Links\Controllers;
4+
5+
use App\Http\Controllers\Controller;
6+
use Domains\Links\Models\Link;
7+
use Domains\Links\Resources\LinkResource;
8+
use Illuminate\Database\Eloquent\Builder;
9+
use Illuminate\Http\Request;
10+
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
11+
12+
class LinksIndexController extends Controller
13+
{
14+
private Link $links;
15+
16+
public function __construct(Link $links)
17+
{
18+
$this->links = $links;
19+
}
20+
21+
public function __invoke(Request $request): AnonymousResourceCollection
22+
{
23+
$links = $this->links
24+
->when($request->input('include'), static function (Builder $query, string $includes) {
25+
return $query->with(
26+
explode(',', $includes)
27+
);
28+
})
29+
->approved()
30+
->simplePaginate();
31+
32+
return LinkResource::collection($links);
33+
}
34+
}

domains/Links/Database/Factories/LinkFactory.php

+12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
use Domains\Links\Models\Link;
4+
use Domains\Tags\Models\Tag;
45
use Illuminate\Database\Eloquent\Factory;
56
use Illuminate\Http\UploadedFile;
67
use Illuminate\Support\Carbon;
@@ -15,3 +16,14 @@
1516
'created_at' => Carbon::now(),
1617
'approved_at' => null,
1718
]);
19+
20+
$factory->afterCreating(Link::class, static function (Link $link) {
21+
$link->tags()
22+
->attach(
23+
factory(Tag::class)->create()
24+
);
25+
});
26+
27+
$factory->state(Link::class, 'approved', static fn () => [
28+
'approved_at' => Carbon::now(),
29+
]);

domains/Links/Models/Link.php

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Domains\Links\Models;
44

55
use Domains\Tags\Models\Tag;
6+
use Illuminate\Database\Eloquent\Builder;
67
use Illuminate\Database\Eloquent\Model;
78
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
89
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -23,4 +24,9 @@ public function tags(): BelongsToMany
2324
{
2425
return $this->belongsToMany(Tag::class);
2526
}
27+
28+
public function scopeApproved(Builder $query): Builder
29+
{
30+
return $query->whereNotNull('approved_at');
31+
}
2632
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Domains\Links\Resources;
4+
5+
use Domains\Tags\Resources\TagResource;
6+
use Illuminate\Http\Resources\Json\JsonResource;
7+
8+
class LinkResource extends JsonResource
9+
{
10+
public function toArray($request): array
11+
{
12+
return [
13+
'id' => $this->id,
14+
'link' => $this->link,
15+
'description' => $this->description,
16+
'author_name' => $this->author_name,
17+
'author_email' => $this->author_email,
18+
'cover_image' => $this->cover_image,
19+
'created_at' => $this->created_at,
20+
'updated_at' => $this->updated_at,
21+
'approved_at' => $this->approved_at,
22+
'tags' => TagResource::collection(
23+
$this->whenLoaded('tags')
24+
),
25+
];
26+
}
27+
}

domains/Links/Routes/api.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
use Domains\Links\Controllers\LinksIndexController;
34
use Domains\Links\Controllers\LinksStoreController;
45

6+
Route::get('/links', LinksIndexController::class)->name('links.index');
57
Route::post('/links', LinksStoreController::class)->name('links.store');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace Domains\Links\Tests\Feature;
4+
5+
use Domains\Links\Models\Link;
6+
use Illuminate\Foundation\Testing\RefreshDatabase;
7+
use Tests\TestCase;
8+
9+
class LinksIndexTest extends TestCase
10+
{
11+
use RefreshDatabase;
12+
13+
protected function setUp(): void
14+
{
15+
parent::setUp();
16+
17+
factory(Link::class, 20)->state('approved')->create();
18+
}
19+
20+
/** @test */
21+
public function it_lists_resources(): void
22+
{
23+
$this->getJson('/links')
24+
->assertSuccessful()
25+
->assertJsonStructure([
26+
'data' => [
27+
[
28+
'id', 'link', 'description', 'cover_image', 'author_name', 'author_email', 'created_at',
29+
],
30+
],
31+
'links' => [
32+
'first', 'last', 'prev', 'next',
33+
],
34+
]);
35+
}
36+
37+
/** @test */
38+
public function it_includes_tags_relation(): void
39+
{
40+
$this->getJson('/links?include=tags')
41+
->assertSuccessful()
42+
->assertJsonStructure([
43+
'data' => [
44+
[
45+
'tags',
46+
],
47+
],
48+
])
49+
->assertJsonCount(1, 'data.0.tags');
50+
}
51+
52+
/** @test */
53+
public function it_doesnt_include_relations_if_not_required(): void
54+
{
55+
$response = $this->getJson('/links')
56+
->assertSuccessful()
57+
->decodeResponseJson();
58+
59+
$this->assertArrayNotHasKey('tags', $response['data'][0]);
60+
}
61+
62+
/** @test */
63+
public function it_supports_pagination_navigation(): void
64+
{
65+
$this->getJson('/links?page=2')
66+
->assertSuccessful()
67+
->assertJsonPath('meta.current_page', 2);
68+
}
69+
}

domains/Links/Tests/Unit/LinkModelTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,10 @@ public function it_has_tags_relation(): void
6262
{
6363
$this->assertInstanceOf(Tag::class, $this->model->tags()->getModel());
6464
}
65+
66+
/** @test */
67+
public function it_has_approved_scope(): void
68+
{
69+
$this->assertTrue(method_exists($this->model, 'scopeApproved'));
70+
}
6571
}

0 commit comments

Comments
 (0)