ExportTests.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using Microsoft.Playwright;
  2. using Tests.E2e.Infra;
  3. using Tests.E2e.PageObjectModels;
  4. using Xunit.Abstractions;
  5. namespace Tests.E2e;
  6. /// <summary>
  7. /// Coverage for the /ssh/export and /hosts/export generators. Both render
  8. /// from whatever is in the config, so each test creates the system it
  9. /// asserts on rather than relying on seed data — the container starts with
  10. /// an empty config volume.
  11. /// Kept in one class so both pages share a single container.
  12. /// </summary>
  13. public class ExportTests(
  14. PlaywrightFixture fixture,
  15. ITestOutputHelper output) : E2ETestBase(fixture, output) {
  16. private readonly PlaywrightFixture _fixture = fixture;
  17. private readonly ITestOutputHelper _output = output;
  18. // =============================================================
  19. // Hosts export — localhost defaults toggle
  20. // =============================================================
  21. [Fact]
  22. public async Task Hosts_Export_Honours_The_Localhost_Defaults_Toggle() {
  23. (IBrowserContext context, IPage page) = await CreatePageAsync();
  24. try {
  25. await page.GotoAsync($"{_fixture.BaseUrl}/hosts/export");
  26. var hosts = new HostsExportPom(page);
  27. await hosts.AssertVisibleAsync();
  28. // Defaults on: the loopback block is emitted.
  29. await hosts.SetIncludeLocalhostAsync(true);
  30. await hosts.GenerateAsync();
  31. await hosts.AssertOutputContainsAsync("127.0.0.1");
  32. await hosts.AssertNoWarningsAsync();
  33. // Defaults off: it is not.
  34. await hosts.SetIncludeLocalhostAsync(false);
  35. await hosts.GenerateAsync();
  36. await hosts.AssertOutputDoesNotContainAsync("127.0.0.1");
  37. }
  38. catch (Exception) {
  39. await DumpAsync(page);
  40. throw;
  41. }
  42. finally {
  43. await context.CloseAsync();
  44. }
  45. }
  46. // =============================================================
  47. // Hosts export — a real system reaches the output
  48. // =============================================================
  49. [Fact]
  50. public async Task Hosts_Export_Emits_An_Entry_For_A_System_With_An_Ip() {
  51. (IBrowserContext context, IPage page) = await CreatePageAsync();
  52. var name = $"e2e-hx-{Guid.NewGuid():N}"[..14];
  53. const string ip = "10.42.7.21";
  54. try {
  55. await CreateSystemWithIpAsync(page, name, ip);
  56. await page.GotoAsync($"{_fixture.BaseUrl}/hosts/export");
  57. var hosts = new HostsExportPom(page);
  58. await hosts.AssertVisibleAsync();
  59. await hosts.SetDomainSuffixAsync("home.local");
  60. await hosts.GenerateAsync();
  61. await hosts.AssertOutputContainsAsync(ip);
  62. await hosts.AssertOutputContainsAsync(name);
  63. await hosts.AssertOutputContainsAsync($"{name}.home.local");
  64. }
  65. catch (Exception) {
  66. await DumpAsync(page);
  67. throw;
  68. }
  69. finally {
  70. await context.CloseAsync();
  71. }
  72. }
  73. // =============================================================
  74. // SSH export — a real system reaches the output
  75. // =============================================================
  76. [Fact]
  77. public async Task Ssh_Export_Emits_A_Host_Block_For_A_System_With_An_Ip() {
  78. (IBrowserContext context, IPage page) = await CreatePageAsync();
  79. var name = $"e2e-sx-{Guid.NewGuid():N}"[..14];
  80. const string ip = "10.42.7.22";
  81. try {
  82. await CreateSystemWithIpAsync(page, name, ip);
  83. await page.GotoAsync($"{_fixture.BaseUrl}/ssh/export");
  84. var ssh = new SshExportPom(page);
  85. await ssh.AssertVisibleAsync();
  86. await ssh.SetDefaultUserAsync("ansible");
  87. await ssh.SetDefaultPortAsync("2222");
  88. await ssh.SetDefaultIdentityAsync("~/.ssh/id_ed25519");
  89. await ssh.GenerateAsync();
  90. await ssh.AssertOutputContainsAsync($"Host {name}");
  91. await ssh.AssertOutputContainsAsync($"HostName {ip}");
  92. await ssh.AssertOutputContainsAsync("User ansible");
  93. await ssh.AssertOutputContainsAsync("Port 2222");
  94. await ssh.AssertOutputContainsAsync("IdentityFile ~/.ssh/id_ed25519");
  95. }
  96. catch (Exception) {
  97. await DumpAsync(page);
  98. throw;
  99. }
  100. finally {
  101. await context.CloseAsync();
  102. }
  103. }
  104. // =============================================================
  105. // Helpers
  106. // =============================================================
  107. private async Task CreateSystemWithIpAsync(IPage page, string name, string ip) {
  108. await page.GotoAsync($"{_fixture.BaseUrl}/systems/list");
  109. var list = new SystemsListPom(page);
  110. await list.AssertLoadedAsync();
  111. await list.AddSystemAsync(name);
  112. if (!page.Url.Contains($"/resources/systems/{name}", StringComparison.OrdinalIgnoreCase))
  113. await list.OpenSystemAsync(name);
  114. var card = new SystemCardPom(page);
  115. await card.AssertVisibleAsync(name);
  116. await card.BeginEditAsync(name);
  117. await card.IpInput(name).FillAsync(ip);
  118. await card.SaveAsync(name);
  119. await Assertions.Expect(card.IpValue(name)).ToContainTextAsync(ip);
  120. }
  121. private async Task DumpAsync(IPage page) {
  122. _output.WriteLine("TEST FAILED — Capturing diagnostics");
  123. _output.WriteLine($"Current URL: {page.Url}");
  124. var html = await page.ContentAsync();
  125. _output.WriteLine("==== DOM SNAPSHOT START ====");
  126. _output.WriteLine(html);
  127. _output.WriteLine("==== DOM SNAPSHOT END ====");
  128. }
  129. }