Skip to content

Commit e4fa49e

Browse files
committed
Update System.CommandLine dependency to allow setting empty values
1 parent 113e07d commit e4fa49e

File tree

6 files changed

+116
-9
lines changed

6 files changed

+116
-9
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.CommandLine;
3+
using System.CommandLine.IO;
4+
using System.IO;
5+
using System.Threading.Tasks;
6+
using dotnet_json.Commands;
7+
using FluentAssertions;
8+
using Newtonsoft.Json;
9+
using Newtonsoft.Json.Linq;
10+
using Xunit;
11+
12+
namespace dotnet_json.Tests.Commands
13+
{
14+
public class SetCommandTests : IDisposable
15+
{
16+
private readonly string _tmpDir;
17+
18+
public SetCommandTests()
19+
{
20+
_tmpDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
21+
Directory.CreateDirectory(_tmpDir);
22+
}
23+
24+
public void Dispose()
25+
{
26+
Directory.Delete(_tmpDir, true);
27+
}
28+
29+
[Theory]
30+
[InlineData(@"{""key"": ""value""}", "key", "test")]
31+
[InlineData(@"{""key"": ""value""}", "key", "")]
32+
public async Task SavesNewValueToFile(string json, string key, string value)
33+
{
34+
await File.WriteAllTextAsync(Path.Join(_tmpDir, "test.json"), json);
35+
36+
var (exitCode, _) = await RunCommand(Path.Join(_tmpDir, "test.json"), key, value);
37+
38+
exitCode.Should().Be(0);
39+
40+
var contents = await File.ReadAllTextAsync(Path.Join(_tmpDir, "test.json"));
41+
var result = JObject.Parse(contents)[key].ToString();
42+
43+
result.Should().Be(value);
44+
}
45+
46+
private async Task<(int exitCode, IConsole console)> RunCommand(params string[] arguments)
47+
{
48+
var command = new SetCommand();
49+
50+
var console = new TestConsole();
51+
52+
var exitCode = await command.InvokeAsync(arguments, console);
53+
54+
return (exitCode, console);
55+
}
56+
}
57+
}

dotnet-json.Tests/JsonDocumentTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,22 @@ public void SetValue_ReplacesValue_WithObject()
199199
.Which.Value.Should().Be("object");
200200
}
201201

202+
[Fact]
203+
public void SetValue_ReplacesValue_WithEmptyString()
204+
{
205+
var document = new JsonDocument(JObject.Parse(@"{ ""key"": ""value"" }"));
206+
207+
document.SetValue("key", "");
208+
209+
document._json.Should().BeOfType<JObject>()
210+
.Which.Should().ContainKey("key");
211+
212+
var value = document._json["key"].Should().BeOfType<JValue>().Subject;
213+
214+
value.Type.Should().Be(JTokenType.String);
215+
value.Value.Should().Be("");
216+
}
217+
202218
[Fact]
203219
public void Merge_MergesTwoDocuments()
204220
{

dotnet-json/Commands/CommandBase.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ protected CommandBase(string name, string? description = null, bool includeOutpu
3131
Handler = this;
3232
}
3333

34+
public int Invoke(InvocationContext context)
35+
{
36+
return InvokeAsync(context).GetAwaiter().GetResult();
37+
}
38+
3439
public Task<int> InvokeAsync(InvocationContext context)
3540
{
3641
Context = context;
@@ -76,12 +81,6 @@ protected T GetParameterValue<T>(Argument<T> argument)
7681
.ParseResult.GetValueForArgument(argument);
7782
}
7883

79-
protected List<T>? GetMultiParameterValue<T>(Argument<T> argument)
80-
{
81-
return (Context ?? throw new Exception("GetMultiParameterValue() must be called from a command handler"))
82-
.ParseResult.GetValueForArgument<List<T>>(argument);
83-
}
84-
8584
protected abstract Task<int> ExecuteAsync();
8685
}
8786
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System.Collections.Generic;
2+
using System.CommandLine;
3+
using System.IO;
4+
using System.Linq;
5+
6+
namespace dotnet_json.Commands
7+
{
8+
public class FilesArgument : Argument<List<string>>
9+
{
10+
public FilesArgument()
11+
{
12+
AddValidator();
13+
}
14+
15+
public FilesArgument(string name, string? description = null)
16+
: base(name, description)
17+
{
18+
AddValidator();
19+
}
20+
21+
public bool AllowNewFile { get; set; }
22+
23+
private void AddValidator()
24+
{
25+
this.AddValidator(symbol =>
26+
symbol.Tokens
27+
.Select(t => t.Value)
28+
.Where(_ => !AllowNewFile) // Need to check AllowNewFile at this point because AddValidator() is called from constructor
29+
.Where(filePath => filePath != "-")
30+
.Where(filePath => !File.Exists(filePath))
31+
.Select(filePath => $"File does not exist: {filePath}")
32+
.FirstOrDefault());
33+
}
34+
}
35+
}

dotnet-json/Commands/MergeCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace dotnet_json.Commands
88
{
99
public class MergeCommand : CommandBase
1010
{
11-
private FileArgument Files = new FileArgument("files", "The names of the files to merge with the first file.") { Arity = ArgumentArity.OneOrMore };
11+
private FilesArgument Files = new FilesArgument("files", "The names of the files to merge with the first file.") { Arity = ArgumentArity.OneOrMore };
1212

1313
public MergeCommand() : base("merge", "merge two or more json files into one")
1414
{
@@ -19,7 +19,7 @@ public MergeCommand() : base("merge", "merge two or more json files into one")
1919

2020
protected override async Task<int> ExecuteAsync()
2121
{
22-
var files = GetMultiParameterValue(Files) ?? throw new ArgumentException("Missing argument <files>");
22+
var files = GetParameterValue(Files) ?? throw new ArgumentException("Missing argument <files>");
2323

2424
JsonDocument document;
2525

dotnet-json/dotnet-json.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
<ItemGroup>
3131
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
32-
<PackageReference Include="System.CommandLine" Version="2.0.0-beta2.21617.1" />
32+
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
3333
</ItemGroup>
3434

3535
<ItemGroup>

0 commit comments

Comments
 (0)