126 lines
4.2 KiB
PHP
126 lines
4.2 KiB
PHP
<?php
|
|
|
|
use App\Services\ArtworkService;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
function dynamicRoutingEmptyPaginator(string $path = '/'): LengthAwarePaginator
|
|
{
|
|
return (new LengthAwarePaginator(collect(), 0, 20, 1))->setPath($path);
|
|
}
|
|
|
|
beforeEach(function () {
|
|
$artworksMock = \Mockery::mock(ArtworkService::class);
|
|
$artworksMock->shouldReceive('getFeaturedArtworks')->andReturn(dynamicRoutingEmptyPaginator('/'))->byDefault();
|
|
$artworksMock->shouldReceive('getLatestArtworks')->andReturn(collect())->byDefault();
|
|
$this->app->instance(ArtworkService::class, $artworksMock);
|
|
|
|
$this->contentTypeId = DB::table('content_types')->insertGetId([
|
|
'name' => 'Digital Art',
|
|
'slug' => 'digital-art',
|
|
'description' => 'Digital art uploads',
|
|
'order' => 1,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
DB::table('content_type_slug_histories')->insert([
|
|
'content_type_id' => $this->contentTypeId,
|
|
'old_slug' => 'concept-art',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
});
|
|
|
|
it('redirects old explore content type slugs to the current canonical slug', function () {
|
|
$this->get('/explore/concept-art?sort=latest')
|
|
->assertRedirect('/digital-art?sort=latest');
|
|
});
|
|
|
|
it('redirects old rss explore slugs while preserving mode and query string', function () {
|
|
$this->get('/rss/explore/concept-art/trending?limit=10')
|
|
->assertRedirect('/rss/explore/digital-art/trending?limit=10');
|
|
});
|
|
|
|
it('redirects old artwork paths to the current canonical content type slug', function () {
|
|
$this->get('/concept-art/fantasy/castle-sunrise')
|
|
->assertRedirect('/digital-art/fantasy/castle-sunrise');
|
|
});
|
|
|
|
it('returns 404 for unknown dynamic content type slugs', function () {
|
|
$this->get('/made-up-content-type')
|
|
->assertNotFound();
|
|
});
|
|
|
|
it('lists resolver-backed content types on the rss feeds page', function () {
|
|
$this->get('/rss-feeds')
|
|
->assertOk()
|
|
->assertSee('/rss/explore/digital-art', false)
|
|
->assertSee('Digital Art');
|
|
});
|
|
|
|
it('keeps static routes ahead of dynamic content type routes even with bad data', function () {
|
|
DB::table('content_types')->insert([
|
|
'name' => 'RSS Collision',
|
|
'slug' => 'rss',
|
|
'description' => 'Invalid but useful for route-order regression coverage',
|
|
'order' => 99,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
$this->get('/rss')
|
|
->assertOk()
|
|
->assertHeader('Content-Type', 'application/rss+xml; charset=utf-8');
|
|
});
|
|
|
|
it('blocks reserved content type slugs in the admin save flow', function () {
|
|
$admin = User::factory()->create(['role' => 'admin']);
|
|
|
|
$this->withoutMiddleware();
|
|
|
|
$this->actingAs($admin)
|
|
->post(route('admin.cp.artworks.content-types.store'), [
|
|
'name' => 'Reserved Help',
|
|
'slug' => 'help',
|
|
'description' => 'Should be rejected',
|
|
'order' => 1,
|
|
])
|
|
->assertStatus(422)
|
|
->assertSeeText('This content type slug is reserved by the public routing layer.');
|
|
});
|
|
|
|
it('allows updating an existing content type that already uses the same reserved slug', function () {
|
|
$admin = User::factory()->create(['role' => 'admin']);
|
|
|
|
$contentTypeId = DB::table('content_types')->insertGetId([
|
|
'name' => 'Members',
|
|
'slug' => 'members',
|
|
'description' => 'Legacy reserved slug still in use',
|
|
'order' => 5,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
$this->withoutMiddleware();
|
|
|
|
$this->actingAs($admin)
|
|
->post(route('admin.cp.artworks.content-types.update', ['id' => $contentTypeId]), [
|
|
'name' => 'Members Updated',
|
|
'slug' => 'members',
|
|
'description' => 'Updated without renaming slug',
|
|
'order' => 5,
|
|
])
|
|
->assertRedirect(route('admin.cp.artworks.content-types.main'));
|
|
|
|
$this->assertDatabaseHas('content_types', [
|
|
'id' => $contentTypeId,
|
|
'slug' => 'members',
|
|
'name' => 'Members Updated',
|
|
'description' => 'Updated without renaming slug',
|
|
]);
|
|
}); |