Studio: make grid checkbox rectangular and commit table changes
This commit is contained in:
236
tests/Feature/StudioTest.php
Normal file
236
tests/Feature/StudioTest.php
Normal file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Artwork;
|
||||
use App\Models\ArtworkStats;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* Helper: create an artwork without triggering observers (avoids GREATEST() SQLite issue).
|
||||
*/
|
||||
function studioArtwork(array $attrs = []): Artwork
|
||||
{
|
||||
return Artwork::withoutEvents(fn () => Artwork::factory()->create($attrs));
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
// Register GREATEST() polyfill for SQLite (used by observers on user_statistics)
|
||||
if (DB::connection()->getDriverName() === 'sqlite') {
|
||||
DB::connection()->getPdo()->sqliteCreateFunction('GREATEST', function (...$args) {
|
||||
return max($args);
|
||||
}, -1);
|
||||
}
|
||||
|
||||
$this->user = User::factory()->create();
|
||||
$this->actingAs($this->user);
|
||||
});
|
||||
|
||||
// ── Route Auth Tests ──────────────────────────────────────────────────────────
|
||||
|
||||
test('studio routes require authentication', function () {
|
||||
auth()->logout();
|
||||
|
||||
$routes = [
|
||||
'/studio',
|
||||
'/studio/artworks',
|
||||
'/studio/artworks/drafts',
|
||||
'/studio/artworks/archived',
|
||||
];
|
||||
|
||||
foreach ($routes as $route) {
|
||||
$this->get($route)->assertRedirect('/login');
|
||||
}
|
||||
});
|
||||
|
||||
test('studio dashboard loads for authenticated user', function () {
|
||||
$this->get('/studio')
|
||||
->assertStatus(200);
|
||||
});
|
||||
|
||||
test('studio artworks page loads', function () {
|
||||
$this->get('/studio/artworks')
|
||||
->assertStatus(200);
|
||||
});
|
||||
|
||||
test('studio drafts page loads', function () {
|
||||
$this->get('/studio/artworks/drafts')
|
||||
->assertStatus(200);
|
||||
});
|
||||
|
||||
test('studio archived page loads', function () {
|
||||
$this->get('/studio/artworks/archived')
|
||||
->assertStatus(200);
|
||||
});
|
||||
|
||||
// ── API Tests ─────────────────────────────────────────────────────────────────
|
||||
|
||||
test('studio api requires authentication', function () {
|
||||
auth()->logout();
|
||||
|
||||
$this->getJson('/api/studio/artworks')
|
||||
->assertStatus(401);
|
||||
});
|
||||
|
||||
test('studio api returns artworks for authenticated user', function () {
|
||||
// Create artworks for this user
|
||||
$artwork = studioArtwork([
|
||||
'user_id' => $this->user->id,
|
||||
'is_public' => true,
|
||||
'is_approved' => true,
|
||||
]);
|
||||
|
||||
ArtworkStats::create([
|
||||
'artwork_id' => $artwork->id,
|
||||
'views' => 100,
|
||||
'downloads' => 10,
|
||||
'favorites' => 5,
|
||||
]);
|
||||
|
||||
$this->getJson('/api/studio/artworks')
|
||||
->assertStatus(200)
|
||||
->assertJsonStructure([
|
||||
'data' => [['id', 'title', 'slug', 'views', 'favourites']],
|
||||
'meta' => ['current_page', 'last_page', 'per_page', 'total'],
|
||||
]);
|
||||
});
|
||||
|
||||
test('studio api does not return other users artworks', function () {
|
||||
$otherUser = User::factory()->create();
|
||||
studioArtwork([
|
||||
'user_id' => $otherUser->id,
|
||||
'is_public' => true,
|
||||
'is_approved' => true,
|
||||
]);
|
||||
|
||||
$this->getJson('/api/studio/artworks')
|
||||
->assertStatus(200)
|
||||
->assertJsonCount(0, 'data');
|
||||
});
|
||||
|
||||
// ── Bulk Action Tests ─────────────────────────────────────────────────────────
|
||||
|
||||
test('bulk archive works on owned artworks', function () {
|
||||
$artwork = studioArtwork([
|
||||
'user_id' => $this->user->id,
|
||||
'is_public' => true,
|
||||
]);
|
||||
|
||||
$this->postJson('/api/studio/artworks/bulk', [
|
||||
'action' => 'archive',
|
||||
'artwork_ids' => [$artwork->id],
|
||||
])
|
||||
->assertStatus(200)
|
||||
->assertJsonPath('success', 1);
|
||||
|
||||
expect($artwork->fresh()->trashed())->toBeTrue();
|
||||
});
|
||||
|
||||
test('bulk delete requires confirmation', function () {
|
||||
$artwork = studioArtwork(['user_id' => $this->user->id]);
|
||||
|
||||
$this->postJson('/api/studio/artworks/bulk', [
|
||||
'action' => 'delete',
|
||||
'artwork_ids' => [$artwork->id],
|
||||
])
|
||||
->assertStatus(422);
|
||||
});
|
||||
|
||||
test('bulk delete with confirmation works', function () {
|
||||
$artwork = studioArtwork(['user_id' => $this->user->id]);
|
||||
|
||||
$this->postJson('/api/studio/artworks/bulk', [
|
||||
'action' => 'delete',
|
||||
'artwork_ids' => [$artwork->id],
|
||||
'confirm' => 'DELETE',
|
||||
])
|
||||
->assertStatus(200)
|
||||
->assertJsonPath('success', 1);
|
||||
});
|
||||
|
||||
test('bulk publish on owned artworks', function () {
|
||||
$artwork = studioArtwork([
|
||||
'user_id' => $this->user->id,
|
||||
'is_public' => false,
|
||||
]);
|
||||
|
||||
$this->postJson('/api/studio/artworks/bulk', [
|
||||
'action' => 'publish',
|
||||
'artwork_ids' => [$artwork->id],
|
||||
])
|
||||
->assertStatus(200)
|
||||
->assertJsonPath('success', 1);
|
||||
|
||||
expect($artwork->fresh()->is_public)->toBeTrue();
|
||||
});
|
||||
|
||||
test('bulk action cannot modify other users artworks', function () {
|
||||
$otherUser = User::factory()->create();
|
||||
$artwork = studioArtwork(['user_id' => $otherUser->id]);
|
||||
|
||||
$this->postJson('/api/studio/artworks/bulk', [
|
||||
'action' => 'archive',
|
||||
'artwork_ids' => [$artwork->id],
|
||||
])
|
||||
->assertStatus(422)
|
||||
->assertJsonPath('success', 0)
|
||||
->assertJsonPath('failed', 1);
|
||||
});
|
||||
|
||||
// ── Toggle Tests ──────────────────────────────────────────────────────────────
|
||||
|
||||
test('toggle publish on single artwork', function () {
|
||||
$artwork = studioArtwork([
|
||||
'user_id' => $this->user->id,
|
||||
'is_public' => false,
|
||||
]);
|
||||
|
||||
$this->postJson("/api/studio/artworks/{$artwork->id}/toggle", [
|
||||
'action' => 'publish',
|
||||
])
|
||||
->assertStatus(200)
|
||||
->assertJsonPath('success', true);
|
||||
|
||||
expect($artwork->fresh()->is_public)->toBeTrue();
|
||||
});
|
||||
|
||||
test('toggle on non-owned artwork returns 404', function () {
|
||||
$otherUser = User::factory()->create();
|
||||
$artwork = studioArtwork(['user_id' => $otherUser->id]);
|
||||
|
||||
$this->postJson("/api/studio/artworks/{$artwork->id}/toggle", [
|
||||
'action' => 'archive',
|
||||
])
|
||||
->assertStatus(404);
|
||||
});
|
||||
|
||||
// ── Analytics API Tests ───────────────────────────────────────────────────────
|
||||
|
||||
test('analytics api returns artwork stats', function () {
|
||||
$artwork = studioArtwork(['user_id' => $this->user->id]);
|
||||
ArtworkStats::create([
|
||||
'artwork_id' => $artwork->id,
|
||||
'views' => 500,
|
||||
'downloads' => 20,
|
||||
'favorites' => 30,
|
||||
'shares_count' => 10,
|
||||
'comments_count' => 5,
|
||||
'ranking_score' => 42.5,
|
||||
'heat_score' => 8.3,
|
||||
]);
|
||||
|
||||
$this->getJson("/api/studio/artworks/{$artwork->id}/analytics")
|
||||
->assertStatus(200)
|
||||
->assertJsonStructure([
|
||||
'artwork' => ['id', 'title', 'slug'],
|
||||
'analytics' => ['views', 'favourites', 'shares', 'comments', 'downloads', 'ranking_score', 'heat_score'],
|
||||
]);
|
||||
});
|
||||
|
||||
test('analytics api denies access to other users artwork', function () {
|
||||
$otherUser = User::factory()->create();
|
||||
$artwork = studioArtwork(['user_id' => $otherUser->id]);
|
||||
|
||||
$this->getJson("/api/studio/artworks/{$artwork->id}/analytics")
|
||||
->assertStatus(404);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user