CommonCatalogControllerTest.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. declare(strict_types=1);
  3. namespace Tests\Feature;
  4. use App\Jobs\Export\ExportCommonCatalogJob;
  5. use App\Jobs\Import\ImportJob;
  6. use App\Models\CommonCatalogItem;
  7. use App\Models\Role;
  8. use App\Models\User;
  9. use Illuminate\Foundation\Testing\RefreshDatabase;
  10. use Illuminate\Http\UploadedFile;
  11. use Illuminate\Support\Facades\Bus;
  12. use Illuminate\Support\Facades\Storage;
  13. use Tests\TestCase;
  14. class CommonCatalogControllerTest extends TestCase
  15. {
  16. use RefreshDatabase;
  17. protected bool $seed = true;
  18. private User $admin;
  19. private User $manager;
  20. protected function setUp(): void
  21. {
  22. parent::setUp();
  23. $this->admin = User::factory()->create(['role' => Role::ADMIN]);
  24. $this->manager = User::factory()->create(['role' => Role::MANAGER]);
  25. }
  26. public function test_guest_cannot_access_common_catalog(): void
  27. {
  28. $this->get(route('common-catalog.index'))->assertRedirect(route('login'));
  29. }
  30. public function test_standard_authenticated_roles_can_view_year_independent_catalog(): void
  31. {
  32. $item = CommonCatalogItem::factory()->create([
  33. 'article' => '0254',
  34. 'calculator_name' => 'Оборудование для благоустройства',
  35. ]);
  36. $this->actingAs($this->manager)
  37. ->withSession(['year' => 2021])
  38. ->get(route('common-catalog.index'))
  39. ->assertOk()
  40. ->assertViewIs('common_catalog.index')
  41. ->assertSee($item->article)
  42. ->assertSee($item->calculator_name);
  43. }
  44. public function test_manager_cannot_mutate_common_catalog(): void
  45. {
  46. $this->actingAs($this->manager)
  47. ->post(route('common-catalog.store'), $this->validData())
  48. ->assertForbidden();
  49. }
  50. public function test_admin_can_create_update_and_delete_item(): void
  51. {
  52. $this->actingAs($this->admin)
  53. ->post(route('common-catalog.store'), $this->validData())
  54. ->assertRedirect();
  55. $item = CommonCatalogItem::query()->where('article', '0007')->firstOrFail();
  56. $updated = $this->validData();
  57. $updated['calculator_name'] = 'Обновлённое наименование';
  58. $this->actingAs($this->admin)
  59. ->put(route('common-catalog.update', $item), $updated)
  60. ->assertRedirect();
  61. $this->assertDatabaseHas('common_catalog_items', [
  62. 'id' => $item->id,
  63. 'article' => '0007',
  64. 'calculator_name' => 'Обновлённое наименование',
  65. ]);
  66. $this->actingAs($this->admin)
  67. ->delete(route('common-catalog.destroy', $item))
  68. ->assertRedirect(route('common-catalog.index'));
  69. $this->assertSoftDeleted('common_catalog_items', ['id' => $item->id]);
  70. }
  71. public function test_article_and_calculator_name_are_required_and_article_is_unique(): void
  72. {
  73. CommonCatalogItem::factory()->create(['article' => '0007']);
  74. $this->actingAs($this->admin)
  75. ->post(route('common-catalog.store'), [
  76. 'article' => '0007',
  77. 'calculator_name' => '',
  78. ])
  79. ->assertSessionHasErrors(['article', 'calculator_name']);
  80. }
  81. public function test_item_card_contains_technical_description_and_calculation_placeholders(): void
  82. {
  83. $item = CommonCatalogItem::factory()->create();
  84. $this->actingAs($this->admin)
  85. ->get(route('common-catalog.show', $item))
  86. ->assertOk()
  87. ->assertSeeText('Техническое описание')
  88. ->assertSeeText('Калькуляция');
  89. }
  90. public function test_admin_can_upload_and_delete_image(): void
  91. {
  92. Storage::fake('public');
  93. $item = CommonCatalogItem::factory()->create();
  94. $this->actingAs($this->admin)
  95. ->post(route('common-catalog.image.upload', $item), [
  96. 'image' => UploadedFile::fake()->image('item.png', 200, 200),
  97. ])
  98. ->assertRedirect();
  99. $item->refresh();
  100. $this->assertNotNull($item->imageFile);
  101. Storage::disk('public')->assertExists($item->imageFile->path);
  102. $fileId = $item->imageFile->id;
  103. $this->actingAs($this->admin)
  104. ->delete(route('common-catalog.image.delete', $item))
  105. ->assertRedirect();
  106. $this->assertDatabaseMissing('files', ['id' => $fileId]);
  107. $this->assertNull($item->refresh()->image_file_id);
  108. }
  109. public function test_admin_can_upload_and_delete_multiple_documents(): void
  110. {
  111. Storage::fake('public');
  112. $item = CommonCatalogItem::factory()->create();
  113. foreach (['certificate.pdf', 'manual.pdf'] as $filename) {
  114. $this->actingAs($this->admin)
  115. ->post(route('common-catalog.documents.upload', $item), [
  116. 'document' => UploadedFile::fake()->create($filename, 20, 'application/pdf'),
  117. ])
  118. ->assertRedirect();
  119. }
  120. $this->assertCount(2, $item->refresh()->documents);
  121. $document = $item->documents->first();
  122. $this->actingAs($this->admin)
  123. ->delete(route('common-catalog.documents.delete', [$item, $document]))
  124. ->assertRedirect();
  125. $this->assertCount(1, $item->refresh()->documents);
  126. $this->assertDatabaseMissing('files', ['id' => $document->id]);
  127. }
  128. public function test_import_and_export_are_queued(): void
  129. {
  130. Storage::fake('upload');
  131. Bus::fake([ImportJob::class, ExportCommonCatalogJob::class]);
  132. $this->actingAs($this->admin)
  133. ->post(route('common-catalog.import'), [
  134. 'import_file' => UploadedFile::fake()->create(
  135. 'common-catalog.xlsx',
  136. 20,
  137. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  138. ),
  139. ])
  140. ->assertRedirect(route('common-catalog.index'));
  141. $this->assertDatabaseHas('imports', [
  142. 'type' => 'common_catalog',
  143. 'year' => null,
  144. 'user_id' => $this->admin->id,
  145. ]);
  146. Bus::assertDispatched(ImportJob::class);
  147. $this->actingAs($this->admin)
  148. ->post(route('common-catalog.export'))
  149. ->assertRedirect(route('common-catalog.index'));
  150. Bus::assertDispatched(ExportCommonCatalogJob::class);
  151. }
  152. private function validData(): array
  153. {
  154. return [
  155. 'article' => '0007',
  156. 'calculator_name' => "0007\nИгровой комплекс",
  157. 'kind' => 'Игровое оборудование',
  158. 'dimensions' => '2 × 3 × 1,5 м',
  159. 'fall_height' => 1.2,
  160. 'dimension_unit' => 'м',
  161. 'weight' => 350.5,
  162. 'volume' => 4.25,
  163. 'places' => 3,
  164. 'age_group' => '3+',
  165. 'max_users' => 8,
  166. 'unit' => 'шт.',
  167. 'series' => 'Двор',
  168. 'trademark' => 'Наш Двор',
  169. ];
  170. }
  171. }