MafOrderControllerTest.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. <?php
  2. namespace Tests\Feature;
  3. use App\Models\MafOrder;
  4. use App\Models\Product;
  5. use App\Models\Role;
  6. use App\Models\User;
  7. use Illuminate\Foundation\Testing\RefreshDatabase;
  8. use Tests\TestCase;
  9. class MafOrderControllerTest extends TestCase
  10. {
  11. use RefreshDatabase;
  12. protected $seed = true;
  13. private User $adminUser;
  14. private User $managerUser;
  15. private User $assistantHeadUser;
  16. protected function setUp(): void
  17. {
  18. parent::setUp();
  19. $this->adminUser = User::factory()->create(['role' => Role::ADMIN]);
  20. $this->managerUser = User::factory()->create(['role' => Role::MANAGER]);
  21. $this->assistantHeadUser = User::factory()->create(['role' => Role::ASSISTANT_HEAD]);
  22. }
  23. private function assertRedirectsToMafShowWithGeneratedNav($response, MafOrder $mafOrder): void
  24. {
  25. $location = $response->headers->get('Location');
  26. $this->assertNotNull($location);
  27. $this->assertStringStartsWith(route('maf_order.show', $mafOrder), $location);
  28. $this->assertStringContainsString('nav=', $location);
  29. }
  30. // ==================== Authentication ====================
  31. public function test_guest_cannot_access_maf_orders_index(): void
  32. {
  33. $response = $this->get(route('maf_order.index'));
  34. $response->assertRedirect(route('login'));
  35. }
  36. public function test_authenticated_admin_can_access_maf_orders_index(): void
  37. {
  38. $response = $this->actingAs($this->adminUser)
  39. ->get(route('maf_order.index'));
  40. $response->assertStatus(200);
  41. $response->assertViewIs('maf_orders.index');
  42. }
  43. public function test_manager_cannot_access_maf_orders_index(): void
  44. {
  45. $response = $this->actingAs($this->managerUser)
  46. ->get(route('maf_order.index'));
  47. $response->assertStatus(403);
  48. }
  49. public function test_assistant_head_can_access_maf_orders_index(): void
  50. {
  51. $response = $this->actingAs($this->assistantHeadUser)
  52. ->get(route('maf_order.index'));
  53. $response->assertStatus(200);
  54. $response->assertViewIs('maf_orders.index');
  55. }
  56. // ==================== Index ====================
  57. public function test_maf_orders_index_displays_orders(): void
  58. {
  59. MafOrder::factory()->create();
  60. $response = $this->actingAs($this->adminUser)
  61. ->get(route('maf_order.index'));
  62. $response->assertStatus(200);
  63. }
  64. // ==================== Store (create) ====================
  65. public function test_can_create_maf_order(): void
  66. {
  67. $product = Product::factory()->create();
  68. $response = $this->actingAs($this->adminUser)
  69. ->post(route('maf_order.store'), [
  70. 'product_id' => $product->id,
  71. 'quantity' => 5,
  72. 'order_number' => 'MO-TEST-001',
  73. ]);
  74. $response->assertRedirect();
  75. $this->assertDatabaseHas('maf_orders', [
  76. 'product_id' => $product->id,
  77. 'quantity' => 5,
  78. 'order_number' => 'MO-TEST-001',
  79. 'in_stock' => 0,
  80. ]);
  81. }
  82. public function test_store_maf_order_requires_product_id(): void
  83. {
  84. $response = $this->actingAs($this->adminUser)
  85. ->post(route('maf_order.store'), [
  86. 'quantity' => 5,
  87. ]);
  88. $response->assertSessionHasErrors('product_id');
  89. }
  90. public function test_store_maf_order_requires_quantity(): void
  91. {
  92. $product = Product::factory()->create();
  93. $response = $this->actingAs($this->adminUser)
  94. ->post(route('maf_order.store'), [
  95. 'product_id' => $product->id,
  96. ]);
  97. $response->assertSessionHasErrors('quantity');
  98. }
  99. public function test_guest_cannot_create_maf_order(): void
  100. {
  101. $product = Product::factory()->create();
  102. $response = $this->post(route('maf_order.store'), [
  103. 'product_id' => $product->id,
  104. 'quantity' => 3,
  105. ]);
  106. $response->assertRedirect(route('login'));
  107. }
  108. // ==================== Show ====================
  109. public function test_can_view_maf_order_details(): void
  110. {
  111. $mafOrder = MafOrder::factory()->create();
  112. $response = $this->actingAs($this->adminUser)
  113. ->get(route('maf_order.show', $mafOrder));
  114. $response->assertStatus(200);
  115. $response->assertViewIs('maf_orders.edit');
  116. }
  117. public function test_maf_order_show_uses_nav_context_back_url(): void
  118. {
  119. $mafOrder = MafOrder::factory()->create();
  120. $indexResponse = $this->actingAs($this->adminUser)
  121. ->get(route('maf_order.index', [
  122. 'filters' => ['user_name' => $this->adminUser->name],
  123. ]));
  124. $nav = $indexResponse->viewData('nav');
  125. $response = $this->actingAs($this->adminUser)
  126. ->get(route('maf_order.show', [
  127. 'maf_order' => $mafOrder,
  128. 'nav' => $nav,
  129. ]));
  130. $response->assertOk();
  131. $response->assertViewHas('nav', $nav);
  132. $response->assertViewHas('back_url', function (string $backUrl): bool {
  133. if (!str_starts_with($backUrl, route('maf_order.index'))) {
  134. return false;
  135. }
  136. $query = parse_url($backUrl, PHP_URL_QUERY);
  137. parse_str((string) $query, $params);
  138. return ($params['filters']['user_name'] ?? null) === $this->adminUser->name;
  139. });
  140. }
  141. public function test_guest_cannot_view_maf_order_details(): void
  142. {
  143. $mafOrder = MafOrder::factory()->create();
  144. $response = $this->get(route('maf_order.show', $mafOrder));
  145. $response->assertRedirect(route('login'));
  146. }
  147. // ==================== Update ====================
  148. public function test_can_update_maf_order(): void
  149. {
  150. $product = Product::factory()->create();
  151. $mafOrder = MafOrder::factory()->create([
  152. 'product_id' => $product->id,
  153. 'quantity' => 3,
  154. ]);
  155. $response = $this->actingAs($this->adminUser)
  156. ->post(route('maf_order.update', $mafOrder), [
  157. 'product_id' => $product->id,
  158. 'quantity' => 10,
  159. 'order_number' => 'MO-UPDATED',
  160. ]);
  161. $response->assertRedirect();
  162. $this->assertDatabaseHas('maf_orders', [
  163. 'id' => $mafOrder->id,
  164. 'quantity' => 10,
  165. ]);
  166. }
  167. public function test_guest_cannot_update_maf_order(): void
  168. {
  169. $product = Product::factory()->create();
  170. $mafOrder = MafOrder::factory()->create(['product_id' => $product->id]);
  171. $response = $this->post(route('maf_order.update', $mafOrder), [
  172. 'product_id' => $product->id,
  173. 'quantity' => 10,
  174. ]);
  175. $response->assertRedirect(route('login'));
  176. }
  177. // ==================== Destroy ====================
  178. public function test_can_delete_maf_order(): void
  179. {
  180. $mafOrder = MafOrder::factory()->create();
  181. $mafOrderId = $mafOrder->id;
  182. $response = $this->actingAs($this->adminUser)
  183. ->delete(route('maf_order.delete', $mafOrder));
  184. $response->assertRedirect();
  185. $this->assertSoftDeleted('maf_orders', ['id' => $mafOrderId]);
  186. }
  187. public function test_guest_cannot_delete_maf_order(): void
  188. {
  189. $mafOrder = MafOrder::factory()->create();
  190. $response = $this->delete(route('maf_order.delete', $mafOrder));
  191. $response->assertRedirect(route('login'));
  192. }
  193. // ==================== SetInStock ====================
  194. public function test_set_in_stock_updates_stock_and_status(): void
  195. {
  196. $mafOrder = MafOrder::factory()->create([
  197. 'quantity' => 8,
  198. 'in_stock' => 0,
  199. 'status' => 'active',
  200. ]);
  201. $response = $this->actingAs($this->adminUser)
  202. ->post(route('maf_order.set_in_stock', $mafOrder));
  203. $this->assertRedirectsToMafShowWithGeneratedNav($response, $mafOrder);
  204. $this->assertDatabaseHas('maf_orders', [
  205. 'id' => $mafOrder->id,
  206. 'in_stock' => 8,
  207. 'status' => 'на складе',
  208. ]);
  209. }
  210. public function test_guest_cannot_set_in_stock(): void
  211. {
  212. $mafOrder = MafOrder::factory()->create(['quantity' => 5]);
  213. $response = $this->post(route('maf_order.set_in_stock', $mafOrder));
  214. $response->assertRedirect(route('login'));
  215. }
  216. public function test_set_order_in_stock_updates_all_rows_by_order_number(): void
  217. {
  218. $first = MafOrder::factory()->create([
  219. 'order_number' => 'MO-BULK-001',
  220. 'quantity' => 3,
  221. 'in_stock' => 0,
  222. 'status' => 'заказан',
  223. ]);
  224. $second = MafOrder::factory()->create([
  225. 'order_number' => 'MO-BULK-001',
  226. 'quantity' => 7,
  227. 'in_stock' => 1,
  228. 'status' => 'заказан',
  229. ]);
  230. $other = MafOrder::factory()->create([
  231. 'order_number' => 'MO-BULK-002',
  232. 'quantity' => 9,
  233. 'in_stock' => 2,
  234. 'status' => 'заказан',
  235. ]);
  236. $response = $this->actingAs($this->adminUser)
  237. ->post(route('maf_order.set_order_in_stock'), [
  238. 'bulk_order_number' => 'MO-BULK-001',
  239. ]);
  240. $response->assertRedirect(route('maf_order.index'));
  241. $this->assertDatabaseHas('maf_orders', [
  242. 'id' => $first->id,
  243. 'in_stock' => 3,
  244. 'status' => 'на складе',
  245. ]);
  246. $this->assertDatabaseHas('maf_orders', [
  247. 'id' => $second->id,
  248. 'in_stock' => 7,
  249. 'status' => 'на складе',
  250. ]);
  251. $this->assertDatabaseHas('maf_orders', [
  252. 'id' => $other->id,
  253. 'in_stock' => 2,
  254. 'status' => 'заказан',
  255. ]);
  256. }
  257. public function test_guest_cannot_set_order_in_stock(): void
  258. {
  259. $response = $this->post(route('maf_order.set_order_in_stock'), [
  260. 'bulk_order_number' => 'MO-BULK-001',
  261. ]);
  262. $response->assertRedirect(route('login'));
  263. }
  264. }