wip: article AI polish, category SEO fields, cover generator, membership plan seeder
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Domain\Ai\Jobs\GenerateArticleCoverJob;
|
||||
use App\Domain\Media\ArticleCoverService;
|
||||
use App\Models\Article;
|
||||
use App\Models\Attachment;
|
||||
use App\Models\Category;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ArticleCoverTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected string $attachmentsRoot;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->attachmentsRoot = storage_path('framework/testing/attachments-'.uniqid());
|
||||
File::ensureDirectoryExists($this->attachmentsRoot);
|
||||
|
||||
config([
|
||||
'filesystems.disks.attachments' => [
|
||||
'driver' => 'local',
|
||||
'root' => $this->attachmentsRoot,
|
||||
'url' => rtrim((string) config('app.url'), '/').'/attachments-local',
|
||||
'visibility' => 'public',
|
||||
'throw' => true,
|
||||
],
|
||||
'larablog.attachments_disk' => 'attachments',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
if (isset($this->attachmentsRoot) && is_dir($this->attachmentsRoot)) {
|
||||
File::deleteDirectory($this->attachmentsRoot);
|
||||
}
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_auto_cover_from_markdown_remote_image(): void
|
||||
{
|
||||
$article = $this->makeArticle([
|
||||
'content' => "Hello\n\n\n\nMore text",
|
||||
]);
|
||||
|
||||
app(ArticleCoverService::class)->apply($article, 'auto');
|
||||
$article->refresh();
|
||||
|
||||
$this->assertTrue($article->hasCover());
|
||||
$this->assertSame(ArticleCoverService::SOURCE_CONTENT_IMAGE, $article->cover_source);
|
||||
$this->assertSame('url', $article->cover_disk);
|
||||
$this->assertSame('https://cdn.example.com/hero.jpg', $article->coverUrl());
|
||||
}
|
||||
|
||||
public function test_auto_cover_from_attachment_when_no_body_image(): void
|
||||
{
|
||||
$article = $this->makeArticle(['content' => 'No images here']);
|
||||
|
||||
Attachment::query()->create([
|
||||
'article_id' => $article->id,
|
||||
'disk' => 'attachments',
|
||||
'path' => 'covers/demo.png',
|
||||
'filename' => 'demo.png',
|
||||
'mime' => 'image/png',
|
||||
'size' => 12,
|
||||
'visibility' => Attachment::VISIBILITY_PUBLIC,
|
||||
]);
|
||||
|
||||
(new GenerateArticleCoverJob($article->id, 'auto'))
|
||||
->handle(app(ArticleCoverService::class));
|
||||
|
||||
$article->refresh();
|
||||
$this->assertTrue($article->hasCover());
|
||||
$this->assertSame(ArticleCoverService::SOURCE_ATTACHMENT, $article->cover_source);
|
||||
$this->assertSame('covers/demo.png', $article->cover_path);
|
||||
}
|
||||
|
||||
public function test_generate_strategy_renders_template_cover(): void
|
||||
{
|
||||
$article = $this->makeArticle([
|
||||
'title' => 'Template Cover Smoke',
|
||||
'description' => 'A short blurb for the generated cover card.',
|
||||
]);
|
||||
|
||||
(new GenerateArticleCoverJob($article->id, 'generate'))
|
||||
->handle(app(ArticleCoverService::class));
|
||||
|
||||
$article->refresh();
|
||||
$this->assertTrue($article->hasCover());
|
||||
$this->assertSame(ArticleCoverService::SOURCE_GENERATED, $article->cover_source);
|
||||
$this->assertTrue(Storage::disk('attachments')->exists((string) $article->cover_path));
|
||||
$this->assertGreaterThan(1000, Storage::disk('attachments')->size((string) $article->cover_path));
|
||||
$this->assertSame(1, Attachment::query()->where('article_id', $article->id)->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $overrides
|
||||
*/
|
||||
protected function makeArticle(array $overrides = []): Article
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$category = Category::query()->create(['name' => 'Cover', 'display_order' => 0]);
|
||||
|
||||
return Article::query()->create(array_merge([
|
||||
'category_id' => $category->id,
|
||||
'user_id' => $user->id,
|
||||
'title' => 'Cover post',
|
||||
'content' => 'Body',
|
||||
'content_format' => 'markdown',
|
||||
'published_at' => now()->subMinute(),
|
||||
'visible' => true,
|
||||
], $overrides));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user