create(); DocumentCategory::factory()->create([ 'slug' => 'organization-public-disclosure', 'name' => '組織公開資訊', 'default_access_level' => 'public', ]); $articleWithAttachment = Article::factory()->create([ 'title' => '舊版章程 PDF', 'slug' => 'legacy-charter', 'content_type' => Article::CONTENT_TYPE_DOCUMENT, 'status' => Article::STATUS_PUBLISHED, 'access_level' => Article::ACCESS_LEVEL_PUBLIC, 'summary' => '舊版章程摘要', 'content' => '舊版章程內容', 'created_by_user_id' => $user->id, 'last_updated_by_user_id' => $user->id, ]); Storage::disk('public')->put('articles/attachments/legacy-charter.pdf', '%PDF-1.4 test'); ArticleAttachment::create([ 'article_id' => $articleWithAttachment->id, 'file_path' => 'articles/attachments/legacy-charter.pdf', 'original_filename' => 'legacy-charter.pdf', 'mime_type' => 'application/pdf', 'file_size' => 13, 'description' => '舊版附件', ]); $articleWithoutAttachment = Article::factory()->create([ 'title' => '純文字福利資源', 'slug' => 'legacy-welfare-links', 'content_type' => Article::CONTENT_TYPE_DOCUMENT, 'status' => Article::STATUS_PUBLISHED, 'access_level' => Article::ACCESS_LEVEL_PUBLIC, 'summary' => '福利連結摘要', 'content' => "第一行\n第二行", 'created_by_user_id' => $user->id, 'last_updated_by_user_id' => $user->id, ]); $this->artisan('articles:import-documents', [ '--fallback-user-id' => $user->id, ])->assertExitCode(0); $this->assertDatabaseCount('documents', 2); $importedFromAttachment = Document::where('title', $articleWithAttachment->title)->firstOrFail(); $this->assertSame('public', $importedFromAttachment->access_level); $this->assertSame('active', $importedFromAttachment->status); $this->assertSame(1, $importedFromAttachment->version_count); $this->assertNotNull($importedFromAttachment->current_version_id); $this->assertTrue($importedFromAttachment->currentVersion()->exists()); $this->assertSame('legacy-charter.pdf', $importedFromAttachment->currentVersion->original_filename); $this->assertTrue(Storage::disk('private')->exists($importedFromAttachment->currentVersion->file_path)); $importedFromMarkdown = Document::where('title', $articleWithoutAttachment->title)->firstOrFail(); $this->assertSame(1, $importedFromMarkdown->version_count); $this->assertNotNull($importedFromMarkdown->current_version_id); $this->assertSame('text/markdown', $importedFromMarkdown->currentVersion->mime_type); $this->assertSame('legacy-welfare-links.md', $importedFromMarkdown->currentVersion->original_filename); $this->assertTrue(Storage::disk('private')->exists($importedFromMarkdown->currentVersion->file_path)); $markdown = Storage::disk('private')->get($importedFromMarkdown->currentVersion->file_path); $this->assertStringContainsString('# 純文字福利資源', $markdown); $this->assertStringContainsString('Source article slug: `legacy-welfare-links`', $markdown); // Idempotency check $this->artisan('articles:import-documents', [ '--fallback-user-id' => $user->id, ])->assertExitCode(0); $this->assertDatabaseCount('documents', 2); } public function test_it_can_archive_source_articles_after_import(): void { Storage::fake('public'); Storage::fake('private'); $user = User::factory()->create(); DocumentCategory::factory()->create([ 'slug' => 'organization-public-disclosure', 'name' => '組織公開資訊', 'default_access_level' => 'public', ]); $article = Article::factory()->create([ 'title' => '待封存來源文章', 'slug' => 'legacy-archive-me', 'content_type' => Article::CONTENT_TYPE_DOCUMENT, 'status' => Article::STATUS_PUBLISHED, 'access_level' => Article::ACCESS_LEVEL_PUBLIC, 'created_by_user_id' => $user->id, 'last_updated_by_user_id' => $user->id, ]); $this->artisan('articles:import-documents', [ '--fallback-user-id' => $user->id, '--mark-archived' => true, ])->assertExitCode(0); $article->refresh(); $this->assertSame(Article::STATUS_ARCHIVED, $article->status); $this->assertNotNull($article->archived_at); $this->assertDatabaseCount('documents', 1); } public function test_it_can_archive_already_imported_source_articles(): void { Storage::fake('public'); Storage::fake('private'); $user = User::factory()->create(); DocumentCategory::factory()->create([ 'slug' => 'organization-public-disclosure', 'name' => '組織公開資訊', 'default_access_level' => 'public', ]); $article = Article::factory()->create([ 'title' => '先匯入後封存', 'slug' => 'legacy-import-then-archive', 'content_type' => Article::CONTENT_TYPE_DOCUMENT, 'status' => Article::STATUS_PUBLISHED, 'access_level' => Article::ACCESS_LEVEL_PUBLIC, 'created_by_user_id' => $user->id, 'last_updated_by_user_id' => $user->id, ]); $this->artisan('articles:import-documents', [ '--fallback-user-id' => $user->id, ])->assertExitCode(0); $this->assertDatabaseCount('documents', 1); $article->refresh(); $this->assertSame(Article::STATUS_PUBLISHED, $article->status); $this->artisan('articles:import-documents', [ '--fallback-user-id' => $user->id, '--mark-archived' => true, ])->assertExitCode(0); $article->refresh(); $this->assertSame(Article::STATUS_ARCHIVED, $article->status); $this->assertNotNull($article->archived_at); $this->assertDatabaseCount('documents', 1); } }