fix: resolve 15 pre-existing test failures flagged across 3 retrospectives
Delete 14 legacy Folder test files (FolderTypeTest, MediaDownloadTest, FolderMentionTest) that referenced removed routes/tables from the Epic 0 folders-to-declarations rename. Declaration equivalents already exist. Fix WorkerDashboardTest session edge case where HandleInertiaRequests middleware auto-assigns workspace, invalidating the no-session assumption. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -267,13 +267,11 @@ test('owner and manager dashboard returns isWorker false', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('worker without workspace session gets isWorker false in fallback', function () {
|
test('user without any workspace gets isWorker false in fallback', function () {
|
||||||
$worker = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($worker->id, ['role' => 'worker']);
|
|
||||||
|
|
||||||
// No session(['current_workspace_id' => ...]) — simulate no active workspace
|
// User has no workspace attachments — middleware cannot auto-assign
|
||||||
$this->actingAs($worker);
|
$this->actingAs($user);
|
||||||
$response = $this->get(route('dashboard'));
|
$response = $this->get(route('dashboard'));
|
||||||
|
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use App\Models\Client;
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Workspace;
|
|
||||||
|
|
||||||
test('can create vat_monthly folder requiring month', function () {
|
|
||||||
$user = User::factory()->create();
|
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($user, ['role' => 'owner']);
|
|
||||||
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($user)->post(route('folders.store'), [
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'title' => 'TVA Mensuelle Mars 2026',
|
|
||||||
'type' => 'vat_monthly',
|
|
||||||
'period_year' => 2026,
|
|
||||||
'period_month' => 3,
|
|
||||||
'status' => 'draft',
|
|
||||||
'priority' => 'medium',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertRedirect();
|
|
||||||
$folder = $client->folders()->where('type', 'vat_monthly')->first();
|
|
||||||
expect($folder)->not->toBeNull();
|
|
||||||
expect($folder->period_month)->toBe(3);
|
|
||||||
expect($folder->period_quarter)->toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('vat_monthly validation fails without month', function () {
|
|
||||||
$user = User::factory()->create();
|
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($user, ['role' => 'owner']);
|
|
||||||
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($user)->post(route('folders.store'), [
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'title' => 'TVA Mensuelle Sans Mois',
|
|
||||||
'type' => 'vat_monthly',
|
|
||||||
'period_year' => 2026,
|
|
||||||
'status' => 'draft',
|
|
||||||
'priority' => 'medium',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertSessionHasErrors('period_month');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('can create vat_quarterly folder requiring quarter', function () {
|
|
||||||
$user = User::factory()->create();
|
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($user, ['role' => 'owner']);
|
|
||||||
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($user)->post(route('folders.store'), [
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'title' => 'TVA Trimestrielle T1 2026',
|
|
||||||
'type' => 'vat_quarterly',
|
|
||||||
'period_year' => 2026,
|
|
||||||
'period_quarter' => 1,
|
|
||||||
'status' => 'draft',
|
|
||||||
'priority' => 'medium',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertRedirect();
|
|
||||||
$folder = $client->folders()->where('type', 'vat_quarterly')->first();
|
|
||||||
expect($folder)->not->toBeNull();
|
|
||||||
expect($folder->period_quarter)->toBe(1);
|
|
||||||
expect($folder->period_month)->toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('vat_quarterly validation fails without quarter', function () {
|
|
||||||
$user = User::factory()->create();
|
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($user, ['role' => 'owner']);
|
|
||||||
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($user)->post(route('folders.store'), [
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'title' => 'TVA Trimestrielle Sans Trimestre',
|
|
||||||
'type' => 'vat_quarterly',
|
|
||||||
'period_year' => 2026,
|
|
||||||
'status' => 'draft',
|
|
||||||
'priority' => 'medium',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertSessionHasErrors('period_quarter');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('server rejects old vat type', function () {
|
|
||||||
$user = User::factory()->create();
|
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($user, ['role' => 'owner']);
|
|
||||||
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($user)->post(route('folders.store'), [
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'title' => 'Old VAT',
|
|
||||||
'type' => 'vat',
|
|
||||||
'period_year' => 2026,
|
|
||||||
'status' => 'draft',
|
|
||||||
'priority' => 'medium',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertSessionHasErrors('type');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('vat_monthly nulls quarter field server-side', function () {
|
|
||||||
$user = User::factory()->create();
|
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($user, ['role' => 'owner']);
|
|
||||||
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($user)->post(route('folders.store'), [
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'title' => 'TVA Mensuelle With Quarter',
|
|
||||||
'type' => 'vat_monthly',
|
|
||||||
'period_year' => 2026,
|
|
||||||
'period_month' => 6,
|
|
||||||
'period_quarter' => 2,
|
|
||||||
'status' => 'draft',
|
|
||||||
'priority' => 'medium',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertRedirect();
|
|
||||||
$folder = $client->folders()->where('title', 'TVA Mensuelle With Quarter')->first();
|
|
||||||
expect($folder->period_quarter)->toBeNull();
|
|
||||||
expect($folder->period_month)->toBe(6);
|
|
||||||
});
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use App\Models\Client;
|
|
||||||
use App\Models\Folder;
|
|
||||||
use App\Models\MediaDownload;
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Workspace;
|
|
||||||
use Illuminate\Http\UploadedFile;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
|
|
||||||
function setupFolderWithMedia(): array
|
|
||||||
{
|
|
||||||
$user = User::factory()->create();
|
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($user, ['role' => 'owner']);
|
|
||||||
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
|
|
||||||
$folder = Folder::factory()->create([
|
|
||||||
'workspace_id' => $workspace->id,
|
|
||||||
'client_id' => $client->id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
Storage::fake('public');
|
|
||||||
$file = UploadedFile::fake()->create('document.pdf', 100, 'application/pdf');
|
|
||||||
$media = $folder->addMedia($file)->toMediaCollection('documents');
|
|
||||||
|
|
||||||
return [$user, $workspace, $folder, $media];
|
|
||||||
}
|
|
||||||
|
|
||||||
test('downloading creates a media download record', function () {
|
|
||||||
[$user, $workspace, $folder, $media] = setupFolderWithMedia();
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$this->actingAs($user)->get(route('folders.media.download', [
|
|
||||||
'folder' => $folder,
|
|
||||||
'mediaId' => $media->id,
|
|
||||||
]));
|
|
||||||
|
|
||||||
$download = MediaDownload::query()
|
|
||||||
->where('media_id', $media->id)
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
expect($download)->not->toBeNull();
|
|
||||||
expect($download->downloaded_at)->not->toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('re-downloading updates timestamp without creating duplicates', function () {
|
|
||||||
[$user, $workspace, $folder, $media] = setupFolderWithMedia();
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$this->actingAs($user)->get(route('folders.media.download', [
|
|
||||||
'folder' => $folder,
|
|
||||||
'mediaId' => $media->id,
|
|
||||||
]));
|
|
||||||
|
|
||||||
$firstDownload = MediaDownload::query()
|
|
||||||
->where('media_id', $media->id)
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->first();
|
|
||||||
$firstTimestamp = $firstDownload->downloaded_at;
|
|
||||||
|
|
||||||
$this->travel(5)->minutes();
|
|
||||||
|
|
||||||
$this->actingAs($user)->get(route('folders.media.download', [
|
|
||||||
'folder' => $folder,
|
|
||||||
'mediaId' => $media->id,
|
|
||||||
]));
|
|
||||||
|
|
||||||
$count = MediaDownload::query()
|
|
||||||
->where('media_id', $media->id)
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->count();
|
|
||||||
|
|
||||||
expect($count)->toBe(1);
|
|
||||||
|
|
||||||
$firstDownload->refresh();
|
|
||||||
expect($firstDownload->downloaded_at->gt($firstTimestamp))->toBeTrue();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('download status is per-user in show endpoint', function () {
|
|
||||||
[$user, $workspace, $folder, $media] = setupFolderWithMedia();
|
|
||||||
$otherUser = User::factory()->create();
|
|
||||||
$workspace->users()->attach($otherUser, ['role' => 'member']);
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
MediaDownload::query()->create([
|
|
||||||
'media_id' => $media->id,
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'downloaded_at' => now(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($user)->get(route('folders.show', $folder));
|
|
||||||
$response->assertOk();
|
|
||||||
$documents = $response->original->getData()['page']['props']['documents'];
|
|
||||||
$doc = collect($documents)->firstWhere('id', $media->id);
|
|
||||||
expect($doc['is_downloaded'])->toBeTrue();
|
|
||||||
|
|
||||||
$response2 = $this->actingAs($otherUser)->get(route('folders.show', $folder));
|
|
||||||
$response2->assertOk();
|
|
||||||
$documents2 = $response2->original->getData()['page']['props']['documents'];
|
|
||||||
$doc2 = collect($documents2)->firstWhere('id', $media->id);
|
|
||||||
expect($doc2['is_downloaded'])->toBeFalse();
|
|
||||||
});
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use App\Models\Client;
|
|
||||||
use App\Models\Folder;
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Workspace;
|
|
||||||
use App\Notifications\FolderMentionNotification;
|
|
||||||
use Illuminate\Support\Facades\Notification;
|
|
||||||
|
|
||||||
function setupFolderMentionScenario(string $role = 'owner'): array
|
|
||||||
{
|
|
||||||
$sender = User::factory()->create();
|
|
||||||
$target = User::factory()->create();
|
|
||||||
$workspace = Workspace::factory()->create();
|
|
||||||
$workspace->users()->attach($sender, ['role' => $role]);
|
|
||||||
$workspace->users()->attach($target, ['role' => 'member']);
|
|
||||||
|
|
||||||
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
|
|
||||||
$folder = Folder::factory()->create([
|
|
||||||
'workspace_id' => $workspace->id,
|
|
||||||
'client_id' => $client->id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return [$sender, $target, $workspace, $folder];
|
|
||||||
}
|
|
||||||
|
|
||||||
test('owner can mention a workspace user', function () {
|
|
||||||
Notification::fake();
|
|
||||||
[$sender, $target, $workspace, $folder] = setupFolderMentionScenario('owner');
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($sender)->post(route('folders.mentions.store', $folder), [
|
|
||||||
'user_id' => $target->id,
|
|
||||||
'message' => 'Please check this folder.',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertRedirect();
|
|
||||||
Notification::assertSentTo($target, FolderMentionNotification::class);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('manager can mention a workspace user', function () {
|
|
||||||
Notification::fake();
|
|
||||||
[$sender, $target, $workspace, $folder] = setupFolderMentionScenario('manager');
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($sender)->post(route('folders.mentions.store', $folder), [
|
|
||||||
'user_id' => $target->id,
|
|
||||||
'message' => 'Please check this folder.',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertRedirect();
|
|
||||||
Notification::assertSentTo($target, FolderMentionNotification::class);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('member cannot mention a workspace user', function () {
|
|
||||||
Notification::fake();
|
|
||||||
[$sender, $target, $workspace, $folder] = setupFolderMentionScenario('member');
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($sender)->post(route('folders.mentions.store', $folder), [
|
|
||||||
'user_id' => $target->id,
|
|
||||||
'message' => 'Please check this folder.',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertForbidden();
|
|
||||||
Notification::assertNothingSent();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('cannot mention user from another workspace', function () {
|
|
||||||
Notification::fake();
|
|
||||||
[$sender, , $workspace, $folder] = setupFolderMentionScenario('owner');
|
|
||||||
$outsider = User::factory()->create();
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$response = $this->actingAs($sender)->post(route('folders.mentions.store', $folder), [
|
|
||||||
'user_id' => $outsider->id,
|
|
||||||
'message' => 'Hello',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertSessionHasErrors('user_id');
|
|
||||||
Notification::assertNothingSent();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('notification is persisted in database', function () {
|
|
||||||
[$sender, $target, $workspace, $folder] = setupFolderMentionScenario('owner');
|
|
||||||
session(['current_workspace_id' => $workspace->id]);
|
|
||||||
|
|
||||||
$this->actingAs($sender)->post(route('folders.mentions.store', $folder), [
|
|
||||||
'user_id' => $target->id,
|
|
||||||
'message' => 'Check this.',
|
|
||||||
]);
|
|
||||||
|
|
||||||
expect($target->notifications()->count())->toBe(1);
|
|
||||||
$notif = $target->notifications()->first();
|
|
||||||
expect($notif->data['folder_id'])->toBe($folder->id);
|
|
||||||
expect($notif->data['message'])->toBe('Check this.');
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user