adminUser = User::factory()->create(['role' => Role::ADMIN]); $this->managerUser = User::factory()->create(['role' => Role::MANAGER]); $this->brigadierUser = User::factory()->create(['role' => Role::BRIGADIER]); } // ==================== Guest redirects ==================== public function test_guest_cannot_access_product_sku_index(): void { $response = $this->get(route('product_sku.index')); $response->assertRedirect(route('login')); } public function test_guest_cannot_access_product_sku_show(): void { $sku = ProductSKU::factory()->create(); $response = $this->get(route('product_sku.show', $sku)); $response->assertRedirect(route('login')); } public function test_guest_cannot_update_product_sku(): void { $sku = ProductSKU::factory()->create(); $response = $this->post(route('product_sku.update', $sku), []); $response->assertRedirect(route('login')); } // ==================== Authorization ==================== public function test_brigadier_cannot_access_product_sku_index(): void { $response = $this->actingAs($this->brigadierUser) ->get(route('product_sku.index')); $response->assertStatus(403); } public function test_manager_cannot_export_mafs(): void { $response = $this->actingAs($this->managerUser) ->post(route('mafs.export')); $response->assertStatus(403); } // ==================== Index ==================== public function test_admin_can_access_product_sku_index(): void { $response = $this->actingAs($this->adminUser) ->get(route('product_sku.index')); $response->assertStatus(200); $response->assertViewIs('products_sku.index'); } public function test_manager_can_access_product_sku_index(): void { $response = $this->actingAs($this->managerUser) ->get(route('product_sku.index')); $response->assertStatus(200); $response->assertViewIs('products_sku.index'); } public function test_maf_filter_options_include_empty_marker_for_factory_number(): void { ProductSKU::factory()->create(['factory_number' => null]); ProductSKU::factory()->create(['factory_number' => ' ']); ProductSKU::factory()->create(['factory_number' => 'FN-123456']); $response = $this->actingAs($this->adminUser) ->getJson(route('getFilters', [ 'table' => 'product_sku', 'column' => 'factory_number', ])); $response->assertOk(); $response->assertJsonFragment(['-пусто-']); $response->assertJsonFragment(['FN-123456']); } public function test_maf_empty_filter_matches_null_blank_and_null_date_values(): void { $orderWithNullFactory = Order::factory()->create(['object_address' => 'ул. Пустая фабрика']); $orderWithBlankFactory = Order::factory()->create(['object_address' => 'ул. Пробелы фабрика']); $orderWithNullDate = Order::factory()->create(['object_address' => 'ул. Пустая дата']); $orderWithBlankStatement = Order::factory()->create(['object_address' => 'ул. Пустая ведомость']); $orderWithFilledValue = Order::factory()->create(['object_address' => 'ул. Заполненная']); $product = Product::factory()->create(); ProductSKU::factory()->create([ 'order_id' => $orderWithNullFactory->id, 'product_id' => $product->id, 'factory_number' => null, 'manufacture_date' => '2026-04-01', 'statement_number' => 'STAT-1', ]); ProductSKU::factory()->create([ 'order_id' => $orderWithBlankFactory->id, 'product_id' => $product->id, 'factory_number' => ' ', 'manufacture_date' => '2026-04-02', 'statement_number' => 'STAT-2', ]); ProductSKU::factory()->create([ 'order_id' => $orderWithNullDate->id, 'product_id' => $product->id, 'factory_number' => 'FN-000001', 'manufacture_date' => null, 'statement_number' => 'STAT-3', ]); ProductSKU::factory()->create([ 'order_id' => $orderWithBlankStatement->id, 'product_id' => $product->id, 'factory_number' => 'FN-000002', 'manufacture_date' => '2026-04-03', 'statement_number' => ' ', ]); ProductSKU::factory()->create([ 'order_id' => $orderWithFilledValue->id, 'product_id' => $product->id, 'factory_number' => 'FN-999999', 'manufacture_date' => '2026-04-04', 'statement_number' => 'STAT-9', ]); $factoryResponse = $this->actingAs($this->adminUser) ->get(route('product_sku.index', [ 'filters' => ['factory_number' => '-пусто-'], ])); $factoryResponse->assertOk(); $factoryAddresses = $factoryResponse->viewData('products_sku')->pluck('object_address')->all(); $this->assertContains('ул. Пустая фабрика', $factoryAddresses); $this->assertContains('ул. Пробелы фабрика', $factoryAddresses); $this->assertNotContains('ул. Заполненная', $factoryAddresses); $dateResponse = $this->actingAs($this->adminUser) ->get(route('product_sku.index', [ 'filters' => ['manufacture_date' => '-пусто-'], ])); $dateResponse->assertOk(); $dateAddresses = $dateResponse->viewData('products_sku')->pluck('object_address')->all(); $this->assertContains('ул. Пустая дата', $dateAddresses); $this->assertNotContains('ул. Заполненная', $dateAddresses); $statementResponse = $this->actingAs($this->adminUser) ->get(route('product_sku.index', [ 'filters' => ['statement_number' => '-пусто-'], ])); $statementResponse->assertOk(); $statementAddresses = $statementResponse->viewData('products_sku')->pluck('object_address')->all(); $this->assertContains('ул. Пустая ведомость', $statementAddresses); $this->assertNotContains('ул. Заполненная', $statementAddresses); } // ==================== Show ==================== public function test_admin_can_view_product_sku(): void { $sku = ProductSKU::factory()->create(); $response = $this->actingAs($this->adminUser) ->get(route('product_sku.show', $sku)); $response->assertStatus(200); $response->assertViewIs('products_sku.edit'); } public function test_manager_can_view_product_sku(): void { $sku = ProductSKU::factory()->create(); $response = $this->actingAs($this->managerUser) ->get(route('product_sku.show', $sku)); $response->assertStatus(200); $response->assertViewIs('products_sku.edit'); } public function test_product_sku_show_uses_nav_context_back_url(): void { $sku = ProductSKU::factory()->create(); $reclamation = \App\Models\Reclamation::factory()->create(); $indexResponse = $this->actingAs($this->adminUser) ->get(route('reclamations.index')); $nav = $indexResponse->viewData('nav'); $this->actingAs($this->adminUser) ->get(route('reclamations.show', [ 'reclamation' => $reclamation, 'nav' => $nav, ])) ->assertOk(); $response = $this->actingAs($this->adminUser) ->get(route('product_sku.show', [ 'product_sku' => $sku, 'nav' => $nav, ])); $response->assertOk(); $response->assertViewHas('nav', $nav); $response->assertViewHas('back_url', route('reclamations.show', [ 'reclamation' => $reclamation, ])); } // ==================== Update ==================== public function test_admin_can_update_product_sku(): void { $product = Product::factory()->create(); $order = Order::factory()->create(); $sku = ProductSKU::factory()->create([ 'product_id' => $product->id, 'order_id' => $order->id, ]); $response = $this->actingAs($this->adminUser) ->post(route('product_sku.update', $sku), [ 'product_id' => $product->id, 'order_id' => $order->id, 'status' => 'shipped', 'factory_number' => 'FN-999999', 'comment' => 'Updated by admin', ]); $response->assertRedirect(); $this->assertDatabaseHas('products_sku', [ 'id' => $sku->id, 'factory_number' => 'FN-999999', 'comment' => 'Updated by admin', ]); } public function test_manager_can_update_product_sku(): void { $product = Product::factory()->create(); $order = Order::factory()->create(); $sku = ProductSKU::factory()->create([ 'product_id' => $product->id, 'order_id' => $order->id, ]); $response = $this->actingAs($this->managerUser) ->post(route('product_sku.update', $sku), [ 'product_id' => $product->id, 'order_id' => $order->id, 'status' => 'needs', 'factory_number' => 'FN-777777', ]); $response->assertRedirect(); } public function test_update_product_sku_redirects_to_parent_url_from_nav_context(): void { $product = Product::factory()->create(); $order = Order::factory()->create(); $sku = ProductSKU::factory()->create([ 'product_id' => $product->id, 'order_id' => $order->id, ]); $reclamation = \App\Models\Reclamation::factory()->create(); $nav = 'product-sku-nav-token'; $response = $this->actingAs($this->adminUser) ->withSession([ 'navigation' => [ $nav => [ 'updated_at' => time(), 'stack' => [ route('reclamations.index'), route('reclamations.show', $reclamation), route('product_sku.show', $sku), ], ], ], ]) ->post(route('product_sku.update', $sku), [ 'nav' => $nav, 'product_id' => $product->id, 'order_id' => $order->id, 'status' => 'shipped', 'factory_number' => 'FN-NAV-123', 'comment' => 'Updated through nav', ]); $response->assertRedirect(route('reclamations.show', [ 'reclamation' => $reclamation, ])); } // ==================== Export ==================== public function test_admin_can_export_mafs(): void { Bus::fake(); $response = $this->actingAs($this->adminUser) ->post(route('mafs.export')); $response->assertRedirect(route('product_sku.index')); $response->assertSessionHas('success'); Bus::assertDispatched(ExportMafJob::class); } }