ContractControllerTest.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <?php
  2. namespace Tests\Feature;
  3. use App\Models\Contract;
  4. use App\Models\Role;
  5. use App\Models\User;
  6. use Illuminate\Foundation\Testing\RefreshDatabase;
  7. use Tests\TestCase;
  8. class ContractControllerTest extends TestCase
  9. {
  10. use RefreshDatabase;
  11. protected $seed = true;
  12. private User $adminUser;
  13. private User $managerUser;
  14. protected function setUp(): void
  15. {
  16. parent::setUp();
  17. $this->adminUser = User::factory()->create(['role' => Role::ADMIN]);
  18. $this->managerUser = User::factory()->create(['role' => Role::MANAGER]);
  19. }
  20. // ==================== Authentication ====================
  21. public function test_guest_cannot_access_contracts_index(): void
  22. {
  23. $response = $this->get(route('contract.index'));
  24. $response->assertRedirect(route('login'));
  25. }
  26. public function test_guest_cannot_access_contract_create(): void
  27. {
  28. $response = $this->get(route('contract.create'));
  29. $response->assertRedirect(route('login'));
  30. }
  31. public function test_guest_cannot_store_contract(): void
  32. {
  33. $response = $this->post(route('contract.store'), []);
  34. $response->assertRedirect(route('login'));
  35. }
  36. public function test_guest_cannot_update_contract(): void
  37. {
  38. $contract = Contract::factory()->create();
  39. $response = $this->post(route('contract.update', $contract), []);
  40. $response->assertRedirect(route('login'));
  41. }
  42. public function test_guest_cannot_delete_contract(): void
  43. {
  44. $contract = Contract::factory()->create();
  45. $response = $this->delete(route('contract.delete', $contract));
  46. $response->assertRedirect(route('login'));
  47. }
  48. // ==================== Index ====================
  49. public function test_admin_can_access_contracts_index(): void
  50. {
  51. $response = $this->actingAs($this->adminUser)
  52. ->get(route('contract.index'));
  53. $response->assertStatus(200);
  54. $response->assertViewIs('contracts.index');
  55. }
  56. public function test_manager_can_access_contracts_index(): void
  57. {
  58. $response = $this->actingAs($this->managerUser)
  59. ->get(route('contract.index'));
  60. $response->assertStatus(200);
  61. $response->assertViewIs('contracts.index');
  62. }
  63. // ==================== Create/Show ====================
  64. public function test_admin_can_access_contract_create_form(): void
  65. {
  66. $response = $this->actingAs($this->adminUser)
  67. ->get(route('contract.create'));
  68. $response->assertStatus(200);
  69. $response->assertViewIs('contracts.edit');
  70. }
  71. public function test_admin_can_view_contract(): void
  72. {
  73. $contract = Contract::factory()->create();
  74. $response = $this->actingAs($this->adminUser)
  75. ->get(route('contract.show', $contract));
  76. $response->assertStatus(200);
  77. $response->assertViewIs('contracts.edit');
  78. }
  79. public function test_contract_show_uses_nav_context_back_url(): void
  80. {
  81. $contract = Contract::factory()->create();
  82. $response = $this->actingAs($this->adminUser)
  83. ->withSession([
  84. 'navigation' => [
  85. 'contract-nav' => [
  86. 'updated_at' => now()->timestamp,
  87. 'stack' => [
  88. route('contract.index', ['page' => 2]),
  89. ],
  90. ],
  91. ],
  92. ])
  93. ->get(route('contract.show', ['contract' => $contract, 'nav' => 'contract-nav']));
  94. $response->assertOk();
  95. $response->assertViewHas('nav', 'contract-nav');
  96. $response->assertViewHas('back_url', route('contract.index', ['page' => 2]));
  97. }
  98. // ==================== Store ====================
  99. public function test_admin_can_create_contract(): void
  100. {
  101. $contractData = [
  102. 'contract_number' => 'CONTRACT-2026-001',
  103. 'contract_date' => '2026-01-15',
  104. 'year' => 2026,
  105. ];
  106. $response = $this->actingAs($this->adminUser)
  107. ->post(route('contract.store'), $contractData);
  108. $response->assertRedirect(route('contract.index'));
  109. $this->assertDatabaseHas('contracts', [
  110. 'contract_number' => 'CONTRACT-2026-001',
  111. 'year' => 2026,
  112. ]);
  113. }
  114. public function test_manager_cannot_create_contract(): void
  115. {
  116. $contractData = [
  117. 'contract_number' => 'CONTRACT-2026-002',
  118. 'contract_date' => '2026-01-15',
  119. 'year' => 2026,
  120. ];
  121. $response = $this->actingAs($this->managerUser)
  122. ->post(route('contract.store'), $contractData);
  123. $response->assertStatus(403);
  124. $this->assertDatabaseMissing('contracts', [
  125. 'contract_number' => 'CONTRACT-2026-002',
  126. ]);
  127. }
  128. public function test_store_contract_requires_contract_number(): void
  129. {
  130. $response = $this->actingAs($this->adminUser)
  131. ->post(route('contract.store'), [
  132. 'contract_date' => '2026-01-15',
  133. 'year' => 2026,
  134. ]);
  135. $response->assertSessionHasErrors('contract_number');
  136. }
  137. public function test_store_contract_requires_contract_date(): void
  138. {
  139. $response = $this->actingAs($this->adminUser)
  140. ->post(route('contract.store'), [
  141. 'contract_number' => 'CONTRACT-2026-003',
  142. 'year' => 2026,
  143. ]);
  144. $response->assertSessionHasErrors('contract_date');
  145. }
  146. public function test_store_contract_requires_year(): void
  147. {
  148. $response = $this->actingAs($this->adminUser)
  149. ->post(route('contract.store'), [
  150. 'contract_number' => 'CONTRACT-2026-004',
  151. 'contract_date' => '2026-01-15',
  152. ]);
  153. $response->assertSessionHasErrors('year');
  154. }
  155. // ==================== Update ====================
  156. public function test_admin_can_update_contract(): void
  157. {
  158. $contract = Contract::factory()->create([
  159. 'contract_number' => 'OLD-NUMBER',
  160. 'year' => 2025,
  161. ]);
  162. $response = $this->actingAs($this->adminUser)
  163. ->post(route('contract.update', $contract), [
  164. 'contract_number' => 'NEW-NUMBER',
  165. 'contract_date' => '2026-02-01',
  166. 'year' => 2026,
  167. ]);
  168. $response->assertRedirect(route('contract.index'));
  169. $this->assertDatabaseHas('contracts', [
  170. 'id' => $contract->id,
  171. 'contract_number' => 'NEW-NUMBER',
  172. 'year' => 2026,
  173. ]);
  174. }
  175. public function test_manager_cannot_update_contract(): void
  176. {
  177. $contract = Contract::factory()->create([
  178. 'contract_number' => 'ORIGINAL-NUMBER',
  179. ]);
  180. $response = $this->actingAs($this->managerUser)
  181. ->post(route('contract.update', $contract), [
  182. 'contract_number' => 'MODIFIED-NUMBER',
  183. 'contract_date' => '2026-02-01',
  184. 'year' => 2026,
  185. ]);
  186. $response->assertStatus(403);
  187. $this->assertDatabaseHas('contracts', [
  188. 'id' => $contract->id,
  189. 'contract_number' => 'ORIGINAL-NUMBER',
  190. ]);
  191. }
  192. // ==================== Delete ====================
  193. public function test_admin_can_delete_contract(): void
  194. {
  195. $contract = Contract::factory()->create();
  196. $response = $this->actingAs($this->adminUser)
  197. ->delete(route('contract.delete', $contract));
  198. $response->assertRedirect(route('contract.index'));
  199. $this->assertDatabaseMissing('contracts', ['id' => $contract->id]);
  200. }
  201. public function test_manager_can_delete_contract(): void
  202. {
  203. $contract = Contract::factory()->create();
  204. $response = $this->actingAs($this->managerUser)
  205. ->delete(route('contract.delete', $contract));
  206. $response->assertRedirect(route('contract.index'));
  207. $this->assertDatabaseMissing('contracts', ['id' => $contract->id]);
  208. }
  209. }