Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/Packages/Audience/Runtime/Events/MessageBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;

namespace Immutable.Audience
{
internal static class MessageBuilder
{
internal static Dictionary<string, object> Track(
string eventName,
string anonymousId,
string userId,
string packageVersion,
Dictionary<string, object> properties = null)
{
var msg = BuildBase("track", packageVersion);
msg["eventName"] = Truncate(eventName, 256);

if (!string.IsNullOrEmpty(anonymousId))
msg["anonymousId"] = Truncate(anonymousId, 256);

if (!string.IsNullOrEmpty(userId))
msg["userId"] = Truncate(userId, 256);

if (properties != null && properties.Count > 0)
msg["properties"] = properties;

return msg;
}

internal static Dictionary<string, object> Identify(
string anonymousId,
string userId,
string identityType,
string packageVersion,
Dictionary<string, object> traits = null)
{
var msg = BuildBase("identify", packageVersion);

if (!string.IsNullOrEmpty(anonymousId))
msg["anonymousId"] = Truncate(anonymousId, 256);

if (!string.IsNullOrEmpty(userId))
msg["userId"] = Truncate(userId, 256);

if (!string.IsNullOrEmpty(identityType))
msg["identityType"] = Truncate(identityType, 256);

if (traits != null && traits.Count > 0)
msg["traits"] = traits;

return msg;
}

internal static Dictionary<string, object> Alias(
string fromId,
string fromType,
string toId,
string toType,
string packageVersion)
{
var msg = BuildBase("alias", packageVersion);
msg["fromId"] = Truncate(fromId, 256);
msg["fromType"] = Truncate(fromType, 256);
msg["toId"] = Truncate(toId, 256);
msg["toType"] = Truncate(toType, 256);
return msg;
}

private static Dictionary<string, object> BuildBase(string type, string packageVersion)
{
return new Dictionary<string, object>
{
["type"] = type,
["messageId"] = Guid.NewGuid().ToString(),
["eventTimestamp"] = DateTime.UtcNow.ToString("o"),
["context"] = new Dictionary<string, object>
{
["library"] = Constants.LibraryName,
["libraryVersion"] = Truncate(packageVersion, 256)
},
["surface"] = Constants.Surface
};
}

private static string Truncate(string s, int maxLen)
{
if (s == null || s.Length <= maxLen)
return s;
return s.Substring(0, maxLen);
}
}
}
101 changes: 101 additions & 0 deletions src/Packages/Audience/Tests/Runtime/MessageBuilderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System.Collections.Generic;
using NUnit.Framework;

namespace Immutable.Audience.Tests
{
[TestFixture]
public class MessageBuilderTests
{
private const string PackageVersion = "1.2.3";

[Test]
public void Track_RequiredFieldsPresent()
{
var result = MessageBuilder.Track("level_complete", "anon-1", null, PackageVersion);

Assert.AreEqual("track", result["type"]);
Assert.IsTrue(result.ContainsKey("messageId"));
Assert.IsTrue(result.ContainsKey("eventTimestamp"));
Assert.IsTrue(result.ContainsKey("context"));
Assert.IsTrue(result.ContainsKey("surface"));
Assert.AreEqual("level_complete", result["eventName"]);
}

[Test]
public void Track_EventNameLongerThan256Chars_TruncatedTo256()
{
var longName = new string('x', 300);

var result = MessageBuilder.Track(longName, null, null, PackageVersion);

Assert.AreEqual(256, ((string)result["eventName"]).Length);
}

[Test]
public void Track_NullUserId_NotPresentInDict()
{
var result = MessageBuilder.Track("evt", "anon-1", null, PackageVersion);

Assert.IsFalse(result.ContainsKey("userId"));
}

[Test]
public void Track_NonNullUserId_PresentInDict()
{
var result = MessageBuilder.Track("evt", "anon-1", "user-99", PackageVersion);

Assert.IsTrue(result.ContainsKey("userId"));
Assert.AreEqual("user-99", result["userId"]);
}

[Test]
public void Identify_TypeAndIdentityFieldsPresent()
{
var result = MessageBuilder.Identify("anon-42", "user-42", "steam", PackageVersion);

Assert.AreEqual("identify", result["type"]);
Assert.AreEqual("anon-42", result["anonymousId"]);
Assert.AreEqual("user-42", result["userId"]);
Assert.AreEqual("steam", result["identityType"]);
}

[Test]
public void Alias_AllFourFieldsPresent()
{
var result = MessageBuilder.Alias("from-id", "email", "to-id", "steam", PackageVersion);

Assert.AreEqual("alias", result["type"]);
Assert.AreEqual("from-id", result["fromId"]);
Assert.AreEqual("email", result["fromType"]);
Assert.AreEqual("to-id", result["toId"]);
Assert.AreEqual("steam", result["toType"]);
}

[Test]
public void AllMessages_ContextContainsLibraryAndLibraryVersion()
{
var track = MessageBuilder.Track("evt", null, null, PackageVersion);
var identify = MessageBuilder.Identify(null, "u1", null, PackageVersion);
var alias = MessageBuilder.Alias("f", "t1", "t", "t2", PackageVersion);

foreach (var msg in new[] { track, identify, alias })
{
var ctx = (Dictionary<string, object>)msg["context"];
Assert.AreEqual(Constants.LibraryName, ctx["library"]);
Assert.AreEqual(PackageVersion, ctx["libraryVersion"]);
}
}

[Test]
public void AllMessages_SurfaceIsUnity()
{
var track = MessageBuilder.Track("evt", null, null, PackageVersion);
var identify = MessageBuilder.Identify(null, "u1", null, PackageVersion);
var alias = MessageBuilder.Alias("f", "t1", "t", "t2", PackageVersion);

Assert.AreEqual("unity", track["surface"]);
Assert.AreEqual("unity", identify["surface"]);
Assert.AreEqual("unity", alias["surface"]);
}
}
}
Loading