Skip to content

Commit 7390b38

Browse files
committed
test: add tests for force delete and restore functionality in AdminPostsController
1 parent bc35ae3 commit 7390b38

18 files changed

Lines changed: 945 additions & 19 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ use Javaabu\Cms\PostTypes\PostType;
7777
->singularName('Blog Post')
7878
->icon('zmdi-library')
7979
->categoryType('blog-categories')
80-
->features([
80+
->features(
8181
PostTypeFeatures::CATEGORIES,
8282
PostTypeFeatures::IMAGE_GALLERY,
8383
'featured-image',
8484
'excerpt',
8585
'video-link',
86-
]),
86+
),
8787
],
8888

8989
'category_types' => [

config/cms.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@
226226
->singularName('News Article')
227227
->icon('zmdi-assignment')
228228
->categoryType('news-categories')
229-
->features(['image-gallery', 'categories', 'featured-image', 'excerpt'])
229+
->features('image-gallery', 'categories', 'featured-image', 'excerpt')
230230
->description('Latest news and updates')
231231
->ogDescription('Stay updated with our latest news'),
232232

@@ -236,7 +236,7 @@
236236
->singularName('Blog Post')
237237
->icon('zmdi-library')
238238
->categoryType('blog-categories')
239-
->features(['image-gallery', 'categories', 'featured-image', 'excerpt'])
239+
->features('image-gallery', 'categories', 'featured-image', 'excerpt')
240240
->description('Blog articles and insights')
241241
->ogDescription('Read our latest blog posts'),
242242

@@ -246,7 +246,7 @@
246246
->singularName('Download')
247247
->icon('zmdi-download')
248248
->categoryType('download-categories')
249-
->features(['documents', 'categories'])
249+
->features('documents', 'categories')
250250
->description('Downloadable files and documents'),
251251

252252
PostType::make('announcements')
@@ -255,7 +255,7 @@
255255
->singularName('Announcement')
256256
->icon('zmdi-alert-triangle')
257257
->categoryType('announcement-categories')
258-
->features(['documents', 'document-number', 'expireable', 'categories', 'reference-no'])
258+
->features('documents', 'document-number', 'expireable', 'categories', 'reference-no')
259259
->description('Important announcements and notices'),
260260

261261
PostType::make('publications')
@@ -264,7 +264,7 @@
264264
->singularName('Publication')
265265
->icon('zmdi-book')
266266
->categoryType('publication-categories')
267-
->features(['documents', 'categories', 'featured-image'])
267+
->features('documents', 'categories', 'featured-image')
268268
->description('Published documents and materials'),
269269

270270
PostType::make('jobs')
@@ -273,7 +273,7 @@
273273
->singularName('Job')
274274
->icon('zmdi-case')
275275
->categoryType('job-categories')
276-
->features(['documents', 'document-number', 'expireable', 'categories', 'reference-no'])
276+
->features('documents', 'document-number', 'expireable', 'categories', 'reference-no')
277277
->description('Job openings and career opportunities'),
278278

279279
PostType::make('galleries')
@@ -282,7 +282,7 @@
282282
->singularName('Gallery')
283283
->icon('zmdi-collection-image-o')
284284
->categoryType('gallery-categories')
285-
->features(['image-gallery', 'format', 'categories'])
285+
->features('image-gallery', 'format', 'categories')
286286
->description('Photo and video galleries'),
287287

288288
PostType::make('tenders')
@@ -291,7 +291,7 @@
291291
->singularName('Tender')
292292
->icon('zmdi-assignment')
293293
->categoryType('tender-categories')
294-
->features(['documents', 'document-number', 'expireable', 'categories', 'reference-no', 'gazette-link'])
294+
->features('documents', 'document-number', 'expireable', 'categories', 'reference-no', 'gazette-link')
295295
->description('Tender notices and bids'),
296296

297297
PostType::make('reports')
@@ -300,15 +300,15 @@
300300
->singularName('Report')
301301
->icon('zmdi-collection-text')
302302
->categoryType('report-categories')
303-
->features(['documents', 'categories', 'document-number'])
303+
->features('documents', 'categories', 'document-number')
304304
->description('Reports and statistics'),
305305

306306
PostType::make('pages')
307307
->name('Pages')
308308
->nameDv('ސްފްޙާތައް')
309309
->singularName('Page')
310310
->icon('zmdi-file')
311-
->features(['page-style'])
311+
->features('page-style')
312312
->description('Static pages and content'),
313313
],
314314

src/Actions/Posts/CreatePostAction.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
class CreatePostAction {
99
public function handle(PostRequest $request)
1010
{
11-
$post = Post::create($request->validated());
11+
$validated = $request->validated();
12+
13+
$post = new Post($validated);
14+
if (array_key_exists('lang', $validated)) {
15+
$post->lang = $validated['lang'];
16+
}
17+
$post->save();
1218

1319
return $post;
1420
}

src/Actions/Posts/EditPostAction.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
<?php
22

3+
namespace Javaabu\Cms\Actions\Posts;
4+
35
use Javaabu\Cms\Http\Requests\PostRequest;
46
use Javaabu\Cms\Models\Post;
57

6-
class EditPostAction {
8+
class EditPostAction
9+
{
710
public function handle(Post $post, PostRequest $request)
811
{
912
$post->update($request->validated());

src/PostTypes/PostType.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,21 @@ public function feature(string|PostTypeFeatures $feature, bool|string $value = t
7979
return $this;
8080
}
8181

82-
public function features(array $features): self
82+
public function features(array|string|PostTypeFeatures ...$features): self
8383
{
8484
foreach ($features as $key => $value) {
85+
if (is_array($value)) {
86+
foreach ($value as $arrayKey => $arrayValue) {
87+
if (is_int($arrayKey)) {
88+
$this->feature($arrayValue, true);
89+
continue;
90+
}
91+
92+
$this->feature($arrayKey, $arrayValue);
93+
}
94+
continue;
95+
}
96+
8597
if (is_int($key)) {
8698
$this->feature($value, true);
8799
continue;

tests/Feature/Controllers/AdminPostsControllerTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,36 @@ public function posts_bulk_throws_when_view_any_authorization_fails(): void
8787
$controller->bulk($type, $request);
8888
}
8989

90+
#[Test]
91+
public function posts_force_delete_returns_json_true_on_success(): void
92+
{
93+
$type = $this->createPostType('alerts');
94+
$post = $this->createPost($type);
95+
$post->delete();
96+
97+
$request = Request::create('/admin/posts/force-delete', 'DELETE', [], [], [], ['HTTP_ACCEPT' => 'application/json']);
98+
$response = app(AdminPostsController::class)->forceDelete($type, $post->id, $request);
99+
100+
$this->assertSame(200, $response->status());
101+
$this->assertSame('true', $response->getContent());
102+
$this->assertDatabaseMissing('posts', ['id' => $post->id]);
103+
}
104+
105+
#[Test]
106+
public function posts_restore_returns_json_true_on_success(): void
107+
{
108+
$type = $this->createPostType('alerts');
109+
$post = $this->createPost($type);
110+
$post->delete();
111+
112+
$request = Request::create('/admin/posts/restore', 'PATCH', [], [], [], ['HTTP_ACCEPT' => 'application/json']);
113+
$response = app(AdminPostsController::class)->restore($type, $post->id, $request);
114+
115+
$this->assertSame(200, $response->status());
116+
$this->assertSame('true', $response->getContent());
117+
$this->assertDatabaseHas('posts', ['id' => $post->id, 'deleted_at' => null]);
118+
}
119+
90120
private function resolvePostForTypeOrFail(PostType $postType, int $postId): Post
91121
{
92122
return Post::query()->where('type', $postType->slug)->findOrFail($postId);
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
namespace Javaabu\Cms\Tests\Feature\Controllers;
4+
5+
use Illuminate\Auth\Access\AuthorizationException;
6+
use Illuminate\Foundation\Testing\RefreshDatabase;
7+
use Illuminate\Http\Request;
8+
use Illuminate\Support\Facades\Gate;
9+
use Illuminate\Validation\ValidationException;
10+
use Javaabu\Cms\Models\Category;
11+
use Javaabu\Cms\Models\CategoryType;
12+
use Javaabu\Cms\Tests\TestCase;
13+
use Javaabu\Cms\Translatable\Http\Controllers\Admin\CategoriesController as TranslatableAdminCategoriesController;
14+
use PHPUnit\Framework\Attributes\Test;
15+
16+
class TranslatableAdminCategoriesControllerTest extends TestCase
17+
{
18+
use RefreshDatabase;
19+
20+
public function setUp(): void
21+
{
22+
parent::setUp();
23+
Gate::shouldReceive('authorize')->andReturn(true);
24+
}
25+
26+
#[Test]
27+
public function destroy_returns_json_true_on_success(): void
28+
{
29+
$type = $this->createCategoryType('blog-categories');
30+
$category = $this->createCategory($type);
31+
32+
$request = Request::create('/admin/translatable/categories/delete', 'DELETE', [], [], [], ['HTTP_ACCEPT' => 'application/json']);
33+
$response = app(TranslatableAdminCategoriesController::class)->destroy('en', $type, $category, $request);
34+
35+
$this->assertSame(200, $response->status());
36+
$this->assertSame('true', $response->getContent());
37+
$this->assertDatabaseMissing('categories', ['id' => $category->id]);
38+
}
39+
40+
#[Test]
41+
public function bulk_rejects_category_ids_from_other_type(): void
42+
{
43+
$blogType = $this->createCategoryType('blog-categories');
44+
$staffType = $this->createCategoryType('staff-categories');
45+
$staffCategory = $this->createCategory($staffType);
46+
47+
$this->expectException(ValidationException::class);
48+
49+
$request = Request::create('/admin/translatable/categories/bulk', 'PATCH', [
50+
'action' => 'delete',
51+
'categories' => [$staffCategory->id],
52+
]);
53+
54+
app(TranslatableAdminCategoriesController::class)->bulk('en', $blogType, $request);
55+
}
56+
57+
#[Test]
58+
public function bulk_throws_when_view_any_authorization_fails(): void
59+
{
60+
$type = $this->createCategoryType('blog-categories');
61+
$controller = \Mockery::mock(TranslatableAdminCategoriesController::class)->makePartial();
62+
$controller->shouldReceive('authorize')->once()->andThrow(new AuthorizationException());
63+
64+
$this->expectException(AuthorizationException::class);
65+
66+
$request = Request::create('/admin/translatable/categories/bulk', 'PATCH', [
67+
'action' => 'delete',
68+
'categories' => [],
69+
]);
70+
71+
$controller->bulk('en', $type, $request);
72+
}
73+
74+
private function createCategoryType(string $slug): CategoryType
75+
{
76+
$categoryType = new CategoryType([
77+
'name' => ucfirst(str_replace('-', ' ', $slug)),
78+
'singular_name' => ucfirst(rtrim(str_replace('-', ' ', $slug), 's')),
79+
'slug' => $slug,
80+
]);
81+
$categoryType->lang = 'en';
82+
$categoryType->save();
83+
return $categoryType;
84+
}
85+
86+
private function createCategory(CategoryType $type): Category
87+
{
88+
$category = new Category([
89+
'name' => 'Category ' . fake()->unique()->numberBetween(1, 99999),
90+
'slug' => 'category-' . fake()->unique()->numberBetween(1, 99999),
91+
]);
92+
$category->type_id = $type->id;
93+
$category->lang = 'en';
94+
$category->save();
95+
return $category;
96+
}
97+
}
98+

0 commit comments

Comments
 (0)