-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implement new `FlagWithTimestamp` type and associated converter. * Re-implement `QuestionActivity.Closed` as `FlagWithTimestamp`.
- Loading branch information
1 parent
72569db
commit 2027c5f
Showing
6 changed files
with
322 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
Source/ActivityPub.Types/Conversion/Converters/FlagWithTimestampConverter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. | ||
// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using ActivityPub.Types.Util; | ||
|
||
namespace ActivityPub.Types.Conversion.Converters; | ||
|
||
/// <summary> | ||
/// Custom JSON converter for <see cref="FlagWithTimestamp"/>. | ||
/// </summary> | ||
public class FlagWithTimestampConverter : JsonConverter<FlagWithTimestamp> | ||
{ | ||
/// <inheritdoc /> | ||
public override FlagWithTimestamp? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
=> reader.TokenType switch | ||
{ | ||
JsonTokenType.Null => null, | ||
JsonTokenType.True => new FlagWithTimestamp { Value = true }, | ||
JsonTokenType.False => new FlagWithTimestamp { Value = false }, | ||
JsonTokenType.String => new FlagWithTimestamp { Timestamp = reader.GetDateTime() }, | ||
_ => throw new JsonException($"Can't convert {reader.TokenType} as {nameof(FlagWithTimestamp)}") | ||
}; | ||
|
||
/// <inheritdoc /> | ||
public override void Write(Utf8JsonWriter writer, FlagWithTimestamp value, JsonSerializerOptions options) | ||
{ | ||
if (value.Timestamp != null) | ||
writer.WriteStringValue(value.Timestamp.Value); | ||
else | ||
writer.WriteBooleanValue(value.Value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. | ||
// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
using System.Text.Json.Serialization; | ||
using ActivityPub.Types.Conversion.Converters; | ||
|
||
namespace ActivityPub.Types.Util; | ||
|
||
/// <summary> | ||
/// A value that can be a <see langword="boolean"/> flag or a <see cref="DateTime"/> timestamp. | ||
/// For example, <see cref="ActivityPub.Types.AS.Extended.Activity.QuestionActivity.Closed"/>. | ||
/// </summary> | ||
[JsonConverter(typeof(FlagWithTimestampConverter))] | ||
public class FlagWithTimestamp | ||
{ | ||
/// <summary> | ||
/// The <see langword="boolean"/> value of this flag. | ||
/// Will be true if <see cref="Timestamp"/> has a value. | ||
/// If set to false, then <see cref="Timestamp"/> will also be set to <see langword="null"/>. | ||
/// </summary> | ||
public bool Value | ||
{ | ||
get => _value; | ||
set | ||
{ | ||
_value = value; | ||
if (!value) | ||
_timestamp = null; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// The timestamp of this flag, is present. | ||
/// If set to a value, then <see cref="Timestamp"/> will automatically change to <see langword="true"/>. | ||
/// If set to <see langword="null"/>, then <see cref="Timestamp"/> will automatically change to <see langword="false"/>. | ||
/// </summary> | ||
public DateTime? Timestamp | ||
{ | ||
get => _timestamp; | ||
set | ||
{ | ||
_value = value != null; | ||
_timestamp = value; | ||
} | ||
} | ||
|
||
private bool _value; | ||
private DateTime? _timestamp; | ||
|
||
/// <summary> | ||
/// Returns the value of <see cref="Value"/>. | ||
/// </summary> | ||
public static implicit operator bool(FlagWithTimestamp flag) => flag.Value; | ||
|
||
/// <summary> | ||
/// Returns the value of <see cref="Timestamp"/>; | ||
/// </summary> | ||
public static implicit operator DateTime?(FlagWithTimestamp flag) => flag.Timestamp; | ||
|
||
/// <summary> | ||
/// Creates a flag with the specified value for <see cref="Value"/>. | ||
/// </summary> | ||
public static implicit operator FlagWithTimestamp(bool value) => new() { Value = value }; | ||
|
||
/// <summary> | ||
/// Creates a flag with the specified value for <see cref="Timestamp"/>. | ||
/// </summary> | ||
public static implicit operator FlagWithTimestamp(DateTime timestamp) => new() { Timestamp = timestamp }; | ||
} |
94 changes: 94 additions & 0 deletions
94
Test/ActivityPub.Types.Tests/Unit/Conversion/Converters/FlagWithTimestampConverterTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. | ||
// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
using ActivityPub.Types.Conversion.Converters; | ||
using ActivityPub.Types.Util; | ||
|
||
namespace ActivityPub.Types.Tests.Unit.Conversion.Converters; | ||
|
||
public abstract class FlagWithTimestampConverterTests : JsonConverterTests<FlagWithTimestamp, FlagWithTimestampConverter> | ||
{ | ||
protected override FlagWithTimestampConverter ConverterUnderTest { get; set; } = new(); | ||
|
||
public class ReadShould : FlagWithTimestampConverterTests | ||
{ | ||
[Fact] | ||
public void ConvertFromNull() | ||
{ | ||
var flag = Read("null"u8); | ||
flag.Should().BeNull(); | ||
} | ||
|
||
[Fact] | ||
public void ConvertFromTrue() | ||
{ | ||
var flag = Read("true"u8); | ||
flag.Should().NotBeNull(); | ||
flag!.Value.Should().BeTrue(); | ||
flag.Timestamp.Should().BeNull(); | ||
} | ||
|
||
[Fact] | ||
public void ConvertFromFalse() | ||
{ | ||
var flag = Read("false"u8); | ||
flag.Should().NotBeNull(); | ||
flag!.Value.Should().BeFalse(); | ||
flag.Timestamp.Should().BeNull(); | ||
} | ||
|
||
[Fact] | ||
public void ConvertFromDateTime() | ||
{ | ||
var flag = Read("\"2024-01-01T00:00:00\""u8); | ||
flag.Should().NotBeNull(); | ||
flag!.Value.Should().BeTrue(); | ||
flag.Timestamp.Should().Be(new DateTime(2024, 1, 1)); | ||
} | ||
|
||
[Theory] | ||
[InlineData("1")] | ||
[InlineData("{}")] | ||
[InlineData("[]")] | ||
public void ThrowOnOtherInput(string json) | ||
{ | ||
Assert.Throws<JsonException>(() => | ||
{ | ||
Read(json); | ||
}); | ||
} | ||
} | ||
|
||
public class WriteShould : FlagWithTimestampConverterTests | ||
{ | ||
[Theory] | ||
[InlineData(true, "true")] | ||
[InlineData(false, "false")] | ||
public void WriteValueToBool(bool value, string expectedJson) | ||
{ | ||
var flag = new FlagWithTimestamp { Value = value }; | ||
var actualJson = Write(flag); | ||
actualJson.Should().Be(expectedJson); | ||
} | ||
|
||
[Fact] | ||
public void WriteTimestampToString() | ||
{ | ||
var flag = new FlagWithTimestamp { Timestamp = new DateTime(2024, 1, 1) }; | ||
var json = Write(flag); | ||
json.Should().Be("\"2024-01-01T00:00:00\""); | ||
} | ||
|
||
[Fact] | ||
public void WriteTimestamp_WhenBothAreSet() | ||
{ | ||
var flag = new FlagWithTimestamp | ||
{ | ||
Timestamp = new DateTime(2024, 1, 1), | ||
Value = true | ||
}; | ||
var json = Write(flag); | ||
json.Should().Be("\"2024-01-01T00:00:00\""); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
Test/ActivityPub.Types.Tests/Unit/Util/FlagWithTimestampTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. | ||
// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
using ActivityPub.Types.Util; | ||
|
||
namespace ActivityPub.Types.Tests.Unit.Util; | ||
|
||
public abstract class FlagWithTimestampTests | ||
{ | ||
private FlagWithTimestamp? FlagUnderTest { get; set; } | ||
|
||
public class ValueShould : FlagWithTimestampTests | ||
{ | ||
[Fact] | ||
public void ConvertFromTrue() | ||
{ | ||
FlagUnderTest = true; | ||
FlagUnderTest.Value.Should().BeTrue(); | ||
} | ||
|
||
[Fact] | ||
public void ConvertFromFalse() | ||
{ | ||
FlagUnderTest = false; | ||
FlagUnderTest.Value.Should().BeFalse(); | ||
} | ||
|
||
[Fact] | ||
public void ConvertToTrue() | ||
{ | ||
bool value = new FlagWithTimestamp { Value = true }; | ||
value.Should().BeTrue(); | ||
} | ||
|
||
[Fact] | ||
public void ConvertToFalse() | ||
{ | ||
bool value = new FlagWithTimestamp { Value = false }; | ||
value.Should().BeFalse(); | ||
} | ||
|
||
[Fact] | ||
public void SetTimeStampToNull_WhenSetToFalse() | ||
{ | ||
FlagUnderTest = new DateTime(2024, 1, 1); | ||
FlagUnderTest.Value = false; | ||
FlagUnderTest.Timestamp.Should().BeNull(); | ||
} | ||
|
||
[Fact] | ||
public void IgnoreTimestamp_WhenSetToTrue() | ||
{ | ||
FlagUnderTest = new DateTime(2024, 1, 1); | ||
FlagUnderTest.Value = true; | ||
FlagUnderTest.Timestamp.Should().NotBeNull(); | ||
} | ||
} | ||
|
||
public class TimestampShould : FlagWithTimestampTests | ||
{ | ||
[Fact] | ||
public void ConvertFromTimestamp() | ||
{ | ||
var timestamp = new DateTime(2024, 1, 1); | ||
FlagUnderTest = timestamp; | ||
FlagUnderTest.Timestamp.Should().Be(timestamp); | ||
} | ||
|
||
[Fact] | ||
public void ConvertToNull() | ||
{ | ||
DateTime? timestamp = new FlagWithTimestamp { Timestamp = null }; | ||
timestamp.Should().BeNull(); | ||
} | ||
|
||
[Fact] | ||
public void ConvertToTimestamp() | ||
{ | ||
var expectedTimestamp = new DateTime(2024, 1, 1); | ||
DateTime? actualTimestamp = new FlagWithTimestamp { Timestamp = expectedTimestamp }; | ||
actualTimestamp.Should().Be(expectedTimestamp); | ||
} | ||
|
||
[Fact] | ||
public void SetValueToTrue_WhenSetToTimestamp() | ||
{ | ||
FlagUnderTest = false; | ||
FlagUnderTest.Timestamp = new DateTime(2024, 1, 1); | ||
FlagUnderTest.Value.Should().BeTrue(); | ||
} | ||
|
||
[Fact] | ||
public void SetValueToFalse_WhenSetToNull() | ||
{ | ||
FlagUnderTest = true; | ||
FlagUnderTest.Timestamp = null; | ||
FlagUnderTest.Value.Should().BeFalse(); | ||
} | ||
} | ||
} |