create(); $network = ModuleNetwork::create(['name' => 'test-net']); $order = Order::create(['order_num' => 'ORD-' . Str::random(10), 'customer_id' => $customer->id]); $orderItem = OrderItem::create(['order_id' => $order->id, 'server_name' => 'vm-test.local']); $service = Service::create([ 'customer_id' => $customer->id, 'order_item_id' => $orderItem->id, 'server_name' => 'vm-test.local', 'status' => $status, ]); $currentIp = ModuleIpAddress::create([ 'module_network_id' => $network->id, 'ip' => '103.1.1.10', 'status' => 1, ]); $vm = ModuleVmware::create([ 'name' => 'vm-test', 'customer_id' => $customer->id, 'vmware_id' => 'vm-9001', 'order_id' => $order->id, 'module_ip_address' => $currentIp->id, 'ip' => '103.1.1.10', 'status' => 1, 'service_id' => $service->id, ]); IpPool::create([ 'uuid' => (string) Str::uuid(), 'ip_address' => '103.1.1.10', 'module_network_id' => $network->id, 'status' => 'assigned', 'service_id' => $service->id, ]); $freePool = IpPool::create([ 'uuid' => (string) Str::uuid(), 'ip_address' => '103.1.1.20', 'module_network_id' => $network->id, 'status' => 'free', 'gateway' => '103.1.1.1', ]); $service->refresh(); $service->update(['status' => $status]); $otherCustomer = Customer::factory()->create(); $otherOrder = Order::create(['order_num' => 'ORD-' . Str::random(10), 'customer_id' => $otherCustomer->id]); $otherService = Service::create([ 'customer_id' => $otherCustomer->id, 'status' => 'active', ]); $usedPool = IpPool::create([ 'uuid' => (string) Str::uuid(), 'ip_address' => '103.1.1.30', 'module_network_id' => $network->id, 'status' => 'assigned', 'service_id' => $otherService->id, ]); return compact('customer', 'network', 'service', 'vm', 'freePool', 'usedPool'); } private function changeIpPayload(array $vars, string $ip): array { return [ 'server_name' => $vars['service']->server_name, 'ip_address' => $ip, 'guest_user' => 'root', 'guest_password' => 'secret123', ]; } public function test_change_ip_outside_pool_returns_422(): void { $vars = $this->makeActiveServiceWithVm(); $response = $this->actingAs($vars['customer'], 'client') ->withHeaders(['x-access-token' => $this->buildClientAccessToken()]) ->postJson('/v1/system/vm-change-ip', $this->changeIpPayload($vars, '103.1.1.99')); $response->assertStatus(422); } public function test_change_ip_already_in_use_returns_422(): void { $vars = $this->makeActiveServiceWithVm(); $response = $this->actingAs($vars['customer'], 'client') ->withHeaders(['x-access-token' => $this->buildClientAccessToken()]) ->postJson('/v1/system/vm-change-ip', $this->changeIpPayload($vars, '103.1.1.30')); $response->assertStatus(422); } public function test_change_ip_to_free_pool_ip_dispatches_job_with_pool_gateway(): void { Queue::fake(); $vars = $this->makeActiveServiceWithVm(); $response = $this->actingAs($vars['customer'], 'client') ->withHeaders(['x-access-token' => $this->buildClientAccessToken()]) ->postJson('/v1/system/vm-change-ip', $this->changeIpPayload($vars, '103.1.1.20')); $response->assertStatus(200)->assertJson(['success' => true]); Queue::assertPushed(ChangeIpVMJob::class, function (ChangeIpVMJob $job) use ($vars) { return $job->ipAddress === '103.1.1.20' && $job->gateway === '103.1.1.1' && $job->newIpPoolId === $vars['freePool']->id; }); $this->assertSame('assigned', $vars['freePool']->fresh()->status); } public function test_power_on_for_suspended_service_returns_403(): void { $vars = $this->makeActiveServiceWithVm(status: 'suspended'); $response = $this->actingAs($vars['customer'], 'client') ->withHeaders(['x-access-token' => $this->buildClientAccessToken()]) ->postJson('/v1/system/vm-power-on', ['product' => $vars['vm']->id]); $response->assertStatus(403); } }