public async Task ValidEventTrackShouldSucceed()
        {
            // Arrange
            var category = "categoryX";
            var action   = "actionA";
            var identity = Identity.Parse("*****@*****.**");
            var extras   = new Dictionary <string, string>()
            {
                { "key1", "value1" }
            };

            Context.UserIdentity.Returns(identity);
            var eventTrackAction = new TrackEventAction(EventTrackExtension);
            var settings         = new JObject
            {
                ["category"] = category,
                ["action"]   = action,
                ["extras"]   = JObject.FromObject(extras)
            };

            // Act
            await eventTrackAction.ExecuteAsync(Context, settings, CancellationToken);

            // Assert
            await EventTrackExtension.Received(1).AddAsync(
                category,
                action,
                label: null,
                value: null,
                messageId: null,
                extras: Arg.Is <Dictionary <string, string> >(d => extras.Keys.All(k => d.ContainsKey(k) && d[k] == extras[k])),
                contactIdentity: identity,
                fireAndForget: true,
                cancellationToken: CancellationToken);
        }
        public async Task ValidEventTrackWithAllFieldsShouldSucceed()
        {
            // Arrange
            var category  = "categoryX";
            var action    = "actionA";
            var label     = "labelll";
            var value     = 45.78M;
            var identity  = Identity.Parse("*****@*****.**");
            var messageId = EnvelopeId.NewId();
            var extras    = new Dictionary <string, string>()
            {
                { "key1", "value1" }
            };

            Context.UserIdentity.Returns(identity);
            EnvelopeReceiverContext <Message> .Create(new Message { Id = messageId });

            var eventTrackAction = new TrackEventAction(EventTrackExtension);
            var settings         = new JObject
            {
                ["category"] = category,
                ["action"]   = action,
                ["label"]    = label,
                ["value"]    = value,
                ["extras"]   = JObject.FromObject(extras)
            };

            // Act
            await eventTrackAction.ExecuteAsync(Context, settings, CancellationToken);

            // Assert
            await EventTrackExtension.Received(1).AddAsync(
                category,
                action,
                label: label,
                value: value,
                messageId: messageId,
                extras: Arg.Is <Dictionary <string, string> >(d => extras.Keys.All(k => d.ContainsKey(k) && d[k] == extras[k])),
                cancellationToken: CancellationToken,
                contactIdentity: identity,
                fireAndForget: true);
        }
        public async Task EventTrackWithoutCategoryShouldFail()
        {
            // Arrange
            string category = null;
            var    action   = "actionA";
            var    identity = "*****@*****.**";
            var    extras   = new Dictionary <string, string>()
            {
                { "key1", "value1" }
            };


            var eventTrackAction = new TrackEventAction(EventTrackExtension);
            var settings         = new JObject
            {
                ["category"] = category,
                ["action"]   = action,
                ["identity"] = identity,
                ["extras"]   = JObject.FromObject(extras)
            };


            // Act
            try
            {
                await eventTrackAction.ExecuteAsync(Context, settings, CancellationToken);

                throw new Exception("The expected exception was not thrown");
            }
            catch (ArgumentException ex)
            {
                // Assert
                ex.Message.ShouldBe("The 'Category' settings value is required for 'TrackEventAction' action");

                await EventTrackExtension.DidNotReceive().AddAsync(
                    category,
                    action,
                    Arg.Is <Dictionary <string, string> >(d => extras.Keys.All(k => d.ContainsKey(k) && d[k] == extras[k])),
                    CancellationToken,
                    identity);
            }
        }