Skip to content

Commit e6b052a

Browse files
committed
Update CLI to prompt for self-contained system
1 parent c5fa59b commit e6b052a

File tree

2 files changed

+94
-86
lines changed

2 files changed

+94
-86
lines changed

developer-cli/Commands/End2EndCommand.cs

Lines changed: 51 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ public class End2EndCommand : Command
1111
{
1212
private static readonly string[] ValidBrowsers = ["chromium", "firefox", "webkit", "safari", "all"];
1313

14+
// Get available self-contained systems
15+
private static readonly string[] AvailableSelfContainedSystems = SelfContainedSystemHelper.GetAvailableSelfContainedSystems();
16+
1417
public End2EndCommand() : base("e2e", "Run end-to-end tests using Playwright")
1518
{
1619
// Add argument for test file patterns
@@ -27,7 +30,7 @@ public class End2EndCommand : Command
2730
AddOption(new Option<bool>(["--quiet"], () => false, "Suppress all output including terminal output and automatic report opening"));
2831
AddOption(new Option<int?>(["--repeat-each"], "Number of times to repeat each test"));
2932
AddOption(new Option<int?>(["--retries"], "Maximum retry count for flaky tests, zero for no retries"));
30-
AddOption(new Option<string?>(["<self-contained-system>", "--self-contained-system", "-s"], "The name of the self-contained system to test (account-management, back-office, etc.)"));
33+
AddOption(new Option<string?>(["<self-contained-system>", "--self-contained-system", "-s"], $"The name of the self-contained system to test ({string.Join(", ", AvailableSelfContainedSystems)}, etc.)"));
3134
AddOption(new Option<bool>(["--show-report"], () => false, "Always show HTML report after test run"));
3235
AddOption(new Option<bool>(["--slow-motion"], () => false, "Run tests in slow motion (automatically enables headed mode)"));
3336
AddOption(new Option<bool>(["--smoke"], () => false, "Run only smoke tests"));
@@ -60,23 +63,27 @@ private static void Execute(
6063
{
6164
Prerequisite.Ensure(Prerequisite.Node);
6265

63-
// Get available self-contained systems
64-
var availableSystems = GetAvailableSelfContainedSystems();
65-
66-
if (availableSystems.Length == 0)
66+
// If debug or UI mode is enabled, we need a specific self-contained system
67+
if ((debug || ui) && selfContainedSystem is null)
6768
{
68-
AnsiConsole.MarkupLine("[red]No self-contained systems with e2e tests found.[/]");
69-
Environment.Exit(1);
69+
selfContainedSystem = SelfContainedSystemHelper.PromptForSelfContainedSystem(AvailableSelfContainedSystems);
7070
}
7171

7272
// Determine which self-contained systems to test based on the provided patterns or grep
73-
var selfContainedSystemsToTest = DetermineSystemsToTest(selfContainedSystem, availableSystems, testPatterns, grep);
73+
string[] selfContainedSystemsToTest;
74+
if (selfContainedSystem is not null)
75+
{
76+
if (!AvailableSelfContainedSystems.Contains(selfContainedSystem))
77+
{
78+
AnsiConsole.MarkupLine($"[red]Invalid self-contained system '{selfContainedSystem}'. Available systems: {string.Join(", ", AvailableSelfContainedSystems)}[/]");
79+
Environment.Exit(1);
80+
}
7481

75-
// Validate self-contained system if provided
76-
if (selfContainedSystem is not null && !availableSystems.Contains(selfContainedSystem))
82+
selfContainedSystemsToTest = [selfContainedSystem];
83+
}
84+
else
7785
{
78-
AnsiConsole.MarkupLine($"[red]Invalid self-contained system '{selfContainedSystem}'. Available systems: {string.Join(", ", availableSystems)}[/]");
79-
Environment.Exit(1);
86+
selfContainedSystemsToTest = DetermineSystemsToTest(testPatterns, grep, AvailableSelfContainedSystems);
8087
}
8188

8289
// Validate browser option
@@ -103,7 +110,7 @@ private static void Execute(
103110
{
104111
overallSuccess = false;
105112
failedSelfContainedSystems.Add(currentSelfContainedSystem);
106-
113+
107114
// If stop on first failure is enabled, exit the loop after the first failure
108115
if (stopOnFirstFailure)
109116
{
@@ -215,7 +222,8 @@ private static bool RunTestsForSystem(
215222
ProcessHelper.StartProcess(processStartInfo, throwOnError: true);
216223
AnsiConsole.MarkupLine(testsFailed
217224
? $"[red]Tests for {selfContainedSystem} failed[/]"
218-
: $"[green]Tests for {selfContainedSystem} completed successfully[/]");
225+
: $"[green]Tests for {selfContainedSystem} completed successfully[/]"
226+
);
219227
}
220228
catch (Exception)
221229
{
@@ -251,51 +259,27 @@ private static void CheckWebsiteAccessibility()
251259
Environment.Exit(1);
252260
}
253261

254-
private static string[] DetermineSystemsToTest(string? specifiedSelfContainedSystem, string[] availableSystems, string[] testPatterns, string? grep)
262+
private static string[] DetermineSystemsToTest(string[] testPatterns, string? grep, string[] availableSystems)
255263
{
256-
// If a specific self-contained system is provided, use only that one
257-
if (specifiedSelfContainedSystem != null)
258-
{
259-
return [specifiedSelfContainedSystem];
260-
}
261-
262-
// If no patterns or grep are provided, run tests for all systems
263264
if ((testPatterns.Length == 0 || testPatterns[0] == "*") && string.IsNullOrEmpty(grep))
264265
{
265266
return availableSystems;
266267
}
267268

268-
// Check if test patterns match specific files in any self-contained system
269269
var matchingSystems = new HashSet<string>();
270270

271-
foreach (var pattern in testPatterns)
271+
foreach (var pattern in testPatterns.Where(p => p != null && p != "*"))
272272
{
273-
// Skip wildcard patterns as they don't help us narrow down the systems
274-
if (pattern == "*" || (pattern.Contains("*") && !pattern.EndsWith(".spec.ts")))
275-
{
276-
continue;
277-
}
278-
279-
if (pattern is null)
280-
{
281-
continue;
282-
}
283-
284-
// Normalize the pattern to handle both file names and paths
285273
var normalizedPattern = pattern.EndsWith(".spec.ts") ? pattern : $"{pattern}.spec.ts";
286274
normalizedPattern = Path.GetFileName(normalizedPattern);
287275

288276
foreach (var system in availableSystems)
289277
{
290278
var e2eTestsPath = Path.Combine(Configuration.ApplicationFolder, system, "WebApp", "e2e-tests");
291-
if (!Directory.Exists(e2eTestsPath))
292-
{
293-
continue;
294-
}
279+
if (!Directory.Exists(e2eTestsPath)) continue;
295280

296281
var testFiles = Directory.GetFiles(e2eTestsPath, "*.spec.ts", SearchOption.AllDirectories)
297-
.Select(Path.GetFileName)
298-
.ToArray();
282+
.Select(Path.GetFileName);
299283

300284
if (testFiles.Any(file => file?.Equals(normalizedPattern, StringComparison.OrdinalIgnoreCase) == true))
301285
{
@@ -304,71 +288,32 @@ private static string[] DetermineSystemsToTest(string? specifiedSelfContainedSys
304288
}
305289
}
306290

307-
// If we found matching systems based on file patterns, return those
308-
if (matchingSystems.Count > 0)
309-
{
310-
return matchingSystems.ToArray();
311-
}
291+
if (matchingSystems.Count > 0) return matchingSystems.ToArray();
312292

313-
// If grep is provided, try to find matching test content
314293
if (!string.IsNullOrEmpty(grep))
315294
{
316295
foreach (var system in availableSystems)
317296
{
318297
var e2eTestsPath = Path.Combine(Configuration.ApplicationFolder, system, "WebApp", "e2e-tests");
319-
if (!Directory.Exists(e2eTestsPath))
320-
{
321-
continue;
322-
}
298+
if (!Directory.Exists(e2eTestsPath)) continue;
323299

324300
var testFiles = Directory.GetFiles(e2eTestsPath, "*.spec.ts", SearchOption.AllDirectories);
325301
foreach (var testFile in testFiles)
326302
{
327-
var fileContent = File.ReadAllText(testFile);
328-
if (fileContent.Contains(grep, StringComparison.OrdinalIgnoreCase))
303+
if (File.ReadAllText(testFile).Contains(grep, StringComparison.OrdinalIgnoreCase))
329304
{
330305
matchingSystems.Add(system);
331-
break; // Found a match in this system, no need to check other files
306+
break;
332307
}
333308
}
334309
}
335310

336-
if (matchingSystems.Count > 0)
337-
{
338-
return matchingSystems.ToArray();
339-
}
311+
if (matchingSystems.Count > 0) return matchingSystems.ToArray();
340312
}
341313

342-
// If we couldn't determine specific systems, run tests for all systems
343314
return availableSystems;
344315
}
345316

346-
private static string[] GetAvailableSelfContainedSystems()
347-
{
348-
var selfContainedSystems = new List<string>();
349-
350-
// Look for directories that contain WebApp/e2e-tests
351-
foreach (var directory in Directory.GetDirectories(Configuration.ApplicationFolder))
352-
{
353-
var directoryName = Path.GetFileName(directory);
354-
355-
// Skip directories that are not self-contained systems
356-
if (directoryName.StartsWith('.') || directoryName == "AppGateway" || directoryName == "AppHost" ||
357-
directoryName == "shared-kernel" || directoryName == "shared-webapp")
358-
{
359-
continue;
360-
}
361-
362-
var e2eTestsPath = Path.Combine(directory, "WebApp", "e2e-tests");
363-
if (Directory.Exists(e2eTestsPath))
364-
{
365-
selfContainedSystems.Add(directoryName);
366-
}
367-
}
368-
369-
return selfContainedSystems.ToArray();
370-
}
371-
372317
private static string BuildPlaywrightArgs(
373318
string[] testPatterns,
374319
string browser,
@@ -427,6 +372,26 @@ private static string BuildPlaywrightArgs(
427372
return string.Join(" ", args);
428373
}
429374

375+
private static string PromptForSelfContainedSystem(string[] availableSystems)
376+
{
377+
if (availableSystems.Length == 0)
378+
{
379+
AnsiConsole.MarkupLine("[red]No self-contained systems found.[/]");
380+
Environment.Exit(1);
381+
return string.Empty; // This line will never be reached but is needed to satisfy the compiler
382+
}
383+
384+
var selectedSystem = AnsiConsole.Prompt(
385+
new SelectionPrompt<string>()
386+
.Title("Select a [green]self-contained system[/] to test:")
387+
.PageSize(10)
388+
.MoreChoicesText("[grey](Move up and down to reveal more systems)[/]")
389+
.AddChoices(availableSystems)
390+
);
391+
392+
return selectedSystem;
393+
}
394+
430395
private static void OpenHtmlReport(string selfContainedSystem)
431396
{
432397
var reportPath = Path.Combine(Configuration.ApplicationFolder, selfContainedSystem, "WebApp", "playwright-report", "index.html");
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using PlatformPlatform.DeveloperCli.Installation;
2+
using Spectre.Console;
3+
4+
namespace PlatformPlatform.DeveloperCli.Utilities;
5+
6+
public static class SelfContainedSystemHelper
7+
{
8+
public static string[] GetAvailableSelfContainedSystems()
9+
{
10+
return Directory.GetDirectories(Configuration.ApplicationFolder)
11+
.Where(dir => HasRequiredFolders(dir))
12+
.Select(Path.GetFileName)
13+
.Where(name => name is not null)
14+
.Select(name => name!)
15+
.OrderBy(name => name)
16+
.ToArray();
17+
}
18+
19+
private static bool HasRequiredFolders(string directory)
20+
{
21+
return Directory.Exists(Path.Combine(directory, "Api")) &&
22+
Directory.Exists(Path.Combine(directory, "Core")) &&
23+
Directory.Exists(Path.Combine(directory, "Tests")) &&
24+
Directory.Exists(Path.Combine(directory, "WebApp"));
25+
}
26+
27+
public static string PromptForSelfContainedSystem(string[] availableSystems)
28+
{
29+
if (!AnsiConsole.Profile.Capabilities.Interactive)
30+
{
31+
AnsiConsole.MarkupLine("[red]Cannot show selection prompt in non-interactive terminal.[/]");
32+
AnsiConsole.MarkupLine("[yellow]Please specify a self-contained system using the -s flag.[/]");
33+
AnsiConsole.MarkupLine($"[yellow]Available systems: {string.Join(", ", availableSystems)}[/]");
34+
Environment.Exit(1);
35+
}
36+
37+
return AnsiConsole.Prompt(
38+
new SelectionPrompt<string>()
39+
.Title("Select a [green]self-contained system[/] to test:")
40+
.AddChoices(availableSystems)
41+
);
42+
}
43+
}

0 commit comments

Comments
 (0)