Skip to content

Commit

Permalink
support Trello's named bottom position
Browse files Browse the repository at this point in the history
  • Loading branch information
GSGBen committed Dec 9, 2021
1 parent b53be1c commit df94682
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 16 deletions.
19 changes: 13 additions & 6 deletions T2MDCli/Cli.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,19 @@ class Cli
private static string _outputPath = "";

// shared options for json work
private static JsonSerializerOptions _jsonDeserializeOptions = new JsonSerializerOptions();
private static JsonSerializerOptions _jsonDeserializeOptions = new JsonSerializerOptions
{
// match camelCase json to PascalCase C# class
PropertyNameCaseInsensitive = true,
// some users have boards (in the per-board processing later, but set all together here)
// with pos values as strings, e.g. "123.45". Support those
NumberHandling = JsonNumberHandling.AllowReadingFromString,
// Trello also (used to?) encode some positions as "bottom". Handle that
Converters =
{
new TrelloDoubleJsonConverter()
}
};

static async Task Main(string[] args)
{
Expand Down Expand Up @@ -109,11 +121,6 @@ private static async Task RunAsync(CliOptions options)
var url = $"https://api.trello.com/1/members/me/boards?key={_apiKey}&token={_apiToken}";
string textResponse = await _httpClient.GetStringAsync(url).ConfigureAwait(false);
var trelloApiBoards = new List<TrelloApiBoardModel>();
// match camelCase json to PascalCase C# class
_jsonDeserializeOptions.PropertyNameCaseInsensitive = true;
// some users have boards (in the per-board processing later, but set all together here)
// with pos values as strings, e.g. "123.45". Support those
_jsonDeserializeOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString;
trelloApiBoards = JsonSerializer.Deserialize<List<TrelloApiBoardModel>>(textResponse, _jsonDeserializeOptions);
if (trelloApiBoards == null)
{
Expand Down
54 changes: 54 additions & 0 deletions T2MDCli/Converters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace GoldenSyrupGames.T2MD
{
/// <summary>
/// Trello sometimes has e.g. pos as "bottom" instead of 123.45 or "123.45", so handle that.
/// </summary>
public class TrelloDoubleJsonConverter : JsonConverter<Double>
{
public override Double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
string? stringValue = reader.GetString();
// handle the weird values
if (stringValue == "bottom")
{
return double.MaxValue - 1;
}
else if (stringValue == "top")
{
return 0.0;
}
// standard double as string
else if (double.TryParse(stringValue, out double value))
{
return value;
}
else
{
throw new System.Text.Json.JsonException($"Couldn't parse the string `{stringValue}` as a double or as one of Trello's positions");
}
}
// double without string
else if (reader.TokenType == JsonTokenType.Number)
{
return reader.GetDouble();
}
// else
throw new System.Text.Json.JsonException();
}

public override void Write(Utf8JsonWriter writer, Double doubleValue, JsonSerializerOptions options)
{
writer.WriteNumberValue(doubleValue);
}
}
}
2 changes: 1 addition & 1 deletion T2MDCli/T2MDCli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<AssemblyName>t2md</AssemblyName>
<Authors>Ben Renninson</Authors>
<Company>Golden Syrup Games</Company>
<Version>1.0.0</Version>
<Version>1.0.2</Version>
<Copyright>2021 Golden Syrup Games</Copyright>
<PackageLicenseExpression></PackageLicenseExpression>

Expand Down
18 changes: 9 additions & 9 deletions T2MDCli/TrelloModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace GoldenSyrupGames.T2MD
/// <summary>
/// Partial model of the API response to /board (maybe?) to deserialize json to. We only use this as listed in the response to /members/me/boards.
/// </summary>
class TrelloApiBoardModel
public class TrelloApiBoardModel
{
public string Name { get; set; } = "";
public string ShortLink { get; set; } = "";
Expand All @@ -31,7 +31,7 @@ public bool AreAllRequiredFieldsFilled()
/// <summary>
/// Partial model of the json from backing up a Trello board (via the web UI, not via the API. E.g. trello.com/b/<id>.json
/// </summary>
class TrelloBoardModel
public class TrelloBoardModel
{
public string Name { get; set; } = "";
public string ShortLink { get; set; } = "";
Expand All @@ -57,7 +57,7 @@ public bool AreAllRequiredFieldsFilled()
/// <summary>
/// Partial model of lists forming part of TrelloBoardModel, + some extra properties we store results in.
/// </summary>
class TrelloListModel
public class TrelloListModel
{
public string Name { get; set; } = "";
public string ID { get; set; } = "";
Expand Down Expand Up @@ -103,7 +103,7 @@ public bool AreAllRequiredFieldsFilled()
/// <summary>
/// Partial model of cards forming part of TrelloBoardModel
/// </summary>
class TrelloCardModel
public class TrelloCardModel
{
public string Name { get; set; } = "";
public string ID { get; set; } = "";
Expand Down Expand Up @@ -147,7 +147,7 @@ public bool AreAllRequiredFieldsFilled()
/// <summary>
/// Partial model of checklists forming part of TrelloBoardModel
/// </summary>
class TrelloChecklistModel
public class TrelloChecklistModel
{
public string Name { get; set; } = "";
public string ID { get; set; } = "";
Expand Down Expand Up @@ -182,7 +182,7 @@ public bool AreAllRequiredFieldsFilled()
/// <summary>
/// Partial model of checklists forming part of TrelloBoardModel
/// </summary>
class TrelloCheckItemModel
public class TrelloCheckItemModel
{
public string Name { get; set; } = "";
public string ID { get; set; } = "";
Expand Down Expand Up @@ -217,7 +217,7 @@ public bool AreAllRequiredFieldsFilled()
/// <summary>
/// Partial model of card actions (like commenting) forming part of TrelloBoardModel
/// </summary>
class TrelloActionModel
public class TrelloActionModel
{
public string ID { get; set; } = "";
/// <summary>
Expand Down Expand Up @@ -249,7 +249,7 @@ public bool AreAllRequiredFieldsFilled()
/// <summary>
/// Partial model of card actions inner data forming part of TrelloBoardModel
/// </summary>
class TrelloActionDataModel
public class TrelloActionDataModel
{
/// <summary>
/// E.g. the contents of the comment
Expand All @@ -264,7 +264,7 @@ class TrelloActionDataModel
/// <summary>
/// partial model of a card's attachment forming part of TrelloBoardModel, + some extra properties we store results in.
/// </summary>
class TrelloAttachmentModel
public class TrelloAttachmentModel
{
public bool IsUpload { get; set; } = false;
public string Name { get; set; } = "";
Expand Down
70 changes: 70 additions & 0 deletions T2MDCliTests/ConvertersTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Text.Json.Serialization;
using System.Text.Json;

namespace GoldenSyrupGames.T2MD.Tests
{
[TestClass]
public class TrelloDoubleJsonConverterTests
{
private JsonSerializerOptions _jsonDeserializeOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
NumberHandling = JsonNumberHandling.AllowReadingFromString,
Converters =
{
new TrelloDoubleJsonConverter()
}
};

// runs before each test
[TestInitialize]
public void Initialize()
{
}

// ensure the default number handling still works (double)
[TestMethod]
public void Read_JsonDouble_ReturnsDouble()
{
double number = 65535.0;
var trelloCardJson = $"{{\"pos\": {number}}}";
var trelloCard = JsonSerializer.Deserialize<TrelloCardModel>(trelloCardJson, _jsonDeserializeOptions);

Assert.AreEqual(number, trelloCard.Pos);
}

// ensure the default number handling still works (int)
[TestMethod]
public void Read_JsonInt_ReturnsDouble()
{
int number = 65535;
var trelloCardJson = $"{{\"pos\": {number}}}";
var trelloCard = JsonSerializer.Deserialize<TrelloCardModel>(trelloCardJson, _jsonDeserializeOptions);

Assert.AreEqual(number, trelloCard.Pos);
}

// ensure converting from string works
[TestMethod]
public void Read_JsonNumberInString_ReturnsDouble()
{
double number = 65535.0;
var trelloCardJson = $"{{\"pos\": \"{number}\"}}";
var trelloCard = JsonSerializer.Deserialize<TrelloCardModel>(trelloCardJson, _jsonDeserializeOptions);

Assert.AreEqual(number, trelloCard.Pos);
}

// ensure converting Trello's custom positions works
[TestMethod]
public void Read_Bottom_ReturnsDouble()
{
var trelloCardJson = "{\"pos\": \"bottom\"}";
var trelloCard = JsonSerializer.Deserialize<TrelloCardModel>(trelloCardJson, _jsonDeserializeOptions);

Assert.IsInstanceOfType(trelloCard.Pos, typeof(double));
}

}
}
20 changes: 20 additions & 0 deletions T2MDCliTests/T2MDCliTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
<PackageReference Include="coverlet.collector" Version="1.3.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\T2MDCli\T2MDCli.csproj" />
</ItemGroup>

</Project>

0 comments on commit df94682

Please sign in to comment.