Skip to content

Commit 8b59ddf

Browse files
authored
Separate Spectre.Console.Cli from Spectre.Console (#1850)
1 parent 6ad814c commit 8b59ddf

13 files changed

Lines changed: 179 additions & 139 deletions

File tree

src/Directory.Packages.props

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
<Project>
2-
32
<PropertyGroup>
43
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
54
</PropertyGroup>
6-
75
<ItemGroup>
8-
<PackageVersion Include="IsExternalInit" Version="1.0.3"/>
9-
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3"/>
10-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
11-
<PackageVersion Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="8.0.0"/>
12-
<PackageVersion Include="MinVer" PrivateAssets="All" Version="6.0.0"/>
13-
<PackageVersion Include="PolySharp" Version="1.15.0"/>
14-
<PackageVersion Include="Roslynator.Analyzers" PrivateAssets="All" Version="4.13.1"/>
15-
<PackageVersion Include="Shouldly" Version="4.3.0"/>
16-
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.10"/>
17-
<PackageVersion Include="Spectre.Verify.Extensions" Version="28.16.0"/>
18-
<PackageVersion Include="StyleCop.Analyzers" PrivateAssets="All" Version="1.2.0-beta.556"/>
19-
<PackageVersion Include="System.Memory" Version="4.6.3"/>
20-
<PackageVersion Include="TunnelVisionLabs.ReferenceAssemblyAnnotator" Version="1.0.0-alpha.160"/>
21-
<PackageVersion Include="Verify.Xunit" Version="30.4.0"/>
22-
<PackageVersion Include="Wcwidth.Sources" Version="2.0.0"/>
23-
<PackageVersion Include="xunit" Version="2.9.3"/>
24-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.1"/>
6+
<PackageVersion Include="IsExternalInit" Version="1.0.3" />
7+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3" />
8+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
9+
<PackageVersion Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="8.0.0" />
10+
<PackageVersion Include="MinVer" PrivateAssets="All" Version="6.0.0" />
11+
<PackageVersion Include="PolySharp" Version="1.15.0" />
12+
<PackageVersion Include="Roslynator.Analyzers" PrivateAssets="All" Version="4.13.1" />
13+
<PackageVersion Include="Shouldly" Version="4.3.0" />
14+
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.10" />
15+
<PackageVersion Include="Spectre.Console" Version="0.50.0" />
16+
<PackageVersion Include="Spectre.Console.Cli" Version="0.50.0" />
17+
<PackageVersion Include="Spectre.Console.Testing" Version="0.50.1-preview.0.20" />
18+
<PackageVersion Include="Spectre.Verify.Extensions" Version="28.16.0" />
19+
<PackageVersion Include="StyleCop.Analyzers" PrivateAssets="All" Version="1.2.0-beta.556" />
20+
<PackageVersion Include="System.Memory" Version="4.6.3" />
21+
<PackageVersion Include="TunnelVisionLabs.ReferenceAssemblyAnnotator" Version="1.0.0-alpha.160" />
22+
<PackageVersion Include="Verify.Xunit" Version="30.4.0" />
23+
<PackageVersion Include="Wcwidth.Sources" Version="2.0.0" />
24+
<PackageVersion Include="xunit" Version="2.9.3" />
25+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.1" />
2526
</ItemGroup>
26-
2727
</Project>

src/Spectre.Console.Cli.sln

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.1.32414.318
5+
MinimumVisualStudioVersion = 15.0.26124.0
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spectre.Console.Cli", "Spectre.Console.Cli\Spectre.Console.Cli.csproj", "{1B67B74F-1243-4381-9A2B-86EA66D135C5}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spectre.Console.Cli.Tests", "Tests\Spectre.Console.Cli.Tests\Spectre.Console.Cli.Tests.csproj", "{E07C46D2-714F-4116-BADD-FEE09617A9C4}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Debug|x64 = Debug|x64
14+
Debug|x86 = Debug|x86
15+
Release|Any CPU = Release|Any CPU
16+
Release|x64 = Release|x64
17+
Release|x86 = Release|x86
18+
EndGlobalSection
19+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Debug|x64.ActiveCfg = Debug|Any CPU
23+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Debug|x64.Build.0 = Debug|Any CPU
24+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Debug|x86.ActiveCfg = Debug|Any CPU
25+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Debug|x86.Build.0 = Debug|Any CPU
26+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
27+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Release|Any CPU.Build.0 = Release|Any CPU
28+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Release|x64.ActiveCfg = Release|Any CPU
29+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Release|x64.Build.0 = Release|Any CPU
30+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Release|x86.ActiveCfg = Release|Any CPU
31+
{1B67B74F-1243-4381-9A2B-86EA66D135C5}.Release|x86.Build.0 = Release|Any CPU
32+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
34+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Debug|x64.ActiveCfg = Debug|Any CPU
35+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Debug|x64.Build.0 = Debug|Any CPU
36+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Debug|x86.ActiveCfg = Debug|Any CPU
37+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Debug|x86.Build.0 = Debug|Any CPU
38+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
39+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Release|Any CPU.Build.0 = Release|Any CPU
40+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Release|x64.ActiveCfg = Release|Any CPU
41+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Release|x64.Build.0 = Release|Any CPU
42+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Release|x86.ActiveCfg = Release|Any CPU
43+
{E07C46D2-714F-4116-BADD-FEE09617A9C4}.Release|x86.Build.0 = Release|Any CPU
44+
EndGlobalSection
45+
GlobalSection(SolutionProperties) = preSolution
46+
HideSolutionNode = FALSE
47+
EndGlobalSection
48+
GlobalSection(ExtensibilityGlobals) = postSolution
49+
SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C}
50+
EndGlobalSection
51+
EndGlobal

src/Spectre.Console.Cli/Spectre.Console.Cli.csproj

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFrameworks>net9.0;net8.0;netstandard2.0</TargetFrameworks>
55
<IsPackable>true</IsPackable>
66
</PropertyGroup>
77
<PropertyGroup>
8-
<IsAotCompatible Condition="'$(TargetFramework)' != 'netstandard2.0'" >false</IsAotCompatible>
8+
<IsAotCompatible Condition="'$(TargetFramework)' != 'netstandard2.0'">false</IsAotCompatible>
99
<IsTrimmable>false</IsTrimmable>
1010
</PropertyGroup>
1111
<ItemGroup Label="REMOVE THIS">
1212
<InternalsVisibleTo Include="Spectre.Console.Cli.Tests" />
1313
</ItemGroup>
1414

15-
<ItemGroup>
16-
<ProjectReference Include="..\Spectre.Console\Spectre.Console.csproj" />
17-
</ItemGroup>
18-
1915
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
2016
<AnnotatedReferenceAssemblyVersion>3.0.0</AnnotatedReferenceAssemblyVersion>
2117
<GenerateNullableAttributes>False</GenerateNullableAttributes>
@@ -26,6 +22,7 @@
2622
<PrivateAssets>all</PrivateAssets>
2723
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
2824
</PackageReference>
25+
<PackageReference Include="Spectre.Console" />
2926
</ItemGroup>
3027

3128

src/Spectre.Console.Testing/Extensions/ShouldlyExtensions.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
1-
namespace Spectre.Console;
1+
namespace Spectre.Console.Testing;
22

3-
internal static class ShouldlyExtensions
3+
/// <summary>
4+
/// Provides extensions for testing using the Shouldly-style fluent assertions.
5+
/// </summary>
6+
public static class ShouldlyExtensions
47
{
8+
/// <summary>
9+
/// Performs the specified action on the given object and then returns the object.
10+
/// Useful for fluent testing patterns where additional assertions or operations
11+
/// are chained together in a readable manner.
12+
/// </summary>
13+
/// <typeparam name="T">The type of the object.</typeparam>
14+
/// <param name="item">The object to operate on.</param>
15+
/// <param name="action">An action to perform on the object.</param>
16+
/// <returns>The original object, to allow further chaining.</returns>
17+
/// <exception cref="ArgumentNullException">Thrown if <paramref name="action"/> is null.</exception>
518
[DebuggerStepThrough]
619
public static T And<T>(this T item, Action<T> action)
720
{
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
namespace Spectre.Console.Testing;
2+
3+
/// <summary>
4+
/// Provides extension methods for working with <see cref="TestConsole"/> in a testing context,
5+
/// including stack trace normalization for consistent and deterministic test output.
6+
/// </summary>
7+
public static partial class TestConsoleExtensions
8+
{
9+
private static readonly Regex _lineNumberRegex = new Regex(":\\d+", RegexOptions.Singleline);
10+
private static readonly Regex _filenameRegex = new Regex("\\sin\\s.*cs:nn", RegexOptions.Multiline);
11+
12+
/// <summary>
13+
/// Writes the given exception to the <see cref="TestConsole"/> and returns a normalized string
14+
/// representation of the exception, with file paths and line numbers sanitized.
15+
/// </summary>
16+
/// <param name="console">The <see cref="TestConsole"/> to write to.</param>
17+
/// <param name="ex">The exception to write and normalize.</param>
18+
/// <param name="formats">Optional formatting options for exception output.</param>
19+
/// <returns>A normalized string of the exception's output, safe for snapshot testing.</returns>
20+
/// <exception cref="InvalidOperationException">
21+
/// Thrown if the console's output buffer is not empty before writing the exception.
22+
/// </exception>
23+
public static string WriteNormalizedException(this TestConsole console, Exception ex, ExceptionFormats formats = ExceptionFormats.Default)
24+
{
25+
if (!string.IsNullOrWhiteSpace(console.Output))
26+
{
27+
throw new InvalidOperationException("Output buffer is not empty.");
28+
}
29+
30+
console.WriteException(ex, formats);
31+
return string.Join("\n", NormalizeStackTrace(console.Output)
32+
.NormalizeLineEndings()
33+
.Split(new char[] { '\n' })
34+
.Select(line => line.TrimEnd()));
35+
}
36+
37+
/// <summary>
38+
/// Normalizes a stack trace string by replacing line numbers with ":nn"
39+
/// and converting full file paths to a fixed placeholder path ("/xyz/filename.cs").
40+
/// </summary>
41+
/// <param name="text">The stack trace text to normalize.</param>
42+
/// <returns>A sanitized stack trace suitable for stable testing output.</returns>
43+
public static string NormalizeStackTrace(string text)
44+
{
45+
text = _lineNumberRegex.Replace(text, match =>
46+
{
47+
return ":nn";
48+
});
49+
50+
return _filenameRegex.Replace(text, match =>
51+
{
52+
var value = match.Value;
53+
var index = value.LastIndexOfAny(new[] { '\\', '/' });
54+
var filename = value.Substring(index + 1, value.Length - index - 1);
55+
56+
return $" in /xyz/{filename}";
57+
});
58+
}
59+
}

src/Spectre.Console.Testing/TestConsoleExtensions.cs renamed to src/Spectre.Console.Testing/Extensions/TestConsoleExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ namespace Spectre.Console.Testing;
33
/// <summary>
44
/// Contains extensions for <see cref="TestConsole"/>.
55
/// </summary>
6-
public static class TestConsoleExtensions
6+
public static partial class TestConsoleExtensions
77
{
88
/// <summary>
99
/// Sets the console's color system.

src/Spectre.Console.Testing/Properties/Usings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
global using System.Diagnostics;
44
global using System.IO;
55
global using System.Linq;
6+
global using System.Text.RegularExpressions;
67
global using System.Threading;
78
global using System.Threading.Tasks;
89
global using Spectre.Console.Cli;
Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFrameworks>net9.0;net8.0;netstandard2.0</TargetFrameworks>
@@ -7,14 +7,9 @@
77
<Description>Contains testing utilities for Spectre.Console.</Description>
88
</PropertyGroup>
99

10-
<ItemGroup Label="REMOVE THIS">
11-
<InternalsVisibleTo Include="Spectre.Console.Tests" />
12-
<InternalsVisibleTo Include="Spectre.Console.Cli.Tests" />
13-
</ItemGroup>
14-
15-
<ItemGroup Label="Project References">
16-
<ProjectReference Include="..\Spectre.Console.Cli\Spectre.Console.Cli.csproj" />
17-
<ProjectReference Include="..\Spectre.Console\Spectre.Console.csproj" />
10+
<ItemGroup>
11+
<PackageReference Include="Spectre.Console" />
12+
<PackageReference Include="Spectre.Console.Cli" />
1813
</ItemGroup>
1914

2015
</Project>

0 commit comments

Comments
 (0)