Skip to content

Commit d5aa961

Browse files
committed
Add parsing tests
1 parent 6d3d705 commit d5aa961

1 file changed

Lines changed: 309 additions & 0 deletions

File tree

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.CommandLine;
6+
using System.IO;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using FluentAssertions;
10+
using NuGet.CommandLine.XPlat.Commands.Package.PackageDownload;
11+
using NuGet.Common;
12+
using NuGet.Test.Utility;
13+
using Xunit;
14+
15+
namespace NuGet.CommandLine.Xplat.Tests.Commands.Package.Download
16+
{
17+
public class PackageDownloadCommandTests
18+
{
19+
[Fact]
20+
public async Task NoArguments_HasDefaultOptions()
21+
{
22+
// Arrange
23+
string args = "package download";
24+
25+
// Act
26+
var result = await RunAsync(args);
27+
28+
// Assert
29+
result.Should().NotBeNull();
30+
result.Packages.Should().BeEmpty();
31+
result.Sources.Should().BeEmpty();
32+
result.OutputDirectory.Should().BeNull();
33+
result.ConfigFile.Should().BeNull();
34+
result.IncludePrerelease.Should().BeFalse();
35+
result.DownloadOnly.Should().BeFalse();
36+
result.AllowInsecureConnections.Should().BeFalse();
37+
result.Interactive.Should().BeFalse();
38+
result.LogLevel.Should().Be(LogLevel.Information);
39+
}
40+
41+
[Fact]
42+
public async Task WithSinglePackage_ShouldParsePackageId()
43+
{
44+
// Arrange
45+
string args = "package download Contoso.Utils";
46+
47+
// Act
48+
var result = await RunAsync(args);
49+
50+
// Assert
51+
result.Should().NotBeNull();
52+
result.Packages.Should().HaveCount(1);
53+
result.Packages[0].Id.Should().Be("Contoso.Utils");
54+
result.Packages[0].VersionRange.Should().BeNull();
55+
}
56+
57+
[Fact]
58+
public async Task WithMultiplePackages_ShouldParseAllPackageIds()
59+
{
60+
// Arrange
61+
string args = "package download Contoso.Utils Contoso.Framework";
62+
63+
// Act
64+
var result = await RunAsync(args);
65+
66+
// Assert
67+
result.Should().NotBeNull();
68+
result.Packages.Should().HaveCount(2);
69+
result.Packages[0].Id.Should().Be("Contoso.Utils");
70+
result.Packages[0].VersionRange.Should().BeNull();
71+
result.Packages[1].Id.Should().Be("Contoso.Framework");
72+
result.Packages[1].VersionRange.Should().BeNull();
73+
}
74+
75+
[Fact]
76+
public async Task WithPackageAndVersion_ShouldParsePackageWithVersionRange()
77+
{
78+
// Arrange
79+
string args = "package download [email protected]";
80+
81+
// Act
82+
var result = await RunAsync(args);
83+
84+
// Assert
85+
result.Should().NotBeNull();
86+
result.Packages.Should().HaveCount(1);
87+
result.Packages[0].Id.Should().Be("Contoso.Utils");
88+
result.Packages[0].VersionRange.Should().NotBeNull();
89+
result.Packages[0].VersionRange!.ToString().Should().Be("[2.1.0, )");
90+
}
91+
92+
[Fact]
93+
public async Task WithPackageAndVersionRange_ShouldParsePackageWithVersionRange()
94+
{
95+
// Arrange
96+
string args = "package download Contoso.Utils@[2.0.0,3.0.0)";
97+
98+
// Act
99+
var result = await RunAsync(args);
100+
101+
// Assert
102+
result.Should().NotBeNull();
103+
result.Packages.Should().HaveCount(1);
104+
result.Packages[0].Id.Should().Be("Contoso.Utils");
105+
result.Packages[0].VersionRange.Should().NotBeNull();
106+
result.Packages[0].VersionRange!.ToString().Should().Be("[2.0.0, 3.0.0)");
107+
}
108+
109+
[Fact]
110+
public async Task WithMixedPackages_ShouldParseMixedPackagesCorrectly()
111+
{
112+
// Arrange
113+
string args = "package download [email protected] Contoso.Framework";
114+
115+
// Act
116+
var result = await RunAsync(args);
117+
118+
// Assert
119+
result.Should().NotBeNull();
120+
result.Packages.Should().HaveCount(2);
121+
result.Packages[0].Id.Should().Be("Contoso.Utils");
122+
result.Packages[0].VersionRange.Should().NotBeNull();
123+
result.Packages[1].Id.Should().Be("Contoso.Framework");
124+
result.Packages[1].VersionRange.Should().BeNull();
125+
}
126+
127+
[Fact]
128+
public async Task WithOutputAndConfig_ShouldBindPaths()
129+
{
130+
// Arrange
131+
using var pathContext = new SimpleTestPathContext();
132+
string outDir = Path.Combine(pathContext.WorkingDirectory, "out");
133+
string cfg = Path.Combine(pathContext.WorkingDirectory, "nuget.config");
134+
135+
string args = $"package download --output-directory \"{outDir}\" --configfile \"{cfg}\"";
136+
137+
// Act
138+
var result = await RunAsync(args);
139+
140+
// Assert
141+
result.Should().NotBeNull();
142+
result.OutputDirectory.Should().Be(outDir);
143+
result.ConfigFile.Should().Be(cfg);
144+
}
145+
146+
[Theory]
147+
[InlineData(true)]
148+
[InlineData(false)]
149+
public async Task WithInteractiveOption_ShouldSetCorrectInteractiveValue(bool value)
150+
{
151+
// Arrange
152+
string args = $"package download --interactive:{value}";
153+
154+
// Act
155+
var result = await RunAsync(args);
156+
157+
// Assert
158+
result.Should().NotBeNull();
159+
result.Interactive.Should().Be(value);
160+
}
161+
162+
[Fact]
163+
public async Task WithBooleanFlags_ShouldSetAllFlagsTrue()
164+
{
165+
// Arrange
166+
string args = "package download --prerelease --download-only --allow-insecure-connections --interactive";
167+
168+
// Act
169+
var result = await RunAsync(args);
170+
171+
// Assert
172+
result.IncludePrerelease.Should().BeTrue();
173+
result.DownloadOnly.Should().BeTrue();
174+
result.AllowInsecureConnections.Should().BeTrue();
175+
result.Interactive.Should().BeTrue();
176+
}
177+
178+
[Theory]
179+
[InlineData("--verbosity quiet", LogLevel.Warning)]
180+
[InlineData("--verbosity q", LogLevel.Warning)]
181+
[InlineData("--verbosity minimal", LogLevel.Minimal)]
182+
[InlineData("--verbosity m", LogLevel.Minimal)]
183+
[InlineData("--verbosity normal", LogLevel.Information)]
184+
[InlineData("--verbosity n", LogLevel.Information)]
185+
[InlineData("--verbosity detailed", LogLevel.Verbose)]
186+
[InlineData("--verbosity d", LogLevel.Verbose)]
187+
[InlineData("--verbosity diagnostic", LogLevel.Debug)]
188+
[InlineData("--verbosity diag", LogLevel.Debug)]
189+
[InlineData("-v quiet", LogLevel.Warning)]
190+
[InlineData("-v minimal", LogLevel.Minimal)]
191+
[InlineData("-v normal", LogLevel.Information)]
192+
[InlineData("-v detailed", LogLevel.Verbose)]
193+
[InlineData("-v diagnostic", LogLevel.Debug)]
194+
public async Task WithVerbosityOption_ShouldSetCorrectLogLevel(string verbosityArgs, LogLevel expectedLogLevel)
195+
{
196+
// Arrange
197+
string args = $"package download {verbosityArgs}";
198+
199+
// Act
200+
var result = await RunAsync(args);
201+
202+
// Assert
203+
result.Should().NotBeNull();
204+
result.LogLevel.Should().Be(expectedLogLevel);
205+
}
206+
207+
[Fact]
208+
public void WithInvalidVersionRange_ShouldHaveParseErrors()
209+
{
210+
// Arrange
211+
string args = "package download Contoso.Utils@invalid-version";
212+
213+
// Act
214+
var result = Parse(args);
215+
216+
// Assert
217+
result.Errors.Count.Should().BeGreaterThan(0);
218+
}
219+
220+
[Fact]
221+
public void WithEmptyVersionAfterAt_ShouldHaveParseErrors()
222+
{
223+
// Arrange
224+
string args = "package download Contoso.Utils@";
225+
226+
// Act
227+
var result = Parse(args);
228+
229+
// Assert
230+
result.Errors.Count.Should().BeGreaterThan(0);
231+
}
232+
233+
[Fact]
234+
public async Task WithAllOptions_ShouldParseAllOptionsCorrectly()
235+
{
236+
// Arrange
237+
using var pathContext = new SimpleTestPathContext();
238+
string outDir = Path.Combine(pathContext.WorkingDirectory, "out");
239+
string cfg = Path.Combine(pathContext.WorkingDirectory, "nuget.config");
240+
241+
string args = $"package download [email protected] --output-directory \"{outDir}\" --configfile \"{cfg}\" --prerelease --download-only --allow-insecure-connections --source s1 --source s2 --verbosity detailed --interactive";
242+
243+
// Act
244+
var result = await RunAsync(args);
245+
246+
// Assert
247+
result.Should().NotBeNull();
248+
result.Packages.Should().HaveCount(1);
249+
result.Packages[0].Id.Should().Be("Contoso.Utils");
250+
result.Packages[0].VersionRange.Should().NotBeNull();
251+
result.OutputDirectory.Should().Be(outDir);
252+
result.ConfigFile.Should().Be(cfg);
253+
result.IncludePrerelease.Should().BeTrue();
254+
result.DownloadOnly.Should().BeTrue();
255+
result.AllowInsecureConnections.Should().BeTrue();
256+
result.Sources.Should().ContainInOrder("s1", "s2");
257+
result.LogLevel.Should().Be(LogLevel.Verbose);
258+
result.Interactive.Should().BeTrue();
259+
}
260+
261+
private ParseResult Parse(string commandLine, Func<PackageDownloadArgs, CancellationToken, Task<int>> action = null)
262+
{
263+
RootCommand rootCommand = new RootCommand();
264+
265+
var packageCommand = new Command("package");
266+
rootCommand.Subcommands.Add(packageCommand);
267+
268+
// Simulate SDK-provided interactive option
269+
var interactiveOption = new Option<bool>("--interactive");
270+
271+
if (action == null)
272+
{
273+
action = (_, _) => throw new NotImplementedException("No action provided for command execution.");
274+
}
275+
276+
PackageDownloadCommand.Register(packageCommand, interactiveOption, action);
277+
278+
var parser = rootCommand.Parse(commandLine);
279+
return parser;
280+
}
281+
282+
private async Task<PackageDownloadArgs> RunAsync(string commandLine)
283+
{
284+
PackageDownloadArgs commandArgs = null;
285+
286+
var parseResult = Parse(commandLine, (args, cancellationToken) =>
287+
{
288+
commandArgs = args;
289+
return Task.FromResult(0);
290+
});
291+
292+
using var output = new StringWriter();
293+
var commandLineConfiguration = new InvocationConfiguration
294+
{
295+
Output = output,
296+
Error = output,
297+
};
298+
299+
await parseResult.InvokeAsync(commandLineConfiguration);
300+
301+
if (commandArgs is null)
302+
{
303+
throw new InvalidOperationException("Command arguments were not set during command execution. Output:" + output.ToString());
304+
}
305+
306+
return commandArgs;
307+
}
308+
}
309+
}

0 commit comments

Comments
 (0)