create(); $role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Admin']); $user->roles()->sync([$role->id]); $this->actingAs($user); // Minimal docx with custom tokens for number and date $tmp = tempnam(sys_get_temp_dir(), 'doc'); $zip = new \ZipArchive; $zip->open($tmp, \ZipArchive::OVERWRITE); $zip->addFromString('[Content_Types].xml', ''); $zip->addFromString('word/document.xml', '{{custom.total_amount}}|{{custom.due_date}}'); $zip->close(); $bytes = file_get_contents($tmp); $upload = UploadedFile::fake()->createWithContent('typed.docx', $bytes); // Create template $resp = $this->post(route('admin.document-templates.store'), [ 'name' => 'Typed Custom', 'slug' => 'typed-custom', 'file' => $upload, ]); $resp->assertRedirect(); $template = DocumentTemplate::where('slug', 'typed-custom')->orderByDesc('version')->firstOrFail(); $template->meta = [ 'custom_defaults' => [ 'total_amount' => null, 'due_date' => null, ], 'custom_default_types' => [ 'total_amount' => 'number', 'due_date' => 'date', ], ]; $template->formatting_options = [ 'number_decimals' => 2, 'decimal_separator' => ',', 'thousands_separator' => '.', // date format may be controlled via template->date_format or formatting_options['default_date_format'] 'default_date_format' => 'd.m.Y', ]; $template->save(); $contract = Contract::factory()->create(); // Generate with explicit overrides $gen = $this->postJson(route('contracts.generate-document', ['contract' => $contract->uuid]), [ 'template_slug' => 'typed-custom', 'custom' => [ 'total_amount' => '1234.5', 'due_date' => '2025-10-12', ], ]); $gen->assertOk()->assertJson(['status' => 'ok']); $doc = \App\Models\Document::latest('id')->first(); $this->assertNotNull($doc); $this->assertTrue(Storage::disk('public')->exists($doc->path)); // Inspect generated document.xml to assert formatted values exist $path = Storage::disk('public')->path($doc->path); $z = new \ZipArchive; $this->assertTrue($z->open($path) === true); $xml = $z->getFromName('word/document.xml'); $z->close(); $this->assertIsString($xml); // Expect EU formatted number and date $this->assertStringContainsString('1.234,50', $xml); $this->assertStringContainsString('12.10.2025', $xml); } }