202 lines
7.5 KiB
PHP
202 lines
7.5 KiB
PHP
<?php
|
|
|
|
use App\Models\Artwork;
|
|
use App\Models\Category;
|
|
use App\Models\ContentType;
|
|
use App\Models\Tag;
|
|
use App\Models\User;
|
|
use App\Support\Seo\SeoFactory;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Str;
|
|
use Inertia\Testing\AssertableInertia;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('renders JSON-LD structured data on published artwork page', function () {
|
|
$user = User::factory()->create(['name' => 'Schema Author']);
|
|
|
|
$contentType = ContentType::create([
|
|
'name' => 'Photography',
|
|
'slug' => 'photography',
|
|
'description' => 'Photography content',
|
|
]);
|
|
|
|
$category = Category::create([
|
|
'content_type_id' => $contentType->id,
|
|
'parent_id' => null,
|
|
'name' => 'Abstract',
|
|
'slug' => 'abstract-' . Str::lower(Str::random(5)),
|
|
'description' => 'Abstract works',
|
|
'is_active' => true,
|
|
'sort_order' => 0,
|
|
]);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'user_id' => $user->id,
|
|
'title' => 'Schema Ready Artwork',
|
|
'slug' => 'schema-ready-artwork',
|
|
'description' => 'Artwork description for schema test.',
|
|
'mime_type' => 'image/jpeg',
|
|
'published_at' => now()->subMinute(),
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
]);
|
|
|
|
$artwork->categories()->attach($category->id);
|
|
|
|
$tagA = Tag::create(['name' => 'neon', 'slug' => 'neon', 'usage_count' => 0, 'is_active' => true]);
|
|
$tagB = Tag::create(['name' => 'city', 'slug' => 'city', 'usage_count' => 0, 'is_active' => true]);
|
|
$artwork->tags()->attach([
|
|
$tagA->id => ['source' => 'user', 'confidence' => 0.9],
|
|
$tagB->id => ['source' => 'user', 'confidence' => 0.8],
|
|
]);
|
|
|
|
$artwork->load(['user', 'tags', 'categories.contentType']);
|
|
|
|
expect(json_encode(app(SeoFactory::class)->artwork(
|
|
$artwork,
|
|
[
|
|
'md' => ['url' => 'https://files.skinbase.org/md/schema-ready.webp', 'width' => 600, 'height' => 400],
|
|
'lg' => ['url' => 'https://files.skinbase.org/lg/schema-ready.webp', 'width' => 1200, 'height' => 800],
|
|
'xl' => ['url' => 'https://files.skinbase.org/xl/schema-ready.webp', 'width' => 2400, 'height' => 1600],
|
|
],
|
|
route('art.show', ['id' => $artwork->id, 'slug' => $artwork->slug]),
|
|
)->toArray()['json_ld'], JSON_UNESCAPED_SLASHES))
|
|
->toContain('"@type":"ImageObject"')
|
|
->toContain('"name":"Schema Ready Artwork"')
|
|
->toContain('"keywords":["neon","city"]');
|
|
});
|
|
|
|
it('builds artwork seo data with breadcrumb and image-license metadata', function () {
|
|
$user = User::factory()->create(['name' => 'Schema Breadcrumb Author']);
|
|
|
|
$contentType = ContentType::create([
|
|
'name' => 'Photography',
|
|
'slug' => 'photography',
|
|
'description' => 'Photography content',
|
|
]);
|
|
|
|
$parentCategory = Category::create([
|
|
'content_type_id' => $contentType->id,
|
|
'parent_id' => null,
|
|
'name' => 'Nature',
|
|
'slug' => 'nature',
|
|
'description' => 'Nature works',
|
|
'is_active' => true,
|
|
'sort_order' => 0,
|
|
]);
|
|
|
|
$category = Category::create([
|
|
'content_type_id' => $contentType->id,
|
|
'parent_id' => $parentCategory->id,
|
|
'name' => 'Forest',
|
|
'slug' => 'forest',
|
|
'description' => 'Forest works',
|
|
'is_active' => true,
|
|
'sort_order' => 1,
|
|
]);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'user_id' => $user->id,
|
|
'title' => 'Licensed Artwork',
|
|
'slug' => 'licensed-artwork',
|
|
'description' => 'Artwork description for breadcrumb schema test.',
|
|
'published_at' => now()->subMinute(),
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
]);
|
|
|
|
$artwork->categories()->attach($category->id);
|
|
$artwork->load(['user', 'tags', 'categories.contentType', 'categories.parent.contentType']);
|
|
$artwork->setAttribute('license_url', 'https://skinbase.org/licenses/custom-license');
|
|
|
|
$seo = app(SeoFactory::class)->artwork(
|
|
$artwork,
|
|
[
|
|
'md' => ['url' => 'https://files.skinbase.org/md/licensed.webp', 'width' => 600, 'height' => 400],
|
|
'lg' => ['url' => 'https://files.skinbase.org/lg/licensed.webp', 'width' => 1200, 'height' => 800],
|
|
'xl' => ['url' => 'https://files.skinbase.org/xl/licensed.webp', 'width' => 2400, 'height' => 1600],
|
|
],
|
|
route('art.show', ['id' => $artwork->id, 'slug' => $artwork->slug]),
|
|
[
|
|
['name' => 'Photography', 'url' => url('/photography')],
|
|
['name' => 'Nature', 'url' => url('/photography/nature')],
|
|
['name' => 'Forest', 'url' => url('/photography/nature/forest')],
|
|
['name' => 'Licensed Artwork', 'url' => route('art.show', ['id' => $artwork->id, 'slug' => $artwork->slug])],
|
|
],
|
|
)->toArray();
|
|
|
|
expect(json_encode($seo['json_ld'], JSON_UNESCAPED_SLASHES))
|
|
->toContain('"@type":"ImageObject"')
|
|
->toContain('"creditText":"Schema Breadcrumb Author"')
|
|
->toContain('"license":"https://skinbase.org/licenses/custom-license"')
|
|
->toContain('"@type":"BreadcrumbList"')
|
|
->toContain('"name":"Photography"')
|
|
->toContain('"name":"Forest"');
|
|
});
|
|
|
|
it('renders JSON-LD via routed artwork show endpoint', function () {
|
|
$user = User::factory()->create(['name' => 'Schema Route Author']);
|
|
|
|
$contentType = ContentType::create([
|
|
'name' => 'Photography',
|
|
'slug' => 'photography',
|
|
'description' => 'Photography content',
|
|
]);
|
|
|
|
$category = Category::create([
|
|
'content_type_id' => $contentType->id,
|
|
'parent_id' => null,
|
|
'name' => 'Abstract',
|
|
'slug' => 'abstract-route',
|
|
'description' => 'Abstract works',
|
|
'is_active' => true,
|
|
'sort_order' => 0,
|
|
]);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'user_id' => $user->id,
|
|
'title' => 'Schema Route Artwork',
|
|
'slug' => 'schema-route-artwork',
|
|
'description' => 'Artwork description for routed schema test.',
|
|
'mime_type' => 'image/png',
|
|
'published_at' => now()->subMinute(),
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
]);
|
|
|
|
$artwork->categories()->attach($category->id);
|
|
|
|
$tag = Tag::create(['name' => 'route-tag', 'slug' => 'route-tag', 'usage_count' => 0, 'is_active' => true]);
|
|
$artwork->tags()->attach([
|
|
$tag->id => ['source' => 'user', 'confidence' => 0.95],
|
|
]);
|
|
|
|
$url = route('artworks.show', [
|
|
'contentTypeSlug' => $contentType->slug,
|
|
'categoryPath' => $category->slug,
|
|
'artwork' => $artwork->slug,
|
|
]);
|
|
|
|
expect($url)->toContain('/photography/abstract-route/schema-route-artwork');
|
|
|
|
$matchedRoute = app('router')->getRoutes()->match(Request::create($url, 'GET'));
|
|
expect($matchedRoute->getName())->toBe('artworks.show');
|
|
|
|
$response = $this->get($url);
|
|
|
|
$response->assertOk()
|
|
->assertInertia(fn (AssertableInertia $page) => $page
|
|
->component('ArtworkPage')
|
|
->where('seo.title', fn (string $title): bool => str_contains($title, 'Schema Route Artwork'))
|
|
->where('seo.json_ld', function ($schemas): bool {
|
|
$json = json_encode($schemas, JSON_UNESCAPED_SLASHES);
|
|
|
|
return str_contains($json, '"@type":"ImageObject"')
|
|
&& str_contains($json, '"@type":"BreadcrumbList"')
|
|
&& str_contains($json, '"name":"Schema Route Artwork"')
|
|
&& str_contains($json, '"keywords":["route-tag"]');
|
|
}));
|
|
});
|