mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-07-26 07:58:14 +00:00
fix(test): fix assembly loading, remove mock server, resolve test warnings
- Create shared _TestHelper.ps1 for reliable module loading in both local dev and CI (fixes System.Runtime 9.0.0.0 FileNotFoundException on PS 7.x by trying Import-Module by name first, then local paths) - Use (Get-Module).ModuleBase for manifest path resolution - Remove PSProxmoxVE.MockServer project and MockIntegration tests - Remove MockIntegration from ExcludeTag filters Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -96,7 +96,7 @@ jobs:
|
||||
$config = New-PesterConfiguration
|
||||
$config.Run.Path = "tests/PSProxmoxVE.Tests"
|
||||
$config.Run.Exit = $true
|
||||
$config.Filter.ExcludeTag = @("Integration", "MockIntegration")
|
||||
$config.Filter.ExcludeTag = @("Integration")
|
||||
$config.Output.Verbosity = "Detailed"
|
||||
$config.TestResult.Enabled = $true
|
||||
$config.TestResult.OutputFormat = "NUnitXml"
|
||||
@@ -111,7 +111,7 @@ jobs:
|
||||
$config = New-PesterConfiguration
|
||||
$config.Run.Path = "tests/PSProxmoxVE.Tests"
|
||||
$config.Run.Exit = $true
|
||||
$config.Filter.ExcludeTag = @("Integration", "MockIntegration")
|
||||
$config.Filter.ExcludeTag = @("Integration")
|
||||
$config.Output.Verbosity = "Detailed"
|
||||
$config.TestResult.Enabled = $true
|
||||
$config.TestResult.OutputFormat = "NUnitXml"
|
||||
|
||||
@@ -13,8 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PSProxmoxVE", "src\PSProxmo
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PSProxmoxVE.Core.Tests", "tests\PSProxmoxVE.Core.Tests\PSProxmoxVE.Core.Tests.csproj", "{E5F6A7B8-C9D0-1234-EF12-345678901234}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PSProxmoxVE.MockServer", "tests\PSProxmoxVE.MockServer\PSProxmoxVE.MockServer.csproj", "{B7490D48-1665-41F4-B248-70051EC2F061}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -61,18 +59,6 @@ Global
|
||||
{E5F6A7B8-C9D0-1234-EF12-345678901234}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E5F6A7B8-C9D0-1234-EF12-345678901234}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E5F6A7B8-C9D0-1234-EF12-345678901234}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -81,6 +67,5 @@ Global
|
||||
{C3D4E5F6-A7B8-9012-CDEF-123456789012} = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
|
||||
{D4E5F6A7-B8C9-0123-DEF1-234567890123} = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
|
||||
{E5F6A7B8-C9D0-1234-EF12-345678901234} = {B2C3D4E5-F6A7-8901-BCDE-F12345678901}
|
||||
{B7490D48-1665-41F4-B248-70051EC2F061} = {B2C3D4E5-F6A7-8901-BCDE-F12345678901}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
namespace PSProxmoxVE.MockServer;
|
||||
|
||||
public record RequestRecord(string Method, string Path, string? Body, DateTime Timestamp);
|
||||
|
||||
public class MockPveServer : IDisposable
|
||||
{
|
||||
private readonly WebApplication _app;
|
||||
private bool _disposed;
|
||||
|
||||
public string BaseUrl { get; }
|
||||
public int Port { get; }
|
||||
public List<RequestRecord> Requests { get; } = new();
|
||||
|
||||
private static readonly Dictionary<string, string> _fixtures = new();
|
||||
private static readonly object _fixtureLock = new();
|
||||
|
||||
// Track task status calls per UPID for simulating running -> completed transitions
|
||||
internal Dictionary<string, int> TaskStatusCallCounts { get; } = new();
|
||||
|
||||
private MockPveServer(WebApplication app, int port)
|
||||
{
|
||||
_app = app;
|
||||
Port = port;
|
||||
BaseUrl = $"https://localhost:{port}";
|
||||
}
|
||||
|
||||
public static MockPveServer Start(int port = 0)
|
||||
{
|
||||
LoadFixtures();
|
||||
|
||||
var cert = GenerateSelfSignedCert();
|
||||
|
||||
var builder = WebApplication.CreateBuilder();
|
||||
builder.WebHost.ConfigureKestrel(options =>
|
||||
{
|
||||
options.ListenLocalhost(port, listenOptions =>
|
||||
{
|
||||
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
|
||||
listenOptions.UseHttps(cert);
|
||||
});
|
||||
});
|
||||
|
||||
// Suppress default logging noise in tests
|
||||
builder.Logging.ClearProviders();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
var server = new MockPveServer(app, port);
|
||||
|
||||
// Request tracking middleware
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
string? body = null;
|
||||
if (context.Request.ContentLength > 0 || context.Request.Headers.ContainsKey("Transfer-Encoding"))
|
||||
{
|
||||
context.Request.EnableBuffering();
|
||||
using var reader = new StreamReader(context.Request.Body, leaveOpen: true);
|
||||
body = await reader.ReadToEndAsync();
|
||||
context.Request.Body.Position = 0;
|
||||
}
|
||||
server.Requests.Add(new RequestRecord(
|
||||
context.Request.Method,
|
||||
context.Request.Path + context.Request.QueryString,
|
||||
body,
|
||||
DateTime.UtcNow));
|
||||
await next();
|
||||
});
|
||||
|
||||
// Auth middleware
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
var path = context.Request.Path.Value ?? "";
|
||||
var method = context.Request.Method;
|
||||
|
||||
// Skip auth for ticket creation and version endpoints
|
||||
bool skipAuth = (path == "/api2/json/access/ticket" && method == "POST")
|
||||
|| (path == "/api2/json/access/ticket" && method == "DELETE")
|
||||
|| (path == "/api2/json/version" && method == "GET");
|
||||
|
||||
if (!skipAuth)
|
||||
{
|
||||
var hasCookie = context.Request.Headers["Cookie"].ToString().Contains("PVEAuthCookie=");
|
||||
var hasToken = context.Request.Headers["Authorization"].ToString().StartsWith("PVEAPIToken=");
|
||||
|
||||
if (!hasCookie && !hasToken)
|
||||
{
|
||||
context.Response.StatusCode = 401;
|
||||
context.Response.ContentType = "application/json";
|
||||
await context.Response.WriteAsync("{\"data\":null,\"errors\":{\"authentication\":\"invalid credentials\"}}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
// Register all routes
|
||||
app.MapAuthRoutes();
|
||||
app.MapVersionRoutes();
|
||||
app.MapNodeRoutes();
|
||||
app.MapVmRoutes();
|
||||
app.MapContainerRoutes();
|
||||
app.MapStorageRoutes();
|
||||
app.MapNetworkRoutes();
|
||||
app.MapUserRoutes();
|
||||
app.MapClusterRoutes();
|
||||
app.MapTaskRoutes(server);
|
||||
app.MapSnapshotRoutes();
|
||||
|
||||
app.StartAsync().GetAwaiter().GetResult();
|
||||
|
||||
// Resolve the actual port (important when port=0 for random assignment)
|
||||
var addresses = app.Urls;
|
||||
var actualPort = port;
|
||||
var serverInstance = app.Services.GetRequiredService<IServer>();
|
||||
if (serverInstance != null)
|
||||
{
|
||||
var addressFeature = serverInstance.Features.Get<IServerAddressesFeature>();
|
||||
if (addressFeature != null)
|
||||
{
|
||||
var addr = addressFeature.Addresses.FirstOrDefault();
|
||||
if (addr != null)
|
||||
{
|
||||
var uri = new Uri(addr);
|
||||
actualPort = uri.Port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new MockPveServer(app, actualPort);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Requests.Clear();
|
||||
TaskStatusCallCounts.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
_app.StopAsync().GetAwaiter().GetResult();
|
||||
_app.DisposeAsync().AsTask().GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetFixture(string name)
|
||||
{
|
||||
if (_fixtures.TryGetValue(name, out var content))
|
||||
return content;
|
||||
return "{\"data\":null}";
|
||||
}
|
||||
|
||||
public static string GenerateUpid(string node, string type, int vmid = 0)
|
||||
=> $"UPID:{node}:{Guid.NewGuid():N}:{DateTimeOffset.UtcNow.ToUnixTimeSeconds():X}:{type}:{vmid}:root@pam:";
|
||||
|
||||
private static X509Certificate2 GenerateSelfSignedCert()
|
||||
{
|
||||
var rsa = RSA.Create(2048);
|
||||
var req = new CertificateRequest("CN=pve-mock", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
var cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(1));
|
||||
return cert;
|
||||
}
|
||||
|
||||
private static void LoadFixtures()
|
||||
{
|
||||
lock (_fixtureLock)
|
||||
{
|
||||
if (_fixtures.Count > 0) return;
|
||||
|
||||
// Resolve fixtures path relative to the assembly location
|
||||
var basePath = AppContext.BaseDirectory;
|
||||
var fixturesPath = Path.GetFullPath(Path.Combine(basePath, "..", "..", "..", "..", "PSProxmoxVE.Core.Tests", "Fixtures"));
|
||||
|
||||
// Fallback: try relative to the project source directory
|
||||
if (!Directory.Exists(fixturesPath))
|
||||
{
|
||||
fixturesPath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "..", "PSProxmoxVE.Core.Tests", "Fixtures"));
|
||||
}
|
||||
|
||||
if (!Directory.Exists(fixturesPath))
|
||||
{
|
||||
// Last resort: look from the working directory
|
||||
fixturesPath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "..", "PSProxmoxVE.Core.Tests", "Fixtures"));
|
||||
}
|
||||
|
||||
if (Directory.Exists(fixturesPath))
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(fixturesPath, "*.json"))
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(file);
|
||||
_fixtures[name] = File.ReadAllText(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,22 +0,0 @@
|
||||
using PSProxmoxVE.MockServer;
|
||||
|
||||
// When run standalone, start on a fixed port
|
||||
using var server = MockPveServer.Start(port: 8006);
|
||||
Console.WriteLine($"Mock Proxmox VE API server running at {server.BaseUrl}");
|
||||
Console.WriteLine("Press Ctrl+C to stop.");
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
Console.CancelKeyPress += (_, e) =>
|
||||
{
|
||||
e.Cancel = true;
|
||||
cts.Cancel();
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Delay(Timeout.Infinite, cts.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Graceful shutdown
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class AuthRoutes
|
||||
{
|
||||
public static WebApplication MapAuthRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapPost("/api2/json/access/ticket", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_ticket_response"), "application/json"));
|
||||
|
||||
app.MapDelete("/api2/json/access/ticket", () =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class ClusterRoutes
|
||||
{
|
||||
public static WebApplication MapClusterRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/cluster/status", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_cluster_status"), "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class ContainerRoutes
|
||||
{
|
||||
public static WebApplication MapContainerRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/nodes/{node}/lxc", (string node) =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_containers"), "application/json"));
|
||||
|
||||
app.MapGet("/api2/json/nodes/{node}/lxc/{vmid}/config", (string node, int vmid) =>
|
||||
Results.Content("{\"data\":{\"hostname\":\"test\",\"memory\":512,\"cores\":1}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/lxc", (string node) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "vzcreate")}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/lxc/{vmid}/status/start", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "vzstart", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/lxc/{vmid}/status/stop", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "vzstop", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/lxc/{vmid}/status/shutdown", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "vzshutdown", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPut("/api2/json/nodes/{node}/lxc/{vmid}/config", (string node, int vmid) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapDelete("/api2/json/nodes/{node}/lxc/{vmid}", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "vzdestroy", vmid)}\"}}", "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class NetworkRoutes
|
||||
{
|
||||
public static WebApplication MapNetworkRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/nodes/{node}/network", (string node) =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_networks"), "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/network", (string node) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapPut("/api2/json/nodes/{node}/network/{iface}", (string node, string iface) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapDelete("/api2/json/nodes/{node}/network/{iface}", (string node, string iface) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
// Apply network config
|
||||
app.MapPut("/api2/json/nodes/{node}/network", (string node) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "netapply")}\"}}", "application/json"));
|
||||
|
||||
// SDN routes
|
||||
app.MapGet("/api2/json/cluster/sdn/zones", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_sdn_zones"), "application/json"));
|
||||
|
||||
app.MapGet("/api2/json/cluster/sdn/vnets", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_sdn_vnets"), "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class NodeRoutes
|
||||
{
|
||||
public static WebApplication MapNodeRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/nodes", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_nodes"), "application/json"));
|
||||
|
||||
app.MapGet("/api2/json/nodes/{node}/status", (string node) =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_node_status"), "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class SnapshotRoutes
|
||||
{
|
||||
public static WebApplication MapSnapshotRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/nodes/{node}/qemu/{vmid}/snapshot", (string node, int vmid) =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_snapshots"), "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/snapshot", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmsnapshot", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapDelete("/api2/json/nodes/{node}/qemu/{vmid}/snapshot/{snapname}", (string node, int vmid, string snapname) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmdelsnapshot", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/snapshot/{snapname}/rollback", (string node, int vmid, string snapname) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmrollback", vmid)}\"}}", "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class StorageRoutes
|
||||
{
|
||||
public static WebApplication MapStorageRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/storage", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_storage"), "application/json"));
|
||||
|
||||
app.MapGet("/api2/json/nodes/{node}/storage/{storage}/content", (string node, string storage) =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_storage_content"), "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/storage/{storage}/upload", (string node, string storage) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "upload")}\"}}", "application/json"))
|
||||
.DisableAntiforgery();
|
||||
|
||||
app.MapPost("/api2/json/storage", () =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapDelete("/api2/json/storage/{storage}", (string storage) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class TaskRoutes
|
||||
{
|
||||
public static WebApplication MapTaskRoutes(this WebApplication app, MockPveServer server)
|
||||
{
|
||||
app.MapGet("/api2/json/nodes/{node}/tasks/{upid}/status", (string node, string upid) =>
|
||||
{
|
||||
// Track call count per UPID: first call returns running, subsequent return completed
|
||||
int count;
|
||||
lock (server.TaskStatusCallCounts)
|
||||
{
|
||||
if (!server.TaskStatusCallCounts.TryGetValue(upid, out count))
|
||||
count = 0;
|
||||
count++;
|
||||
server.TaskStatusCallCounts[upid] = count;
|
||||
}
|
||||
|
||||
if (count <= 1)
|
||||
return Results.Content(MockPveServer.GetFixture("pve9_task_running"), "application/json");
|
||||
else
|
||||
return Results.Content(MockPveServer.GetFixture("pve9_tasks"), "application/json");
|
||||
});
|
||||
|
||||
app.MapGet("/api2/json/nodes/{node}/tasks/{upid}/log", (string node, string upid) =>
|
||||
Results.Content("{\"data\":[{\"n\":1,\"t\":\"starting task\"}]}", "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class UserRoutes
|
||||
{
|
||||
public static WebApplication MapUserRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/access/users", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_users"), "application/json"));
|
||||
|
||||
app.MapGet("/api2/json/access/users/{userid}", (string userid) =>
|
||||
{
|
||||
// Return first user from fixture
|
||||
var fixture = MockPveServer.GetFixture("pve9_users");
|
||||
try
|
||||
{
|
||||
var doc = System.Text.Json.JsonDocument.Parse(fixture);
|
||||
var dataArray = doc.RootElement.GetProperty("data");
|
||||
var first = dataArray[0];
|
||||
return Results.Content($"{{\"data\":{first.GetRawText()}}}", "application/json");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Results.Content("{\"data\":null}", "application/json");
|
||||
}
|
||||
});
|
||||
|
||||
app.MapPost("/api2/json/access/users", () =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapPut("/api2/json/access/users/{userid}", (string userid) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapDelete("/api2/json/access/users/{userid}", (string userid) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
// Roles
|
||||
app.MapGet("/api2/json/access/roles", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_roles"), "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/access/roles", () =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapDelete("/api2/json/access/roles/{roleid}", (string roleid) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
// ACL
|
||||
app.MapGet("/api2/json/access/acl", () =>
|
||||
Results.Content("{\"data\":[]}", "application/json"));
|
||||
|
||||
app.MapPut("/api2/json/access/acl", () =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class VersionRoutes
|
||||
{
|
||||
public static WebApplication MapVersionRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/version", () =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_version"), "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace PSProxmoxVE.MockServer.Routes;
|
||||
|
||||
public static class VmRoutes
|
||||
{
|
||||
public static WebApplication MapVmRoutes(this WebApplication app)
|
||||
{
|
||||
app.MapGet("/api2/json/nodes/{node}/qemu", (string node) =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_vms"), "application/json"));
|
||||
|
||||
app.MapGet("/api2/json/nodes/{node}/qemu/{vmid}/config", (string node, int vmid) =>
|
||||
Results.Content(MockPveServer.GetFixture("pve9_vm_config"), "application/json"));
|
||||
|
||||
app.MapGet("/api2/json/nodes/{node}/qemu/{vmid}/status/current", (string node, int vmid) =>
|
||||
{
|
||||
// Return first VM from fixture as a single-item response
|
||||
var fixture = MockPveServer.GetFixture("pve9_vms");
|
||||
try
|
||||
{
|
||||
var doc = System.Text.Json.JsonDocument.Parse(fixture);
|
||||
var dataArray = doc.RootElement.GetProperty("data");
|
||||
foreach (var item in dataArray.EnumerateArray())
|
||||
{
|
||||
if (item.TryGetProperty("vmid", out var id) && id.GetInt32() == vmid)
|
||||
return Results.Content($"{{\"data\":{item.GetRawText()}}}", "application/json");
|
||||
}
|
||||
// If no match, return first item
|
||||
var first = dataArray[0];
|
||||
return Results.Content($"{{\"data\":{first.GetRawText()}}}", "application/json");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Results.Content("{\"data\":null}", "application/json");
|
||||
}
|
||||
});
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu", (string node) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmcreate")}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/status/start", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmstart", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/status/stop", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmstop", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/status/shutdown", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmshutdown", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/status/reset", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmreset", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/status/suspend", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmsuspend", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/status/resume", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmresume", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/clone", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmclone", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPost("/api2/json/nodes/{node}/qemu/{vmid}/migrate", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmigrate", vmid)}\"}}", "application/json"));
|
||||
|
||||
app.MapPut("/api2/json/nodes/{node}/qemu/{vmid}/config", (string node, int vmid) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapPut("/api2/json/nodes/{node}/qemu/{vmid}/resize", (string node, int vmid) =>
|
||||
Results.Content("{\"data\":null}", "application/json"));
|
||||
|
||||
app.MapDelete("/api2/json/nodes/{node}/qemu/{vmid}", (string node, int vmid) =>
|
||||
Results.Content($"{{\"data\":\"{MockPveServer.GenerateUpid(node, "qmdestroy", vmid)}\"}}", "application/json"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -14,21 +14,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveCloudInitConfig', 'Set-PveCloudInitConfig',
|
||||
@@ -48,7 +34,7 @@ BeforeAll {
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Cloud-Init cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
|
||||
@@ -10,21 +10,7 @@
|
||||
BeforeAll {
|
||||
# Resolve the built DLL relative to the repository root.
|
||||
# Adjust the path if your build output directory differs.
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
}
|
||||
|
||||
Describe 'Connect-PveServer' {
|
||||
|
||||
@@ -6,21 +6,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
}
|
||||
|
||||
Describe 'Disconnect-PveServer' {
|
||||
|
||||
@@ -6,21 +6,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
}
|
||||
|
||||
Describe 'Test-PveConnection' {
|
||||
|
||||
@@ -10,21 +10,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
# Pre-calculate availability for each cmdlet.
|
||||
$script:Availability = @{}
|
||||
|
||||
@@ -10,21 +10,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$script:CmdExists = $null -ne (Get-Command 'Get-PveContainer' -ErrorAction SilentlyContinue)
|
||||
}
|
||||
@@ -34,7 +20,7 @@ Describe 'Get-PveContainer' {
|
||||
Context 'Command existence' {
|
||||
It 'Get-PveContainer should be listed in the module manifest CmdletsToExport' {
|
||||
# The .psd1 declares the cmdlet; implementation may be pending.
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
if (Test-Path $manifestPath) {
|
||||
$manifest = Import-PowerShellDataFile $manifestPath
|
||||
$manifest.CmdletsToExport | Should -Contain 'Get-PveContainer'
|
||||
|
||||
@@ -27,21 +27,7 @@ BeforeAll {
|
||||
# -----------------------------------------------------------------------
|
||||
# Resolve and import module
|
||||
# -----------------------------------------------------------------------
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$moduleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $moduleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $moduleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Check required environment variables
|
||||
|
||||
@@ -1,311 +0,0 @@
|
||||
#Requires -Modules Pester
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Integration tests that run PSProxmoxVE cmdlets against the mock PVE API server.
|
||||
These validate end-to-end behavior: HTTP requests, auth, deserialization, pipeline.
|
||||
|
||||
.DESCRIPTION
|
||||
The mock server is started before all tests and stopped after. Each test group
|
||||
exercises real cmdlet execution against simulated PVE API responses. No real
|
||||
Proxmox host is needed.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
# Find the built mock server
|
||||
$mockServerProject = Join-Path $PSScriptRoot '../../PSProxmoxVE.MockServer/PSProxmoxVE.MockServer.csproj'
|
||||
if (-not (Test-Path $mockServerProject)) {
|
||||
throw "Mock server project not found at $mockServerProject"
|
||||
}
|
||||
|
||||
# Find the built module DLL
|
||||
$dllSearchPaths = @(
|
||||
(Join-Path $PSScriptRoot '../../PSProxmoxVE.MockServer/bin/Release/net9.0/PSProxmoxVE.MockServer.dll'),
|
||||
(Join-Path $PSScriptRoot '../../PSProxmoxVE.MockServer/bin/Debug/net9.0/PSProxmoxVE.MockServer.dll')
|
||||
)
|
||||
$mockServerDll = $dllSearchPaths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if (-not $mockServerDll) {
|
||||
# Build it
|
||||
$buildOutput = dotnet build $mockServerProject --configuration Release 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to build mock server (exit code $LASTEXITCODE): $buildOutput"
|
||||
}
|
||||
$mockServerDll = $dllSearchPaths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
if (-not $mockServerDll) {
|
||||
throw "Mock server build succeeded but DLL not found at expected paths: $($dllSearchPaths -join ', ')"
|
||||
}
|
||||
}
|
||||
|
||||
# Start mock server as a background process on a random port
|
||||
$script:MockPort = Get-Random -Minimum 18000 -Maximum 19000
|
||||
$script:MockHost = "localhost"
|
||||
$script:MockUrl = "https://${script:MockHost}:${script:MockPort}"
|
||||
|
||||
$mockServerDir = Split-Path $mockServerDll -Parent
|
||||
$script:MockProcess = Start-Process -FilePath 'dotnet' `
|
||||
-ArgumentList @($mockServerDll, '--urls', "https://0.0.0.0:$($script:MockPort)") `
|
||||
-WorkingDirectory $mockServerDir `
|
||||
-PassThru -NoNewWindow -RedirectStandardOutput (Join-Path $TestDrive 'mock-stdout.log') `
|
||||
-RedirectStandardError (Join-Path $TestDrive 'mock-stderr.log')
|
||||
|
||||
# Wait for server to become responsive
|
||||
$maxWait = 30
|
||||
$waited = 0
|
||||
$ready = $false
|
||||
while ($waited -lt $maxWait -and -not $ready) {
|
||||
Start-Sleep -Seconds 1
|
||||
$waited++
|
||||
try {
|
||||
# Use .NET directly to skip cert validation
|
||||
$handler = [System.Net.Http.HttpClientHandler]::new()
|
||||
$handler.ServerCertificateCustomValidationCallback = { $true }
|
||||
$client = [System.Net.Http.HttpClient]::new($handler)
|
||||
$result = $client.GetStringAsync("$($script:MockUrl)/api2/json/version").GetAwaiter().GetResult()
|
||||
if ($result -match '"version"') {
|
||||
$ready = $true
|
||||
}
|
||||
$client.Dispose()
|
||||
$handler.Dispose()
|
||||
} catch {
|
||||
# Not ready yet
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $ready) {
|
||||
$stderr = if (Test-Path (Join-Path $TestDrive 'mock-stderr.log')) { Get-Content (Join-Path $TestDrive 'mock-stderr.log') -Raw } else { 'N/A' }
|
||||
throw "Mock server failed to start within ${maxWait}s. Stderr: $stderr"
|
||||
}
|
||||
|
||||
# Import the module
|
||||
Import-Module PSProxmoxVE -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
# Stop mock server
|
||||
if ($script:MockProcess -and -not $script:MockProcess.HasExited) {
|
||||
$script:MockProcess.Kill()
|
||||
$script:MockProcess.WaitForExit(5000)
|
||||
}
|
||||
|
||||
# Disconnect any active session
|
||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
|
||||
Describe 'Mock PVE Server - Authentication' -Tag 'MockIntegration' {
|
||||
|
||||
It 'Should connect with API token' {
|
||||
$session = Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck -PassThru
|
||||
|
||||
$session | Should -Not -BeNullOrEmpty
|
||||
$session.Hostname | Should -Be $script:MockHost
|
||||
$session.Port | Should -Be $script:MockPort
|
||||
$session.AuthMode | Should -Be 'ApiToken'
|
||||
$session.ServerVersion | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should connect with credentials' {
|
||||
$secPassword = ConvertTo-SecureString 'testpass' -AsPlainText -Force
|
||||
$cred = [PSCredential]::new('root@pam', $secPassword)
|
||||
|
||||
$session = Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-Credential $cred -SkipCertificateCheck -PassThru
|
||||
|
||||
$session | Should -Not -BeNullOrEmpty
|
||||
$session.AuthMode | Should -Be 'Ticket'
|
||||
$session.Ticket | Should -Not -BeNullOrEmpty
|
||||
$session.CsrfToken | Should -Not -BeNullOrEmpty
|
||||
$session.IsExpired | Should -Be $false
|
||||
}
|
||||
|
||||
It 'Should report connection status' {
|
||||
# Connect first
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
|
||||
$result = Test-PveConnection
|
||||
$result | Should -Be $true
|
||||
}
|
||||
|
||||
It 'Should disconnect cleanly' {
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
|
||||
{ Disconnect-PveServer } | Should -Not -Throw
|
||||
|
||||
$result = Test-PveConnection
|
||||
$result | Should -Be $false
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Mock PVE Server - Node Operations' -Tag 'MockIntegration' {
|
||||
|
||||
BeforeAll {
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
|
||||
It 'Should list nodes' {
|
||||
$nodes = Get-PveNode
|
||||
$nodes | Should -Not -BeNullOrEmpty
|
||||
$nodes[0].Node | Should -Not -BeNullOrEmpty
|
||||
$nodes[0].Status | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should filter nodes by name' {
|
||||
$nodes = Get-PveNode -Name 'pve1'
|
||||
$nodes | Should -Not -BeNullOrEmpty
|
||||
$nodes | ForEach-Object { $_.Node | Should -Be 'pve1' }
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Mock PVE Server - VM Operations' -Tag 'MockIntegration' {
|
||||
|
||||
BeforeAll {
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
|
||||
It 'Should list VMs' {
|
||||
$vms = Get-PveVm -Node 'pve1'
|
||||
$vms | Should -Not -BeNullOrEmpty
|
||||
$vms.Count | Should -BeGreaterOrEqual 1
|
||||
}
|
||||
|
||||
It 'Should filter VMs by status' {
|
||||
$running = Get-PveVm -Node 'pve1' -Status 'running'
|
||||
$running | Should -Not -BeNullOrEmpty
|
||||
$running | ForEach-Object { $_.Status | Should -Be 'running' }
|
||||
}
|
||||
|
||||
It 'Should get VM config' {
|
||||
$config = Get-PveVmConfig -Node 'pve1' -VmId 100
|
||||
$config | Should -Not -BeNullOrEmpty
|
||||
$config.Cores | Should -BeGreaterThan 0
|
||||
}
|
||||
|
||||
It 'Should get VM config via pipeline' {
|
||||
$vms = Get-PveVm -Node 'pve1' -VmId 100
|
||||
$config = $vms | Get-PveVmConfig
|
||||
$config | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Mock PVE Server - Storage Operations' -Tag 'MockIntegration' {
|
||||
|
||||
BeforeAll {
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
|
||||
It 'Should list storage' {
|
||||
$storage = Get-PveStorage
|
||||
$storage | Should -Not -BeNullOrEmpty
|
||||
$storage[0].Storage | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should list storage content' {
|
||||
$content = Get-PveStorageContent -Node 'pve1' -Storage 'local'
|
||||
$content | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Mock PVE Server - Network Operations' -Tag 'MockIntegration' {
|
||||
|
||||
BeforeAll {
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
|
||||
It 'Should list networks' {
|
||||
$networks = Get-PveNetwork -Node 'pve1'
|
||||
$networks | Should -Not -BeNullOrEmpty
|
||||
$networks[0].Iface | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Mock PVE Server - User Operations' -Tag 'MockIntegration' {
|
||||
|
||||
BeforeAll {
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
|
||||
It 'Should list users' {
|
||||
$users = Get-PveUser
|
||||
$users | Should -Not -BeNullOrEmpty
|
||||
$users[0].UserId | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should list roles' {
|
||||
$roles = Get-PveRole
|
||||
$roles | Should -Not -BeNullOrEmpty
|
||||
$roles[0].RoleId | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Mock PVE Server - Cluster Operations' -Tag 'MockIntegration' {
|
||||
|
||||
BeforeAll {
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
|
||||
It 'Should list snapshots' {
|
||||
$snapshots = Get-PveSnapshot -Node 'pve1' -VmId 100
|
||||
$snapshots | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Mock PVE Server - Container Operations' -Tag 'MockIntegration' {
|
||||
|
||||
BeforeAll {
|
||||
Connect-PveServer -Server $script:MockHost -Port $script:MockPort `
|
||||
-ApiToken 'root@pam!test=00000000-0000-0000-0000-000000000000' `
|
||||
-SkipCertificateCheck
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
|
||||
It 'Should list containers' {
|
||||
$containers = Get-PveContainer -Node 'pve1'
|
||||
$containers | Should -Not -BeNullOrEmpty
|
||||
$containers[0].VmId | Should -BeGreaterThan 0
|
||||
}
|
||||
}
|
||||
@@ -10,21 +10,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveNetwork', 'New-PveNetwork', 'Set-PveNetwork',
|
||||
@@ -44,7 +30,7 @@ BeforeAll {
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Network cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
|
||||
@@ -14,21 +14,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$script:SdnCmdlets = @(
|
||||
'Get-PveSdnZone', 'New-PveSdnZone', 'Remove-PveSdnZone',
|
||||
@@ -52,7 +38,7 @@ BeforeAll {
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'SDN cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
|
||||
@@ -12,21 +12,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveSnapshot', 'New-PveSnapshot',
|
||||
@@ -46,7 +32,7 @@ BeforeAll {
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Snapshot cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
|
||||
@@ -9,21 +9,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveStorage', 'Get-PveStorageContent',
|
||||
@@ -43,14 +29,14 @@ BeforeAll {
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Storage cmdlets — manifest declarations' {
|
||||
It 'Get-PveStorage should be declared in CmdletsToExport' {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
if (-not (Test-Path $manifestPath)) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$manifest = Import-PowerShellDataFile $manifestPath
|
||||
$manifest.CmdletsToExport | Should -Contain 'Get-PveStorage'
|
||||
}
|
||||
|
||||
It 'Get-PveStorageContent should be declared in CmdletsToExport' {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
if (-not (Test-Path $manifestPath)) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$manifest = Import-PowerShellDataFile $manifestPath
|
||||
$manifest.CmdletsToExport | Should -Contain 'Get-PveStorageContent'
|
||||
|
||||
@@ -7,21 +7,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$script:CmdExists = $null -ne (Get-Command 'Send-PveIso' -ErrorAction SilentlyContinue)
|
||||
}
|
||||
@@ -30,7 +16,7 @@ Describe 'Send-PveIso' {
|
||||
|
||||
Context 'Manifest declaration' {
|
||||
It 'Should be declared in CmdletsToExport' {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
if (-not (Test-Path $manifestPath)) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$manifest = Import-PowerShellDataFile $manifestPath
|
||||
$manifest.CmdletsToExport | Should -Contain 'Send-PveIso'
|
||||
|
||||
@@ -13,21 +13,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveTemplate', 'New-PveTemplate',
|
||||
@@ -47,7 +33,7 @@ BeforeAll {
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Template cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
|
||||
@@ -9,21 +9,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$allNames = @('Get-PveApiToken', 'New-PveApiToken', 'Remove-PveApiToken')
|
||||
|
||||
@@ -44,7 +30,7 @@ BeforeAll {
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'API Token cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
|
||||
@@ -11,21 +11,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
$allNames = @(
|
||||
'Get-PveUser', 'New-PveUser', 'Remove-PveUser', 'Set-PveUser',
|
||||
@@ -50,7 +36,7 @@ BeforeAll {
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'User / Role / Permission cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$manifestPath = Join-Path (Get-Module PSProxmoxVE).ModuleBase 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
|
||||
@@ -6,21 +6,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
}
|
||||
|
||||
Describe 'Get-PveVm' {
|
||||
|
||||
@@ -6,21 +6,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
}
|
||||
|
||||
Describe 'New-PveVm' {
|
||||
|
||||
@@ -6,21 +6,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
}
|
||||
|
||||
Describe 'Remove-PveVm' {
|
||||
|
||||
@@ -17,21 +17,7 @@
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net9.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
. $PSScriptRoot/../_TestHelper.ps1
|
||||
|
||||
# Helper: assert the standard lifecycle parameter set for Node/VmId/Wait.
|
||||
function Assert-StandardLifecycleParams {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Shared module-loading helper for Pester tests.
|
||||
Dot-source this file inside BeforeAll to import PSProxmoxVE reliably
|
||||
in both local-dev and CI environments.
|
||||
#>
|
||||
|
||||
# If the module is already loaded, nothing to do.
|
||||
if (Get-Module -Name PSProxmoxVE) { return }
|
||||
|
||||
# 1. Try importing by module name (works in CI where the module is
|
||||
# installed to a PSModulePath location via dotnet publish + copy).
|
||||
try {
|
||||
Import-Module PSProxmoxVE -Force -ErrorAction Stop
|
||||
return
|
||||
}
|
||||
catch {
|
||||
# Module not on PSModulePath — fall through to local-path discovery.
|
||||
}
|
||||
|
||||
# 2. Discover the built DLL from the local source tree.
|
||||
# Prefer the framework that matches the running PowerShell edition.
|
||||
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot '../..')
|
||||
$moduleRoot = Join-Path $repoRoot 'src/PSProxmoxVE'
|
||||
|
||||
if ($PSVersionTable.PSEdition -eq 'Core') {
|
||||
$frameworks = @('net9.0', 'net48')
|
||||
}
|
||||
else {
|
||||
$frameworks = @('net48', 'net9.0')
|
||||
}
|
||||
|
||||
$searchPaths = foreach ($fw in $frameworks) {
|
||||
# Publish output (has all dependencies co-located)
|
||||
Join-Path $repoRoot "publish/$fw/PSProxmoxVE.dll"
|
||||
# Build output
|
||||
Join-Path $moduleRoot "bin/Debug/$fw/PSProxmoxVE.dll"
|
||||
Join-Path $moduleRoot "bin/Release/$fw/PSProxmoxVE.dll"
|
||||
}
|
||||
|
||||
$moduleDll = $searchPaths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $moduleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $moduleDll -Force -ErrorAction Stop
|
||||
@@ -270,7 +270,7 @@ function Invoke-PesterUnitTests {
|
||||
|
||||
$config = New-PesterConfiguration
|
||||
$config.Run.Path = $pesterTestDir
|
||||
$config.Filter.ExcludeTag = @('Integration', 'MockIntegration')
|
||||
$config.Filter.ExcludeTag = @('Integration')
|
||||
$config.Output.Verbosity = 'Detailed'
|
||||
$config.Run.PassThru = $true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user