From c22bfdc9185e42621d07d8b6266a37f5c3156c27 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 31 Jan 2023 18:32:36 -0500 Subject: [PATCH 1/5] Added logic that creates instances of the user profile in a factory class This was added in a separate class of 'WaterfallStepContextExtensions' to facilitate unit testing. The advantage is that our new 'UserProfileFactory' class does not depend directly on 'WaterfallStepContext' (therefore it is no longer necessary to create an instance of this class in our unit tests). --- .../WaterfallStepContextExtensions.cs | 17 ++----------- .../Chatbot/Factories/UserProfileFactory.cs | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 src/Features/Chatbot/Factories/UserProfileFactory.cs diff --git a/src/Features/Chatbot/Extensions/WaterfallStepContextExtensions.cs b/src/Features/Chatbot/Extensions/WaterfallStepContextExtensions.cs index 44abc9a6..6844b9ae 100644 --- a/src/Features/Chatbot/Extensions/WaterfallStepContextExtensions.cs +++ b/src/Features/Chatbot/Extensions/WaterfallStepContextExtensions.cs @@ -8,21 +8,8 @@ public static class WaterfallStepContextExtensions public static UserProfile CreateUserProfileInstance(this WaterfallStepContext stepContext) { - var channelData = stepContext.Context.Activity.GetChannelData(); - var idWithoutPrefix = stepContext.Context - .Activity - .From - .Id - .Replace(oldValue: DirectLineService.Prefix, - newValue: string.Empty); - - var result = idWithoutPrefix.Split("-"); - var userProfile = new UserProfile - { - UserId = int.Parse(result[0]), - PersonId = int.Parse(result[1]), - FullName = channelData?.FullName - }; + var channelData = stepContext.Context.Activity.GetChannelData(); + var userProfile = UserProfileFactory.Create(channelData, stepContext.Context.Activity.From.Id); stepContext.Values[UserInfo] = userProfile; return userProfile; } diff --git a/src/Features/Chatbot/Factories/UserProfileFactory.cs b/src/Features/Chatbot/Factories/UserProfileFactory.cs new file mode 100644 index 00000000..c8667fad --- /dev/null +++ b/src/Features/Chatbot/Factories/UserProfileFactory.cs @@ -0,0 +1,24 @@ +namespace DentallApp.Features.Chatbot.Factories; + +public class UserProfileFactory +{ + public const string IdentifiersCouldNotBeExtractedSeparatelyMessage + = "The 'user ID' and 'person ID' could not be extracted separately from channel ID.\n" + + "This error may be caused by not following the format: " + + "{userID}-{personID}"; + + public static UserProfile Create(ChannelData channelData, string channelId) + { + var idWithoutPrefix = channelId.Replace(oldValue: DirectLineService.Prefix, newValue: string.Empty); + var identifiers = idWithoutPrefix.Split("-"); + if (identifiers.Length != 2) + throw new InvalidOperationException(IdentifiersCouldNotBeExtractedSeparatelyMessage); + var userProfile = new UserProfile + { + UserId = int.Parse(identifiers[0]), + PersonId = int.Parse(identifiers[1]), + FullName = channelData?.FullName + }; + return userProfile; + } +} From 91879c2bc9f9d093735c514c36f6dd8ab24320ac Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 31 Jan 2023 18:33:24 -0500 Subject: [PATCH 2/5] Added new constants to 'ActivityFactory' --- .../Features/Chatbot/Dialogs/ActivityFactory.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/DentallApp.UnitTests/Features/Chatbot/Dialogs/ActivityFactory.cs b/tests/DentallApp.UnitTests/Features/Chatbot/Dialogs/ActivityFactory.cs index 57da1a57..f3627213 100644 --- a/tests/DentallApp.UnitTests/Features/Chatbot/Dialogs/ActivityFactory.cs +++ b/tests/DentallApp.UnitTests/Features/Chatbot/Dialogs/ActivityFactory.cs @@ -2,11 +2,14 @@ public static class ActivityFactory { + private const string UserId = "1000"; + private const string PersonId = "2000"; + public static Activity CreateInitialActivity() => new() { Text = "Hi", - From = new ChannelAccount { Id = "dl_1000-2000", Name = "daveseva2010@hotmail.es" }, + From = new ChannelAccount { Id = $"dl_{UserId}-{PersonId}", Name = "daveseva2010@hotmail.es" }, ChannelData = JObject.Parse(@" { fullName: 'Dave Roman' From 23578d1370ebc38fd7f9341a5f60600e8a2f2f8e Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 31 Jan 2023 18:34:17 -0500 Subject: [PATCH 3/5] Added unit tests for class 'UserProfileFactory' --- .../Factories/UserProfileFactoryTests.cs | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tests/DentallApp.UnitTests/Features/Chatbot/Factories/UserProfileFactoryTests.cs diff --git a/tests/DentallApp.UnitTests/Features/Chatbot/Factories/UserProfileFactoryTests.cs b/tests/DentallApp.UnitTests/Features/Chatbot/Factories/UserProfileFactoryTests.cs new file mode 100644 index 00000000..812c28fd --- /dev/null +++ b/tests/DentallApp.UnitTests/Features/Chatbot/Factories/UserProfileFactoryTests.cs @@ -0,0 +1,75 @@ +namespace DentallApp.UnitTests.Features.Chatbot.Factories; + +[TestClass] +public class UserProfileFactoryTests +{ + [TestMethod] + public void Create_WhenChannelIdStartsWithPrefix_ShouldReturnsUserProfileInstance() + { + var channelData = new ChannelData(); + var channelId = "dl_1000-2000"; + + var userProfile = UserProfileFactory.Create(channelData, channelId); + + Assert.AreEqual(expected: 1000, actual: userProfile.UserId); + Assert.AreEqual(expected: 2000, actual: userProfile.PersonId); + Assert.IsNull(userProfile.FullName); + } + + [TestMethod] + public void Create_WhenChannelIdHasNotPrefix_ShouldReturnsUserProfileInstance() + { + var channelData = new ChannelData(); + var channelId = "1000-2000"; + + var userProfile = UserProfileFactory.Create(channelData, channelId); + + Assert.AreEqual(expected: 1000, actual: userProfile.UserId); + Assert.AreEqual(expected: 2000, actual: userProfile.PersonId); + Assert.IsNull(userProfile.FullName); + } + + [DataTestMethod] + [DataRow("dl_")] + [DataRow("dl_1000_2000")] + [DataRow("1000_2000")] + [DataRow("1000")] + [DataRow("dl_1000-2000-1-2")] + [DataRow("1000-2000-1-2")] + [DataRow("--")] + [DataRow("")] + [DataRow(" ")] + public void Create_WhenIdentifiersCouldNotBeExtractedSeparately_ShouldThrowInvalidOperationException(string channelId) + { + var channelData = new ChannelData(); + + void action() => UserProfileFactory.Create(channelData, channelId); + + var exception = Assert.ThrowsException(action); + StringAssert.Contains(exception.Message, UserProfileFactory.IdentifiersCouldNotBeExtractedSeparatelyMessage); + } + + [TestMethod] + public void Create_WhenChannelDataIsNull_ShouldReturnsFullNameWithNullValue() + { + ChannelData channelData = default; + var channelId = "dl_1000-2000"; + + var userProfile = UserProfileFactory.Create(channelData, channelId); + + Assert.IsNull(userProfile.FullName); + } + + [DataTestMethod] + [DataRow("")] + [DataRow("Dave Roman")] + public void Create_WhenChannelDataIsNotNull_ShouldReturnsFullNameWithValidValue(string value) + { + var channelData = new ChannelData { FullName = value }; + var channelId = "dl_1000-2000"; + + var userProfile = UserProfileFactory.Create(channelData, channelId); + + Assert.AreEqual(expected: value, actual: userProfile.FullName); + } +} From df55eeaf361427b5a52d144a5ccfcf5bb4d01640 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 31 Jan 2023 18:35:39 -0500 Subject: [PATCH 4/5] Added comments to the 'ChannelData' class --- src/Features/Chatbot/Models/ChannelData.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Features/Chatbot/Models/ChannelData.cs b/src/Features/Chatbot/Models/ChannelData.cs index d7f9a009..fb9f1b5a 100644 --- a/src/Features/Chatbot/Models/ChannelData.cs +++ b/src/Features/Chatbot/Models/ChannelData.cs @@ -1,5 +1,8 @@ namespace DentallApp.Features.Chatbot.Models; +/// +/// Represents the data of a channel such as Direct Line or WebChat. +/// public class ChannelData { /// From a4298fb43681c2beae9b18fb39765e737b03b6f1 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Tue, 31 Jan 2023 18:43:51 -0500 Subject: [PATCH 5/5] Added comments to the 'UserProfileFactory' class --- src/Features/Chatbot/Factories/UserProfileFactory.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Features/Chatbot/Factories/UserProfileFactory.cs b/src/Features/Chatbot/Factories/UserProfileFactory.cs index c8667fad..6f405fd4 100644 --- a/src/Features/Chatbot/Factories/UserProfileFactory.cs +++ b/src/Features/Chatbot/Factories/UserProfileFactory.cs @@ -1,5 +1,8 @@ namespace DentallApp.Features.Chatbot.Factories; +/// +/// A factory that can create instances. +/// public class UserProfileFactory { public const string IdentifiersCouldNotBeExtractedSeparatelyMessage @@ -7,6 +10,15 @@ public const string IdentifiersCouldNotBeExtractedSeparatelyMessage "This error may be caused by not following the format: " + "{userID}-{personID}"; + /// + /// Creates an instance of type . + /// + /// The channel data. + /// The channel ID. + /// + /// + /// The identifiers cannot be extracted separately from the channel ID. + /// public static UserProfile Create(ChannelData channelData, string channelId) { var idWithoutPrefix = channelId.Replace(oldValue: DirectLineService.Prefix, newValue: string.Empty);