File: /home/xedaptot/be.naniguide.com/tests/Feature/TemplateModelFeatureTest.php
<?php
/**
* Template model feature tests.
*/
uses(Tests\TestCase::class, Illuminate\Foundation\Testing\DatabaseTransactions::class)
->group('applyTemplateFrom');
use App\Model\Template;
test('template model accepts content attributes', function () {
$template = new Template([
'name' => 'Welcome Email',
'content' => '<html><body><h1>Welcome!</h1></body></html>',
'theme' => 'default',
]);
expect($template->name)->toBe('Welcome Email');
expect($template->content)->toContain('<h1>Welcome!</h1>');
expect($template->theme)->toBe('default');
});
test('template has uid in fillable', function () {
$template = new Template();
$fillable = $template->getFillable();
expect($fillable)->toContain('name');
expect($fillable)->toContain('content');
});
test('applyTemplateFrom copies theme + json + content but not name', function () {
$source = Template::factory()->create([
'theme' => 'extended',
'name' => 'Source',
'content' => '<html><body>SOURCE-MARKER</body></html>',
'json' => '{"name":"PageElement","template":"Page","blocks":[{"name":"hero"}],"formats":{"background_color":"#FF0000"}}',
]);
$target = Template::factory()->create([
'theme' => 'default',
'name' => 'Target',
'content' => '<html><body>ORIGINAL</body></html>',
'json' => Template::DEFAULT_BUILDER_JSON,
]);
// Source has no thumbnail on disk — the copy must no-op cleanly rather
// than throw. This is the path the "Change Theme" flow hits whenever the
// source template was never rendered to disk.
$target->applyTemplateFrom($source);
$fresh = Template::find($target->id);
expect($fresh->theme)->toBe('extended');
expect($fresh->content)->toContain('SOURCE-MARKER');
expect($fresh->json)->toContain('hero');
expect($fresh->name)->toBe('Target'); // name must NOT be overwritten
});
test('applyTemplateFrom copies thumbnail file when source has one', function () {
$source = Template::factory()->create(['name' => 'Source']);
$target = Template::factory()->create(['name' => 'Target']);
// Attach a fake 1×1 PNG to the source template via updateThumbnailFromPath,
// then swap → the target must end up with the same bytes under its own
// thumb path.
$pngBytes = base64_decode(
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='
);
$tmp = tempnam(sys_get_temp_dir(), 'thumb_src_');
file_put_contents($tmp, $pngBytes);
try {
$source->updateThumbnailFromPath($tmp);
$target->applyTemplateFrom($source);
} finally {
if (file_exists($tmp)) @unlink($tmp);
}
$storage = app(\App\Library\Storage\StorageInterface::class);
$targetAsset = \App\Library\Storage\AssetPath::from($target->getThumbPath());
expect($storage->fileExists($targetAsset))->toBeTrue();
expect($storage->getFileContent($targetAsset))->toBe($pngBytes);
});
test('getThumbUrl appends ?v=<updated_at> cache-buster when thumb exists', function () {
$template = Template::factory()->create();
$pngBytes = base64_decode(
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='
);
$tmp = tempnam(sys_get_temp_dir(), 'thumb_cb_');
file_put_contents($tmp, $pngBytes);
try {
$template->updateThumbnailFromPath($tmp);
} finally {
if (file_exists($tmp)) @unlink($tmp);
}
$url = $template->getThumbUrl();
expect($url)->toContain('?v=');
// Version must match the model's updated_at timestamp so the URL changes
// whenever Change Theme re-saves the record (which bumps updated_at).
expect($url)->toContain('v=' . $template->updated_at->timestamp);
});
test('copyThumbnailFrom no-ops when source has no thumbnail on disk', function () {
$source = Template::factory()->create(['name' => 'NoThumb']);
$target = Template::factory()->create(['name' => 'Target']);
// Must not throw — exercises the early-return guard inside copyThumbnailFrom.
$target->copyThumbnailFrom($source);
$storage = app(\App\Library\Storage\StorageInterface::class);
$targetAsset = \App\Library\Storage\AssetPath::from($target->getThumbPath());
expect($storage->fileExists($targetAsset))->toBeFalse();
});