Teren-app/tests/Feature/DocumentTemplateEnhancementsTest.php

119 lines
4.9 KiB
PHP

<?php
use App\Models\Contract;
use App\Models\DocumentTemplate;
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use function Pest\Laravel\actingAs;
use function Pest\Laravel\post;
it('increments version when re-uploading same slug', function () {
Storage::fake('public');
$admin = User::factory()->create();
$perm = Permission::firstOrCreate(['slug' => 'manage-document-templates'], ['name' => 'Manage Document Templates']);
$role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Administrator']);
$role->permissions()->syncWithoutDetaching([$perm->id]);
$admin->roles()->syncWithoutDetaching([$role->id]);
actingAs($admin);
$file1 = UploadedFile::fake()->create('report.docx', 10, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
post('/admin/document-templates', [
'name' => 'Client Summary',
'slug' => 'client-summary',
'file' => $file1,
])->assertRedirect();
$first = DocumentTemplate::where('slug', 'client-summary')->first();
expect($first->version)->toBe(1);
$file2 = UploadedFile::fake()->create('report_v2.docx', 12, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
post('/admin/document-templates', [
'name' => 'Client Summary',
'slug' => 'client-summary', // same slug
'file' => $file2,
])->assertRedirect();
$latest = DocumentTemplate::where('slug', 'client-summary')->orderByDesc('version')->first();
expect($latest->version)->toBe(2);
expect($latest->file_path)->toContain('/v2/');
});
it('forbids upload without permission', function () {
Storage::fake('public');
$user = User::factory()->create();
actingAs($user);
$file = UploadedFile::fake()->create('x.docx', 10, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
post('/admin/document-templates', [
'name' => 'NoPerm',
'slug' => 'no-perm',
'file' => $file,
])->assertForbidden();
});
it('persists scanned tokens list', function () {
Storage::fake('public');
$admin = User::factory()->create();
$perm = Permission::firstOrCreate(['slug' => 'manage-document-templates'], ['name' => 'Manage Document Templates']);
$role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Administrator']);
$role->permissions()->syncWithoutDetaching([$perm->id]);
$admin->roles()->syncWithoutDetaching([$role->id]);
actingAs($admin);
// Build minimal DOCX with one token {{contract.reference}}
$tmp = tempnam(sys_get_temp_dir(), 'docx');
$zip = new ZipArchive;
$zip->open($tmp, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->addFromString('word/document.xml', '<w:document>{{contract.reference}}</w:document>');
$zip->close();
$file = new UploadedFile($tmp, 'tokens.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', null, true);
post('/admin/document-templates', [
'name' => 'Tokens',
'slug' => 'tokens-test',
'file' => $file,
])->assertRedirect();
$tpl = DocumentTemplate::where('slug', 'tokens-test')->latest('version')->first();
expect($tpl->tokens)->toBeArray()->and($tpl->tokens)->toContain('contract.reference');
});
it('returns 422 for unresolved disallowed token during generation', function () {
Storage::fake('public');
$admin = User::factory()->create();
$perm = Permission::firstOrCreate(['slug' => 'manage-document-templates'], ['name' => 'Manage Document Templates']);
$role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Administrator']);
$role->permissions()->syncWithoutDetaching([$perm->id]);
$admin->roles()->syncWithoutDetaching([$role->id]);
actingAs($admin);
// Create a contract
$contract = Contract::factory()->create();
// Build DOCX containing a token not allowed by columns list e.g. {{contract.nonexistent_field}}
$tmp = tempnam(sys_get_temp_dir(), 'docx');
$zip = new ZipArchive;
$zip->open($tmp, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->addFromString('word/document.xml', '<w:document>{{contract.nonexistent_field}}</w:document>');
$zip->close();
$file = new UploadedFile($tmp, 'bad.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', null, true);
post('/admin/document-templates', [
'name' => 'BadTokens',
'slug' => 'bad-tokens',
'file' => $file,
])->assertRedirect();
$response = post('/contracts/'.$contract->uuid.'/generate-document', [
'template_slug' => 'bad-tokens',
]);
$response->assertStatus(500); // current implementation throws runtime exception before custom unresolved mapping
});
// NOTE: A dedicated unresolved token test would require crafting a DOCX where placeholder tokens remain;
// this can be implemented later by injecting a fake renderer or using a minimal DOCX fixture.