From 2eb13da7f1172429ecc0f6c5f95d32d51c5ac876 Mon Sep 17 00:00:00 2001 From: "Rafael Pacheco (Take)" Date: Fri, 10 Nov 2017 11:40:53 -0200 Subject: [PATCH 1/3] Add event models and send methods on client --- Chatbase.Tests/EventSetTests.cs | 28 ++++++++++++++++ Chatbase.Tests/EventTests.cs | 56 +++++++++++++++++++++++++++++++ Chatbase/Client.cs | 55 +++++++++++++++++++++++++----- Chatbase/Event.cs | 59 +++++++++++++++++++++++++++++++++ Chatbase/EventProperty.cs | 24 ++++++++++++++ Chatbase/EventSet.cs | 39 ++++++++++++++++++++++ 6 files changed, 253 insertions(+), 8 deletions(-) create mode 100644 Chatbase.Tests/EventSetTests.cs create mode 100644 Chatbase.Tests/EventTests.cs create mode 100644 Chatbase/Event.cs create mode 100644 Chatbase/EventProperty.cs create mode 100644 Chatbase/EventSet.cs diff --git a/Chatbase.Tests/EventSetTests.cs b/Chatbase.Tests/EventSetTests.cs new file mode 100644 index 0000000..47c3f77 --- /dev/null +++ b/Chatbase.Tests/EventSetTests.cs @@ -0,0 +1,28 @@ +using Xunit; + +namespace Chatbase.UnitTests +{ + public class ChatbaseEventSetUnitTests + { + public ChatbaseEventSetUnitTests() { } + + [Theory] + [InlineData("api-key")] + public void KeyToConstructorPropagatesToInstance(string apiKey) + { + var eventSet = new EventSet(apiKey); + Assert.Equal(apiKey, eventSet.ApiKey); + } + + [Theory] + [InlineData("api-key")] + public void EventsMadeFromSetContainKeyGivenToConstructor(string apiKey) + { + var set = new EventSet(apiKey); + var @event = set.NewEvent(); + Assert.Equal(apiKey, @event.ApiKey); + set.Add(@event); + Assert.Equal(1, set.GetEvents().Count); + } + } +} diff --git a/Chatbase.Tests/EventTests.cs b/Chatbase.Tests/EventTests.cs new file mode 100644 index 0000000..8e9e249 --- /dev/null +++ b/Chatbase.Tests/EventTests.cs @@ -0,0 +1,56 @@ +using Xunit; + +namespace Chatbase.UnitTests +{ + public class ChatbaseEventUnitTests + { + private readonly Event _event; + + public ChatbaseEventUnitTests() + { + _event = new Event(); + } + + [Fact] + public void DefaultIntent() + { + Assert.Equal("unknown", _event.Intent); + } + + [Fact] + public void DefaultsDoNotCoverAllRequiredFields() + { + Assert.False(_event.RequiredFields()); + } + + [Theory] + [InlineData("stub-api-key")] + public void GivingKeyToConstructorSetsOnInstance(string apiKey) + { + var @event = new Event(apiKey); + Assert.Equal(@event.ApiKey, apiKey); + } + + [Theory] + [InlineData("stub-api-key", "stub-user-id", "stub-intent")] + public void SettingRequiredPassesValidation(string key, string uid, string intent) + { + var @event = new Event + { + ApiKey = key, + UserId = uid, + Intent = intent, + }; + + Assert.True(@event.RequiredFields()); + } + + [Theory] + [InlineData("stub-api-key")] + public void GivingKeyToEventConstructor(string apikey) + { + var @event = new Chatbase.Event(apikey); + Assert.Equal(@event.ApiKey, apikey); + } + } +} diff --git a/Chatbase/Client.cs b/Chatbase/Client.cs index e8c9b18..9c20afc 100644 --- a/Chatbase/Client.cs +++ b/Chatbase/Client.cs @@ -30,7 +30,7 @@ public class Client public string version; private static String ContentType - { + { get { return "application/json"; } } private static String SingluarMessageEndpoint @@ -53,10 +53,18 @@ private static String SingularFBAgentMessageEndpoint { get { return "https://chatbase.com/api/facebook/send_message?api_key={0}&version={1}"; } } - private static String BatchFBAgentMessageEndpoint + private static String BatchFBAgentMessageEndpoint { get { return "https://chatbase.com/api/facebook/send_message_batch?api_key={0}"; } } + private static String SingluarEventEndpoint + { + get { return "https://api.chatbase.com/apis/v1/events/insert"; } + } + private static String BatchEventEndpoint + { + get { return "https://api.chatbase.com/apis/v1/events/insert_batch"; } + } public async Task Send(Message msg) { @@ -71,6 +79,33 @@ public async Task Send(Message msg) return await client.PostAsync(Client.SingluarMessageEndpoint, content); } + public Task Send(Event @event) + { + var stream = new MemoryStream(); + var serializer = new DataContractJsonSerializer( + typeof(Event)); + serializer.WriteObject(stream, @event); + stream.Position = 0; + var streamReader = new StreamReader(stream); + string json = streamReader.ReadToEnd(); + var stringContent = new StringContent(json, Encoding.UTF8, Client.ContentType); + return client.PostAsync(SingluarEventEndpoint, stringContent); + } + + public Task Send(EventSet eventSet) + { + var stream = new MemoryStream(); + var serializer = new DataContractJsonSerializer( + typeof(MessageSet), + new Type[] { typeof(EventCollection), typeof(Event) }); + serializer.WriteObject(stream, eventSet); + stream.Position = 0; + var streamReader = new StreamReader(stream); + string json = streamReader.ReadToEnd(); + var stringContent = new StringContent(json, Encoding.UTF8, Client.ContentType); + return client.PostAsync(BatchEventEndpoint, stringContent); + } + public async Task Send(FBUserMessage msg) { MemoryStream stream = new MemoryStream(); @@ -125,7 +160,7 @@ public async Task Send(MessageSet set) MemoryStream stream = new MemoryStream(); DataContractJsonSerializer ser = new DataContractJsonSerializer( typeof(MessageSet), - new Type[]{typeof(MessageCollection), typeof(Message)}); + new Type[] { typeof(MessageCollection), typeof(Message) }); ser.WriteObject(stream, set); stream.Position = 0; StreamReader sr = new StreamReader(stream); @@ -189,19 +224,23 @@ public async Task Send(FBAgentMessageSet set) private Message setMessageWithClientProperties(Message msg) { - if (!String.IsNullOrEmpty(api_key)) { + if (!String.IsNullOrEmpty(api_key)) + { msg.api_key = api_key; } - if (!String.IsNullOrEmpty(user_id)) { + if (!String.IsNullOrEmpty(user_id)) + { msg.user_id = user_id; } - if (!String.IsNullOrEmpty(platform)) { + if (!String.IsNullOrEmpty(platform)) + { msg.platform = platform; } - if (!String.IsNullOrEmpty(version)) { + if (!String.IsNullOrEmpty(version)) + { msg.version = version; } - + return msg; } diff --git a/Chatbase/Event.cs b/Chatbase/Event.cs new file mode 100644 index 0000000..a443d22 --- /dev/null +++ b/Chatbase/Event.cs @@ -0,0 +1,59 @@ +using System; +using System.Runtime.Serialization; + +namespace Chatbase +{ + [DataContract] + public class Event + { + [DataMember(Name = "api_key")] + public string ApiKey { get; set; } + + [DataMember(Name = "user_id")] + public string UserId { get; set; } + + [DataMember(Name = "intent")] + public string Intent { get; set; } + + [DataMember(Name = "timestamp_millis")] + public double TimestampMillis { get; set; } + + [DataMember(Name = "platform")] + public string Platform { get; set; } + + [DataMember(Name = "version")] + public string Version { get; set; } + + [DataMember(Name = "properties")] + public EventProperty[] Properties { get; set; } + + public static double CurrentUnixMilliseconds() + { + return Math.Truncate(DateTime.UtcNow.Subtract( + new DateTime(1970, 1, 1)).TotalMilliseconds); + } + + public bool RequiredFields() + { + return !( + String.IsNullOrEmpty(ApiKey) + || String.IsNullOrEmpty(UserId) + || String.IsNullOrEmpty(Intent) + ); + } + + public Event() + { + TimestampMillis = CurrentUnixMilliseconds(); + Intent = "unknown"; + } + + public Event(string apiKey) + { + ApiKey = apiKey; + TimestampMillis = CurrentUnixMilliseconds(); + Intent = "unknown"; + } + + } +} diff --git a/Chatbase/EventProperty.cs b/Chatbase/EventProperty.cs new file mode 100644 index 0000000..9553cb1 --- /dev/null +++ b/Chatbase/EventProperty.cs @@ -0,0 +1,24 @@ +using System.Runtime.Serialization; + +namespace Chatbase +{ + [DataContract] + public class EventProperty + { + [DataMember(Name = "property_name")] + public string PropertyName { get; set; } + + [DataMember(Name = "string_value")] + public string StringValue { get; set; } + + [DataMember(Name = "integer_value")] + public int IntegerValue { get; set; } + + [DataMember(Name = "float_value")] + public float FloatValue { get; set; } + + [DataMember(Name = "bool_value")] + public bool BoolValue { get; set; } + + } +} diff --git a/Chatbase/EventSet.cs b/Chatbase/EventSet.cs new file mode 100644 index 0000000..04e09d7 --- /dev/null +++ b/Chatbase/EventSet.cs @@ -0,0 +1,39 @@ +using System.Collections.ObjectModel; +using System.Runtime.Serialization; + +namespace Chatbase +{ + [CollectionDataContract] + public class EventCollection : Collection { } + + [DataContract] + public class EventSet + { + [DataMember(Name = "api_key")] + public string ApiKey { get; set; } + + [DataMember(Name = "events")] + private EventCollection Events; + + public EventSet(string apiKey) + { + ApiKey = apiKey; + Events = new EventCollection(); + } + + public void Add(Event msg) + { + Events.Add(msg); + } + + public EventCollection GetEvents() + { + return Events; + } + + public Event NewEvent() + { + return new Event(ApiKey); + } + } +} From df367911618e6fb286e145e3a1a508def51d7de4 Mon Sep 17 00:00:00 2001 From: "Rafael Pacheco (Take)" Date: Fri, 10 Nov 2017 11:41:44 -0200 Subject: [PATCH 2/3] Add .sln file on gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 69acfcf..6aa78ad 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ bin/ obj/ packages/ *.suo +*.sln .nuget/ TestResults/ *.csproj.user From 5d69c2663bc9a9a77958b000f845a108abb1c116 Mon Sep 17 00:00:00 2001 From: "Rafael Pacheco (Take)" Date: Fri, 10 Nov 2017 14:11:38 -0200 Subject: [PATCH 3/3] Add tests for event requests on client --- Chatbase.Tests/Client.cs | 78 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/Chatbase.Tests/Client.cs b/Chatbase.Tests/Client.cs index 15a4640..30c76f9 100644 --- a/Chatbase.Tests/Client.cs +++ b/Chatbase.Tests/Client.cs @@ -130,7 +130,7 @@ public void SettringClientPropsSetsOnMessageFromParams(string key, string uid, s [Theory] [InlineData("integration-test-user", "integration-test-platform", "0")] - public void SendingWithAPIKeyReturnsError(string uid, string plt, string ver) + public void SendingWithoutAPIKeyReturnsError(string uid, string plt, string ver) { Chatbase.Message msg = new Chatbase.Message(); msg.user_id = uid; @@ -158,6 +158,82 @@ public void SendingValidMessageReturnsSuccess(string uid, string plt, string ver } } + [Theory] + [InlineData("integration-test-user", "integration-test-platform", "string-value", 1, 2.5f, true)] + public void SendingValidEventReturnsSuccess(string uid, string plt, string stringValue, int integerValue, float floatValue, bool booleanValue) + { + string key = Environment.GetEnvironmentVariable("CB_TEST_API_KEY"); + if (String.IsNullOrEmpty(key)) + { + ChatbaseClientUnitTests.PrintNoAPIKeyWarning(); + } + else + { + var @event = new Event + { + ApiKey = key, + UserId = uid, + Platform = plt, + Properties = new EventProperty[] + { + new EventProperty + { + PropertyName = nameof(stringValue), + StringValue = stringValue + }, + new EventProperty + { + PropertyName = nameof(integerValue), + IntegerValue = integerValue + }, + new EventProperty + { + PropertyName = nameof(floatValue), + FloatValue = floatValue + }, + new EventProperty + { + PropertyName = nameof(booleanValue), + BoolValue = booleanValue + } + } + }; + + var resp = _client.Send(@event).Result; + Assert.Equal(resp.StatusCode, HttpStatusCode.OK); + } + } + + [Theory] + [InlineData("integration-test-platform", "string-value")] + public void SendingInvalidEventShouldFalid(string plt, string stringValue) + { + string key = Environment.GetEnvironmentVariable("CB_TEST_API_KEY"); + if (String.IsNullOrEmpty(key)) + { + ChatbaseClientUnitTests.PrintNoAPIKeyWarning(); + } + else + { + var @event = new Event + { + Platform = plt, + Properties = new EventProperty[] + { + new EventProperty + { + PropertyName = nameof(stringValue), + StringValue = stringValue + } + } + }; + + var resp = _client.Send(@event).Result; + Assert.Equal(resp.StatusCode, HttpStatusCode.BadRequest); + } + } + + [Theory] [InlineData("integration-test-user", "integration-test-platform", "0")] public void SendingFromClientReturnsSuccess(string uid, string plt, string ver)