From 01070f3332830abdd78165bcefc65757a19d4c84 Mon Sep 17 00:00:00 2001 From: Martijn Vos Date: Wed, 29 Jan 2025 11:06:19 +0100 Subject: [PATCH 1/6] Add missing suggestions derived types --- .../BusinessMessaging/Model/MultiChannel/SuggestionBase.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CM.Text/BusinessMessaging/Model/MultiChannel/SuggestionBase.cs b/CM.Text/BusinessMessaging/Model/MultiChannel/SuggestionBase.cs index 865d015..81cf7d4 100644 --- a/CM.Text/BusinessMessaging/Model/MultiChannel/SuggestionBase.cs +++ b/CM.Text/BusinessMessaging/Model/MultiChannel/SuggestionBase.cs @@ -6,8 +6,15 @@ namespace CM.Text.BusinessMessaging.Model.MultiChannel /// /// Suggestions can be used in several channels, not all channels /// support all suggestions. + /// + /// Requires a json derived type for serialization to work /// [PublicAPI] + [JsonDerivedType(typeof(CalendarSuggestion), nameof(CalendarSuggestion))] + [JsonDerivedType(typeof(DialSuggestion), nameof(DialSuggestion))] + [JsonDerivedType(typeof(OpenUrlSuggestion), nameof(OpenUrlSuggestion))] + [JsonDerivedType(typeof(ReplySuggestion), nameof(ReplySuggestion))] + [JsonDerivedType(typeof(ViewLocationSuggestion), nameof(ViewLocationSuggestion))] public abstract class SuggestionBase { /// From 3bbc41a08a232f86d4b2d4dba55515acc859b788 Mon Sep 17 00:00:00 2001 From: Martijn Vos Date: Wed, 29 Jan 2025 11:32:07 +0100 Subject: [PATCH 2/6] Remove action fields and specify 'action' as discriminator name --- .../Model/MultiChannel/CalendarSuggestion.cs | 6 ------ .../Model/MultiChannel/DialSuggestion.cs | 6 ------ .../Model/MultiChannel/OpenUrlSuggestion.cs | 6 ------ .../Model/MultiChannel/ReplySuggestion.cs | 6 ------ .../Model/MultiChannel/SuggestionBase.cs | 17 ++++++----------- .../MultiChannel/ViewLocationSuggestion.cs | 6 ------ 6 files changed, 6 insertions(+), 41 deletions(-) diff --git a/CM.Text/BusinessMessaging/Model/MultiChannel/CalendarSuggestion.cs b/CM.Text/BusinessMessaging/Model/MultiChannel/CalendarSuggestion.cs index c8768b2..2a52e55 100644 --- a/CM.Text/BusinessMessaging/Model/MultiChannel/CalendarSuggestion.cs +++ b/CM.Text/BusinessMessaging/Model/MultiChannel/CalendarSuggestion.cs @@ -11,12 +11,6 @@ namespace CM.Text.BusinessMessaging.Model.MultiChannel [PublicAPI] public class CalendarSuggestion : SuggestionBase { - /// - /// The action of this suggestion - /// - [JsonPropertyName("action")] - public override string Action => "CreateCalendarEvent"; - /// /// The options of the agenda item /// diff --git a/CM.Text/BusinessMessaging/Model/MultiChannel/DialSuggestion.cs b/CM.Text/BusinessMessaging/Model/MultiChannel/DialSuggestion.cs index 2508ae3..13c6894 100644 --- a/CM.Text/BusinessMessaging/Model/MultiChannel/DialSuggestion.cs +++ b/CM.Text/BusinessMessaging/Model/MultiChannel/DialSuggestion.cs @@ -11,12 +11,6 @@ namespace CM.Text.BusinessMessaging.Model.MultiChannel [PublicAPI] public class DialSuggestion : SuggestionBase { - /// - /// The action of this suggestion - /// - [JsonPropertyName("action")] - public override string Action => "Dial"; - /// /// The dial options /// diff --git a/CM.Text/BusinessMessaging/Model/MultiChannel/OpenUrlSuggestion.cs b/CM.Text/BusinessMessaging/Model/MultiChannel/OpenUrlSuggestion.cs index 267dd0a..66faff6 100644 --- a/CM.Text/BusinessMessaging/Model/MultiChannel/OpenUrlSuggestion.cs +++ b/CM.Text/BusinessMessaging/Model/MultiChannel/OpenUrlSuggestion.cs @@ -13,12 +13,6 @@ namespace CM.Text.BusinessMessaging.Model.MultiChannel [PublicAPI] public class OpenUrlSuggestion : SuggestionBase { - /// - /// The action of this suggestion - /// - [JsonPropertyName("action")] - public override string Action => "openUrl"; - /// /// The url the end user can open /// diff --git a/CM.Text/BusinessMessaging/Model/MultiChannel/ReplySuggestion.cs b/CM.Text/BusinessMessaging/Model/MultiChannel/ReplySuggestion.cs index d101b5f..2a1946e 100644 --- a/CM.Text/BusinessMessaging/Model/MultiChannel/ReplySuggestion.cs +++ b/CM.Text/BusinessMessaging/Model/MultiChannel/ReplySuggestion.cs @@ -9,12 +9,6 @@ namespace CM.Text.BusinessMessaging.Model.MultiChannel [PublicAPI] public class ReplySuggestion : SuggestionBase { - /// - /// The action of this suggestion - /// - [JsonPropertyName("action")] - public override string Action => "reply"; - /// /// Description of the Reply suggestion /// diff --git a/CM.Text/BusinessMessaging/Model/MultiChannel/SuggestionBase.cs b/CM.Text/BusinessMessaging/Model/MultiChannel/SuggestionBase.cs index 81cf7d4..df675ec 100644 --- a/CM.Text/BusinessMessaging/Model/MultiChannel/SuggestionBase.cs +++ b/CM.Text/BusinessMessaging/Model/MultiChannel/SuggestionBase.cs @@ -10,19 +10,14 @@ namespace CM.Text.BusinessMessaging.Model.MultiChannel /// Requires a json derived type for serialization to work /// [PublicAPI] - [JsonDerivedType(typeof(CalendarSuggestion), nameof(CalendarSuggestion))] - [JsonDerivedType(typeof(DialSuggestion), nameof(DialSuggestion))] - [JsonDerivedType(typeof(OpenUrlSuggestion), nameof(OpenUrlSuggestion))] - [JsonDerivedType(typeof(ReplySuggestion), nameof(ReplySuggestion))] - [JsonDerivedType(typeof(ViewLocationSuggestion), nameof(ViewLocationSuggestion))] + [JsonPolymorphic(TypeDiscriminatorPropertyName = "action")] + [JsonDerivedType(typeof(CalendarSuggestion), "CreateCalendarEvent")] + [JsonDerivedType(typeof(DialSuggestion), "Dial")] + [JsonDerivedType(typeof(OpenUrlSuggestion), "openUrl")] + [JsonDerivedType(typeof(ReplySuggestion), "reply")] + [JsonDerivedType(typeof(ViewLocationSuggestion), "viewLocation")] public abstract class SuggestionBase { - /// - /// The action of this suggestion - /// - [JsonPropertyName("action")] - public virtual string Action { get; } - /// /// The text the end user will see /// diff --git a/CM.Text/BusinessMessaging/Model/MultiChannel/ViewLocationSuggestion.cs b/CM.Text/BusinessMessaging/Model/MultiChannel/ViewLocationSuggestion.cs index df20cf5..e9d988d 100644 --- a/CM.Text/BusinessMessaging/Model/MultiChannel/ViewLocationSuggestion.cs +++ b/CM.Text/BusinessMessaging/Model/MultiChannel/ViewLocationSuggestion.cs @@ -9,12 +9,6 @@ namespace CM.Text.BusinessMessaging.Model.MultiChannel [PublicAPI] public class ViewLocationSuggestion : SuggestionBase { - /// - /// The action of this suggestion - /// - [JsonPropertyName("action")] - public override string Action => "viewLocation"; - /// /// The location options /// From abf379fba924c82cdc29c98dad6a0c9f401f1e07 Mon Sep 17 00:00:00 2001 From: Martijn Vos Date: Wed, 29 Jan 2025 13:11:01 +0100 Subject: [PATCH 3/6] Make EndTime and StartTime properties instead of fields for serialization to work --- .../BusinessMessaging/Model/MultiChannel/CalendarOptions.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CM.Text/BusinessMessaging/Model/MultiChannel/CalendarOptions.cs b/CM.Text/BusinessMessaging/Model/MultiChannel/CalendarOptions.cs index 0e7744f..7122d14 100644 --- a/CM.Text/BusinessMessaging/Model/MultiChannel/CalendarOptions.cs +++ b/CM.Text/BusinessMessaging/Model/MultiChannel/CalendarOptions.cs @@ -13,12 +13,14 @@ public class CalendarOptions /// /// The end of the appointment. /// - [JsonPropertyName("endTime")] public DateTime EndTime; + [JsonPropertyName("endTime")] + public DateTime EndTime { get; set; } /// /// The start of the appointment. /// - [JsonPropertyName("startTime")] public DateTime StartTime; + [JsonPropertyName("startTime")] + public DateTime StartTime { get; set; } /// /// The description which will appear in the calendar app From 86bd4f0d90b4af5d788082ac67cb1d35ce7e15c6 Mon Sep 17 00:00:00 2001 From: Martijn Vos Date: Wed, 29 Jan 2025 15:07:32 +0100 Subject: [PATCH 4/6] Add Suggestion serialization tests --- CM.Text.Tests/SuggestionsTests.cs | 123 ++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 CM.Text.Tests/SuggestionsTests.cs diff --git a/CM.Text.Tests/SuggestionsTests.cs b/CM.Text.Tests/SuggestionsTests.cs new file mode 100644 index 0000000..a22c3ea --- /dev/null +++ b/CM.Text.Tests/SuggestionsTests.cs @@ -0,0 +1,123 @@ +using System.Text.Json; +using CM.Text.BusinessMessaging.Model.MultiChannel; +using FluentAssertions; + +namespace CM.Text.Tests +{ + [TestClass] + public class SuggestionsTests + { + [TestMethod] + public void SerializationCalendarSuggestionTest() + { + var calenderSuggestion = new CalendarSuggestion() + { + Calendar = new CalendarOptions() + { + Title = "Appointment selection", + Description = "Schedule an appointment with us", + EndTime = DateTime.UtcNow, + StartTime = DateTime.UtcNow, + } + }; + + var serialized= JsonSerializer.Serialize(calenderSuggestion); + + serialized.Should().NotBeNullOrWhiteSpace(); + + var deserialized = JsonSerializer.Deserialize(serialized); + + deserialized.Should().BeOfType(); + var deserializedCalendarSuggestion = deserialized as CalendarSuggestion; + deserializedCalendarSuggestion.Should().BeEquivalentTo(calenderSuggestion); + } + + [TestMethod] + public void SerializationDialSuggestionTest() + { + var dialSuggestion = new DialSuggestion() + { + Dial = new Dial() + { + PhoneNumber = "0031612345678" + } + }; + + var serialized= JsonSerializer.Serialize(dialSuggestion); + + serialized.Should().NotBeNullOrWhiteSpace(); + + var deserialized = JsonSerializer.Deserialize(serialized); + + deserialized.Should().BeOfType(); + var deserializedDialSuggestion = deserialized as DialSuggestion; + deserializedDialSuggestion.Should().BeEquivalentTo(dialSuggestion); + } + + [TestMethod] + public void SerializationOpenUrlSuggestionTest() + { + var openUrlSuggestion = new OpenUrlSuggestion() + { + Url = "https://www.cm.com" + }; + + var serialized= JsonSerializer.Serialize(openUrlSuggestion); + + serialized.Should().NotBeNullOrWhiteSpace(); + + var deserialized = JsonSerializer.Deserialize(serialized); + + deserialized.Should().BeOfType(); + var deserializedOpenUrlSuggestion = deserialized as OpenUrlSuggestion; + deserializedOpenUrlSuggestion.Should().BeEquivalentTo(openUrlSuggestion); + } + + [TestMethod] + public void SerializationViewLocationSuggestionTest() + { + var viewLocationSuggestion = new ViewLocationSuggestion() + { + Location = new ViewLocationOptions() + { + Label = "CM.com headquarters", + Latitude = "51.602885", + Longitude = "4.7683932", + SearchQuery = "CM.com headquarters", + Radius = 5 + } + }; + + var serialized= JsonSerializer.Serialize(viewLocationSuggestion); + + serialized.Should().NotBeNullOrWhiteSpace(); + + var deserialized = JsonSerializer.Deserialize(serialized); + + deserialized.Should().BeOfType(); + var deserializedViewLocationSuggestion = deserialized as ViewLocationSuggestion; + deserializedViewLocationSuggestion.Should().BeEquivalentTo(viewLocationSuggestion); + } + + [TestMethod] + public void SerializationReplySuggestionTest() + { + var replySuggestion = new ReplySuggestion() + { + Label = "Some label", + PostbackData = "LABEL", + Description = "Description of the label", + Media = new MediaContent("Test image", "https://example.com", "image/jpg") + }; + var serialized= JsonSerializer.Serialize(replySuggestion); + + serialized.Should().NotBeNullOrWhiteSpace(); + + var deserialized = JsonSerializer.Deserialize(serialized); + + deserialized.Should().BeOfType(); + var deserializedReplySuggestion = deserialized as ReplySuggestion; + deserializedReplySuggestion.Should().BeEquivalentTo(replySuggestion); + } + } +} From 5af0a2bdb53ff29f482961777c83d7279c0758f8 Mon Sep 17 00:00:00 2001 From: Martijn Vos Date: Wed, 29 Jan 2025 17:56:19 +0100 Subject: [PATCH 5/6] Update CHANGELOG.md and csproj version --- CHANGELOG.md | 4 ++++ CM.Text/CM.Text.csproj | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12b6f76..dd0297a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.11.1] - TBD +### Added +- Derived type declarations on `SuggestionBase` + ## [2.11.0] - 2025-01-10 ### Added - Context.MessageId on RichMessages supporting WhatsApp for referencing a previous message diff --git a/CM.Text/CM.Text.csproj b/CM.Text/CM.Text.csproj index f8d9970..a96c07e 100644 --- a/CM.Text/CM.Text.csproj +++ b/CM.Text/CM.Text.csproj @@ -13,12 +13,12 @@ LICENSE icon.png $([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/../CHANGELOG.md")) - 2.11.0 + 2.11.1 https://github.com/cmdotcom/text-sdk-dotnet en true - 2.11.0 - 2.11.0 + 2.11.1 + 2.11.1 True From 60d8e6efac7be02ed08544fd0238867dc8da3711 Mon Sep 17 00:00:00 2001 From: Martijn Vos Date: Fri, 31 Jan 2025 15:07:19 +0100 Subject: [PATCH 6/6] Add release date in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd0297a..22fb1ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.11.1] - TBD +## [2.11.1] - 2025-01-31 ### Added - Derived type declarations on `SuggestionBase`