create(['role' => UserRole::Owner]); $response = $this->actingAs($owner)->post(route('zones.store'), [ 'name' => 'Гостиная', 'description' => 'Тест', ]); $response->assertRedirect(route('zones.index')); $this->assertDatabaseHas('zones', ['name' => 'Гостиная', 'user_id' => $owner->id]); } public function test_viewer_cannot_create_zone(): void { $viewer = User::factory()->create(['role' => UserRole::Viewer]); $response = $this->actingAs($viewer)->post(route('zones.store'), [ 'name' => 'Гостиная', ]); $response->assertForbidden(); $this->assertDatabaseMissing('zones', ['name' => 'Гостиная']); } public function test_viewer_can_view_zones_index(): void { $viewer = User::factory()->create(['role' => UserRole::Viewer]); Zone::forceCreate(['user_id' => $viewer->id, 'name' => 'Гроубокс']); $response = $this->actingAs($viewer)->get(route('zones.index')); $response->assertOk(); $response->assertInertia(fn (Assert $page) => $page ->component('Zones/Index') ->where('zones.0.name', 'Гроубокс') ); } public function test_zone_show_lists_its_devices_with_live_status(): void { $viewer = User::factory()->create(['role' => UserRole::Viewer]); $zone = Zone::forceCreate(['user_id' => $viewer->id, 'name' => 'Гроубокс']); $type = DeviceType::create([ 'code' => 'fan', 'category' => DeviceCategory::Actuator, 'capabilities' => ['turn_on'], ]); Device::forceCreate([ 'user_id' => $viewer->id, 'zone_id' => $zone->id, 'device_type_id' => $type->id, 'name' => 'Вентилятор', 'external_id' => 'fan-1', 'protocol' => 'mqtt', ]); $this->mock(DeviceShadow::class, function ($mock) { $mock->shouldReceive('statuses')->once()->with(['fan-1'])->andReturn(['fan-1' => 'online']); }); $response = $this->actingAs($viewer)->get(route('zones.show', $zone)); $response->assertOk(); $response->assertInertia(fn (Assert $page) => $page ->component('Zones/Show') ->where('zone.name', 'Гроубокс') ->where('devices.0.name', 'Вентилятор') ->where('devices.0.status', 'online') ); } public function test_viewer_cannot_delete_zone(): void { $viewer = User::factory()->create(['role' => UserRole::Viewer]); $zone = Zone::forceCreate(['user_id' => $viewer->id, 'name' => 'Гроубокс']); $response = $this->actingAs($viewer)->delete(route('zones.destroy', $zone)); $response->assertForbidden(); $this->assertDatabaseHas('zones', ['id' => $zone->id]); } public function test_guest_is_redirected_to_login(): void { $response = $this->get(route('zones.index')); $response->assertRedirect(route('login')); } }