diff --git a/Analytics-CSharp/Analytics-CSharp.csproj b/Analytics-CSharp/Analytics-CSharp.csproj index 0b02328..fbfd69d 100644 --- a/Analytics-CSharp/Analytics-CSharp.csproj +++ b/Analytics-CSharp/Analytics-CSharp.csproj @@ -10,7 +10,7 @@ Segment, Inc The hassle-free way to add analytics to your C# app. - 2.4.0 + 2.4.2 MIT https://github.com/segmentio/Analytics-CSharp git @@ -39,7 +39,7 @@ - + diff --git a/Analytics-CSharp/Segment/Analytics/Compat/Migration.cs b/Analytics-CSharp/Segment/Analytics/Compat/Migration.cs index e629abf..b925764 100644 --- a/Analytics-CSharp/Segment/Analytics/Compat/Migration.cs +++ b/Analytics-CSharp/Segment/Analytics/Compat/Migration.cs @@ -1,9 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Net.Http.Headers; -using System.Reflection; -using Segment.Analytics; using Segment.Serialization; namespace Segment.Analytics.Compat @@ -31,9 +27,13 @@ public static void Track(this Analytics analytics, string userId, string eventNa public static void Track(this Analytics analytics, string userId, string eventName, Dictionary properties) { + if (properties == null) + { + properties = new Dictionary(); + } properties.Add("userId", userId); analytics.Track(eventName, - JsonUtility.FromJson(JsonUtility.ToJson(properties))); + JsonUtility.FromJson(JsonUtility.ToJson(properties))); } [Obsolete("This should only be used if migrating from Analytics.NET or Analytics.Xamarin")] @@ -43,36 +43,48 @@ public static void Screen(this Analytics analytics, string userId, string eventN } [Obsolete("This should only be used if migrating from Analytics.NET or Analytics.Xamarin")] - public static void Screen(this Analytics analytics, string userId, string eventName, + public static void Screen(this Analytics analytics, string userId, string title, Dictionary properties) { + if (properties == null) + { + properties = new Dictionary(); + } properties.Add("userId", userId); - analytics.Screen(eventName, - JsonUtility.FromJson(JsonUtility.ToJson(properties))); + analytics.Screen(title, + JsonUtility.FromJson(JsonUtility.ToJson(properties))); } [Obsolete("This should only be used if migrating from Analytics.NET or Analytics.Xamarin")] - public static void Page(this Analytics analytics, string userId, string eventName) + public static void Page(this Analytics analytics, string userId, string title) { - analytics.Page(eventName, new JsonObject() {{"userId", userId}}); + analytics.Page(title, new JsonObject() {{"userId", userId}}); } [Obsolete("This should only be used if migrating from Analytics.NET or Analytics.Xamarin")] - public static void Page(this Analytics analytics, string userId, string eventName, + public static void Page(this Analytics analytics, string userId, string title, Dictionary properties) { + if (properties == null) + { + properties = new Dictionary(); + } properties.Add("userId", userId); - analytics.Page(eventName, - JsonUtility.FromJson(JsonUtility.ToJson(properties))); + analytics.Page(title, + JsonUtility.FromJson(JsonUtility.ToJson(properties))); } [Obsolete("This should only be used if migrating from Analytics.NET or Analytics.Xamarin")] public static void Group(this Analytics analytics, string userId, string groupId, Dictionary traits) { + if (traits == null) + { + traits = new Dictionary(); + } traits.Add("userId", userId); analytics.Group(groupId, - JsonUtility.FromJson(JsonUtility.ToJson(traits))); + JsonUtility.FromJson(JsonUtility.ToJson(traits))); } [Obsolete("This should only be used if migrating from Analytics.NET or Analytics.Xamarin")] diff --git a/Analytics-CSharp/Segment/Analytics/Version.cs b/Analytics-CSharp/Segment/Analytics/Version.cs index aa1261f..228d1b5 100644 --- a/Analytics-CSharp/Segment/Analytics/Version.cs +++ b/Analytics-CSharp/Segment/Analytics/Version.cs @@ -2,6 +2,6 @@ namespace Segment.Analytics { internal static class Version { - internal const string SegmentVersion = "2.4.0"; + internal const string SegmentVersion = "2.4.2"; } } diff --git a/Tests/Compat/MigrationTest.cs b/Tests/Compat/MigrationTest.cs new file mode 100644 index 0000000..b8891ba --- /dev/null +++ b/Tests/Compat/MigrationTest.cs @@ -0,0 +1,182 @@ +using System.Collections.Generic; +using Moq; +using Segment.Analytics; +using Segment.Analytics.Utilities; +using Segment.Analytics.Compat; +using Segment.Serialization; +using Tests.Utils; +using Xunit; + +namespace Tests.Compat +{ + public class MigrationTest + { + private readonly Analytics _analytics; + + private Settings? _settings; + + private readonly Mock _plugin; + + public MigrationTest() + { + _settings = JsonUtility.FromJson( + "{\"integrations\":{\"Segment.io\":{\"apiKey\":\"1vNgUqwJeCHmqgI9S1sOm9UHCyfYqbaQ\"}},\"plan\":{},\"edgeFunction\":{}}"); + + var mockHttpClient = new Mock(null, null, null); + mockHttpClient + .Setup(httpClient => httpClient.Settings()) + .ReturnsAsync(_settings); + + _plugin = new Mock + { + CallBase = true + }; + + var config = new Configuration( + writeKey: "123", + storageProvider: new DefaultStorageProvider("tests"), + autoAddSegmentDestination: false, + useSynchronizeDispatcher: true, + httpClientProvider: new MockHttpClientProvider(mockHttpClient) + ); + _analytics = new Analytics(config); + _analytics.Add(new UserIdPlugin()); + } + + [Fact] + public void TestCompatTrackAcceptNullDict() + { + var actual = new List(); + _plugin.Setup(o => o.Track(Capture.In(actual))); + _analytics.Add(_plugin.Object); + _analytics.Track("user123", "foo", null); + + Assert.NotEmpty(actual); + Assert.False(actual[0].Properties.ContainsKey("userId")); + Assert.Equal("user123", actual[0].UserId); + Assert.Equal("foo", actual[0].Event); + } + + [Fact] + public void TestCompatTrackAcceptDictWithNulls() + { + var properties = new Dictionary + { + ["nullValue"] = null + }; + var actual = new List(); + _plugin.Setup(o => o.Track(Capture.In(actual))); + _analytics.Add(_plugin.Object); + _analytics.Track("user123", "foo", properties); + + Assert.NotEmpty(actual); + Assert.False(actual[0].Properties.ContainsKey("userId")); + Assert.Equal("user123", actual[0].UserId); + Assert.Equal("foo", actual[0].Event); + Assert.True(actual[0].Properties.ContainsKey("nullValue")); + Assert.Equal(JsonNull.Instance, actual[0].Properties["nullValue"]); + } + + [Fact] + public void TestCompatScreenAcceptNullDict() + { + var actual = new List(); + _plugin.Setup(o => o.Screen(Capture.In(actual))); + _analytics.Add(_plugin.Object); + _analytics.Screen("user123", "foo", null); + + Assert.NotEmpty(actual); + Assert.False(actual[0].Properties.ContainsKey("userId")); + Assert.Equal("user123", actual[0].UserId); + Assert.Equal("foo", actual[0].Name); + } + + [Fact] + public void TestCompatScreenAcceptDictWithNulls() + { + var properties = new Dictionary + { + ["nullValue"] = null + }; + var actual = new List(); + _plugin.Setup(o => o.Screen(Capture.In(actual))); + _analytics.Add(_plugin.Object); + _analytics.Screen("user123", "foo", properties); + + Assert.NotEmpty(actual); + Assert.False(actual[0].Properties.ContainsKey("userId")); + Assert.Equal("user123", actual[0].UserId); + Assert.Equal("foo", actual[0].Name); + Assert.True(actual[0].Properties.ContainsKey("nullValue")); + Assert.Equal(JsonNull.Instance, actual[0].Properties["nullValue"]); + } + + [Fact] + public void TestCompatPageAcceptNullDict() + { + var actual = new List(); + _plugin.Setup(o => o.Page(Capture.In(actual))); + _analytics.Add(_plugin.Object); + _analytics.Page("user123", "foo", null); + + Assert.NotEmpty(actual); + Assert.False(actual[0].Properties.ContainsKey("userId")); + Assert.Equal("user123", actual[0].UserId); + Assert.Equal("foo", actual[0].Name); + } + + [Fact] + public void TestCompatPageAcceptDictWithNulls() + { + var properties = new Dictionary + { + ["nullValue"] = null + }; + var actual = new List(); + _plugin.Setup(o => o.Page(Capture.In(actual))); + _analytics.Add(_plugin.Object); + _analytics.Page("user123", "foo", properties); + + Assert.NotEmpty(actual); + Assert.False(actual[0].Properties.ContainsKey("userId")); + Assert.Equal("user123", actual[0].UserId); + Assert.Equal("foo", actual[0].Name); + Assert.True(actual[0].Properties.ContainsKey("nullValue")); + Assert.Equal(JsonNull.Instance, actual[0].Properties["nullValue"]); + } + + [Fact] + public void TestCompatGroupAcceptNullDict() + { + var actual = new List(); + _plugin.Setup(o => o.Group(Capture.In(actual))); + _analytics.Add(_plugin.Object); + _analytics.Group("user123", "foo", null); + + Assert.NotEmpty(actual); + Assert.False(actual[0].Traits.ContainsKey("userId")); + Assert.Equal("user123", actual[0].UserId); + Assert.Equal("foo", actual[0].GroupId); + } + + [Fact] + public void TestCompatGroupAcceptDictWithNulls() + { + var properties = new Dictionary + { + ["nullValue"] = null + }; + var actual = new List(); + _plugin.Setup(o => o.Group(Capture.In(actual))); + _analytics.Add(_plugin.Object); + _analytics.Group("user123", "foo", properties); + + Assert.NotEmpty(actual); + Assert.False(actual[0].Traits.ContainsKey("userId")); + Assert.Equal("user123", actual[0].UserId); + Assert.Equal("foo", actual[0].GroupId); + Assert.True(actual[0].Traits.ContainsKey("nullValue")); + Assert.Equal(JsonNull.Instance, actual[0].Traits["nullValue"]); + } + } +} diff --git a/Tests/Utils/Stubs.cs b/Tests/Utils/Stubs.cs index adfb003..ee32a6d 100644 --- a/Tests/Utils/Stubs.cs +++ b/Tests/Utils/Stubs.cs @@ -45,6 +45,11 @@ public class StubEventPlugin : EventPlugin public override PluginType Type => PluginType.Before; } + public class StubAfterEventPlugin : EventPlugin + { + public override PluginType Type => PluginType.After; + } + public class StubDestinationPlugin : DestinationPlugin { public override string Key { get; }