| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- <?php
- declare(strict_types=1);
- namespace Tests\Feature;
- use App\Models\ChatMessage;
- use App\Models\CommonCatalogItem;
- use App\Models\File;
- use App\Models\ProductionOrder;
- use App\Models\ProductionOrderItem;
- use App\Models\User;
- use Illuminate\Foundation\Testing\RefreshDatabase;
- use Illuminate\Http\UploadedFile;
- use Illuminate\Support\Facades\Storage;
- use Tests\TestCase;
- class ProductionOrderFileAndChatControllerTest extends TestCase
- {
- use RefreshDatabase;
- protected bool $seed = true;
- private User $admin;
- private User $assistant;
- private User $manager;
- private ProductionOrder $order;
- private ProductionOrderItem $item;
- protected function setUp(): void
- {
- parent::setUp();
- Storage::fake('public');
- $this->admin = User::factory()->admin()->create();
- $this->assistant = User::factory()->assistantHead()->create();
- $this->manager = User::factory()->manager()->create();
- $this->order = ProductionOrder::factory()->create(['manager_id' => $this->manager->id]);
- $this->item = ProductionOrderItem::factory()->create([
- 'production_order_id' => $this->order->id,
- 'common_catalog_item_id' => CommonCatalogItem::factory(),
- ]);
- }
- public function test_assistant_can_upload_documents_photos_and_item_passport(): void
- {
- $this->actingAs($this->assistant)
- ->post(route('schedule.orders.documents.store', $this->order), [
- 'documents' => [UploadedFile::fake()->create('instruction.pdf', 10, 'application/pdf')],
- ])
- ->assertRedirect();
- $this->actingAs($this->assistant)
- ->post(route('schedule.orders.photos.store', $this->order), [
- 'photos' => [UploadedFile::fake()->image('object.jpg', 100, 100)],
- ])
- ->assertRedirect();
- $this->actingAs($this->assistant)
- ->post(route('schedule.orders.items.passport.store', [$this->order, $this->item]), [
- 'passport' => UploadedFile::fake()->create('passport.pdf', 10, 'application/pdf'),
- ])
- ->assertRedirect();
- $this->assertSame(1, $this->order->documents()->count());
- $this->assertSame(1, $this->order->photos()->count());
- $this->assertNotNull($this->item->fresh()->passport_file_id);
- foreach (File::query()->get() as $file) {
- Storage::disk('public')->assertExists($file->path);
- }
- }
- public function test_manager_can_chat_but_cannot_manage_order_files(): void
- {
- $this->actingAs($this->manager)
- ->post(route('schedule.orders.chat-messages.store', $this->order), [
- 'message' => 'Заказ принят в работу',
- 'attachments' => [UploadedFile::fake()->create('note.txt', 1, 'text/plain')],
- ])
- ->assertRedirect()
- ->assertSessionHas('success');
- $message = ChatMessage::query()->where('production_order_id', $this->order->id)->firstOrFail();
- $this->assertSame('Заказ принят в работу', $message->message);
- $this->assertSame(1, $message->files()->count());
- $this->actingAs($this->manager)
- ->post(route('schedule.orders.documents.store', $this->order), [
- 'documents' => [UploadedFile::fake()->create('forbidden.pdf', 1, 'application/pdf')],
- ])
- ->assertForbidden();
- $this->actingAs($this->manager)
- ->post(route('schedule.orders.items.passport.store', [$this->order, $this->item]), [
- 'passport' => UploadedFile::fake()->create('forbidden.pdf', 1, 'application/pdf'),
- ])
- ->assertForbidden();
- }
- public function test_order_card_uses_queued_multi_file_upload_forms(): void
- {
- $this->actingAs($this->assistant)
- ->get(route('schedule.orders.show', $this->order))
- ->assertOk()
- ->assertSee('id="production-order-documents-input"', false)
- ->assertSee('name="documents[]" multiple', false)
- ->assertSee('id="production-order-photos-input"', false)
- ->assertSee('name="photos[]" multiple', false)
- ->assertSee('onchange="$(this).parent().submit()"', false);
- }
- public function test_document_and_photo_upload_validation_errors_are_in_russian(): void
- {
- $documentResponse = $this->actingAs($this->assistant)
- ->withHeader('Accept', 'application/json')
- ->post(route('schedule.orders.documents.store', $this->order), [
- 'documents' => ['не файл'],
- ])
- ->assertUnprocessable()
- ->assertJsonValidationErrors('documents.0');
- $this->assertSame(
- 'Выбранный документ не является файлом.',
- $documentResponse->json('errors')['documents.0'][0],
- );
- $this->assertStringContainsString(
- 'Выбранный документ не является файлом.',
- (string) $documentResponse->json('message'),
- );
- $photoResponse = $this->actingAs($this->assistant)
- ->withHeader('Accept', 'application/json')
- ->post(route('schedule.orders.photos.store', $this->order), [
- 'photos' => [UploadedFile::fake()->create('document.pdf', 10, 'application/pdf')],
- ])
- ->assertUnprocessable()
- ->assertJsonValidationErrors('photos.0');
- $this->assertSame(
- 'Допустимы только фотографии JPG, JPEG, PNG и WebP.',
- $photoResponse->json('errors')['photos.0'][0],
- );
- $this->assertStringContainsString(
- 'Допустимы только фотографии JPG, JPEG, PNG и WebP.',
- (string) $photoResponse->json('message'),
- );
- }
- public function test_order_card_shows_mime_icons_image_previews_and_chat(): void
- {
- $pdf = File::factory()->pdf()->create(['user_id' => $this->admin->id]);
- $image = File::factory()->image()->create(['user_id' => $this->admin->id]);
- $passport = File::factory()->image()->create(['user_id' => $this->admin->id]);
- $this->order->documents()->attach([$pdf->id, $image->id]);
- $this->order->photos()->attach($image->id);
- $this->item->update(['passport_file_id' => $passport->id]);
- ChatMessage::query()->create([
- 'production_order_id' => $this->order->id,
- 'user_id' => $this->manager->id,
- 'message' => 'Сообщение в чате заказа',
- ]);
- $this->actingAs($this->manager)
- ->get(route('schedule.orders.show', $this->order))
- ->assertOk()
- ->assertSee('bi-file-earmark-pdf', false)
- ->assertSee('bi-file-earmark-image', false)
- ->assertSee('data-toggle="lightbox"', false)
- ->assertSee('Фотографии (1)')
- ->assertSee('data-bs-target="#production-order-photos-'.$this->order->id.'"', false)
- ->assertSee('id="production-order-photos-'.$this->order->id.'" class="card-body collapse"', false)
- ->assertSee('data-lazy-images', false)
- ->assertSee('data-src="'.$image->thumbnail_link.'"', false)
- ->assertSee('class="img-thumbnail maf-img"', false)
- ->assertSee('Сообщение в чате заказа')
- ->assertSee(route('schedule.orders.chat-messages.store', $this->order), false)
- ->assertDontSee(route('schedule.orders.documents.store', $this->order), false);
- }
- public function test_file_and_chat_routes_reject_resources_from_another_order(): void
- {
- $otherOrder = ProductionOrder::factory()->create(['manager_id' => $this->manager->id]);
- $otherItem = ProductionOrderItem::factory()->create([
- 'production_order_id' => $otherOrder->id,
- 'common_catalog_item_id' => CommonCatalogItem::factory(),
- ]);
- $message = ChatMessage::query()->create([
- 'production_order_id' => $otherOrder->id,
- 'user_id' => $this->admin->id,
- 'message' => 'Чужое сообщение',
- ]);
- $this->actingAs($this->admin)
- ->post(route('schedule.orders.items.passport.store', [$this->order, $otherItem]), [
- 'passport' => UploadedFile::fake()->create('passport.pdf', 1, 'application/pdf'),
- ])
- ->assertNotFound();
- $this->actingAs($this->admin)
- ->delete(route('schedule.orders.chat-messages.destroy', [$this->order, $message]))
- ->assertNotFound();
- }
- }
|