#!/usr/bin/env nu # Hetzner provider API client integration tests (with mocks) # Load mock responses def load-mock-responses []: nothing -> record { let mocks = (open ../../tests/mocks/mock_api_responses.json) $mocks } # Mock HTTP response handler def mock-http-response [endpoint: string]: nothing -> record { let mocks = (load-mock-responses) match $endpoint { "/servers" => { $mocks.servers_list } "/servers/12345" => { $mocks.server_info } "/volumes" => { $mocks.volumes_list } "/networks" => { $mocks.networks_list } "/floating_ips" => { $mocks.floating_ips_list } "/server_types" => { $mocks.server_types_list } "/error/401" => { $mocks.error_401 } "/error/404" => { $mocks.error_404 } _ => { error make {msg: $"Unknown endpoint: ($endpoint)"} } } } # Test framework def test-result [name: string, passed: bool]: nothing -> record { if $passed { print $"✓ ($name)" } else { print $"✗ ($name)" } {name: $name, passed: $passed} } # Test: GET request response structure def test_get_request_servers []: nothing -> record { let result = (do { let response = (mock-http-response "/servers") ($response | has servers) } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "GET /servers: response structure" $passed } # Test: GET request returns list def test_get_request_list []: nothing -> record { let result = (do { let response = (mock-http-response "/servers") ($response.servers | describe) =~ "list" } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "GET /servers: returns list" $passed } # Test: GET single server def test_get_single_server []: nothing -> record { let result = (do { let response = (mock-http-response "/servers/12345") ($response | has server) and (not ($response.server | is-empty)) } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "GET /servers/{id}: single server response" $passed } # Test: GET volumes list def test_get_volumes_list []: nothing -> record { let result = (do { let response = (mock-http-response "/volumes") ($response | has volumes) and (($response.volumes | describe) =~ "list") } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "GET /volumes: returns list" $passed } # Test: GET networks list def test_get_networks_list []: nothing -> record { let result = (do { let response = (mock-http-response "/networks") ($response | has networks) } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "GET /networks: returns list" $passed } # Test: GET floating IPs list def test_get_floating_ips_list []: nothing -> record { let result = (do { let response = (mock-http-response "/floating_ips") ($response | has floating_ips) } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "GET /floating_ips: returns list" $passed } # Test: GET server types list def test_get_server_types_list []: nothing -> record { let result = (do { let response = (mock-http-response "/server_types") ($response | has server_types) and (($response.server_types | length) > 0) } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "GET /server_types: returns list" $passed } # Test: Server type pricing structure def test_server_type_pricing []: nothing -> record { let result = (do { let response = (mock-http-response "/server_types") let st = ($response.server_types | first) { has_name: ($st | has name) has_cores: ($st | has cores) has_prices: ($st | has prices) } } | complete) let passed = ($result.exit_code == 0 and $result.stdout.has_name and $result.stdout.has_cores and $result.stdout.has_prices) test-result "server_types: pricing structure" $passed } # Test: Error response format (401) def test_error_401_response []: nothing -> record { let result = (do { let response = (mock-http-response "/error/401") ($response | has error) and ($response.error | has message) } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "error_response: 401 Unauthorized format" $passed } # Test: Error response format (404) def test_error_404_response []: nothing -> record { let result = (do { let response = (mock-http-response "/error/404") ($response | has error) and ($response.error.code == "not_found") } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "error_response: 404 Not Found format" $passed } # Test: Server pagination fields (if present) def test_response_server_count []: nothing -> record { let result = (do { let response = (mock-http-response "/servers") ($response.servers | length) } | complete) let passed = ($result.exit_code == 0 and $result.stdout > 0) test-result "response: contains servers" $passed } # Test: Unknown endpoint error def test_unknown_endpoint_error []: nothing -> record { let result = (do { mock-http-response "/unknown" } | complete) let passed = ($result.exit_code != 0) test-result "error_handling: unknown endpoint fails" $passed } # Test: Server ID type def test_server_id_type []: nothing -> record { let result = (do { let response = (mock-http-response "/servers") let server = ($response.servers | first) ($server.id | describe) =~ "int" } | complete) let passed = ($result.exit_code == 0 and $result.stdout) test-result "response: server ID is integer" $passed } # Main test runner def main []: nothing -> record { print "=== Hetzner API Client Integration Tests (Mock Mode) ===" print "" let results = [ (test_get_request_servers) (test_get_request_list) (test_get_single_server) (test_get_volumes_list) (test_get_networks_list) (test_get_floating_ips_list) (test_get_server_types_list) (test_server_type_pricing) (test_error_401_response) (test_error_404_response) (test_response_server_count) (test_unknown_endpoint_error) (test_server_id_type) ] print "" print "Test Summary:" print "=============" let passed = ($results | where {|r| $r.passed} | length) let failed = ($results | where {|r| not $r.passed} | length) let total = ($results | length) print $"Passed: ($passed)/$total" print $"Failed: ($failed)/$total" {passed: $passed, failed: $failed, total: $total} }