public void GetDatasetResults_Success()
        {
            var timeframe = QueryRelativeTimeframe.ThisNMinutes(12);
            var result    = new JObject();
            var client    = new KeenClient(SettingsEnv);

            Mock <IDataset> datasetMock = null;

            if (UseMocks)
            {
                datasetMock = new Mock <IDataset>();
                datasetMock.Setup(m => m.GetResultsAsync(
                                      It.Is <string>(n => n == _datasetName),
                                      It.Is <string>(i => i == _indexBy),
                                      It.Is <string>(t => t == timeframe.ToString())))
                .ReturnsAsync(result);

                client.Datasets = datasetMock.Object;
            }

            var dataset = client.QueryDataset(_datasetName, _indexBy, timeframe.ToString());

            Assert.IsNotNull(dataset);

            datasetMock?.VerifyAll();
        }
Beispiel #2
0
        public async Task DefaultHeaders_Success()
        {
            object responseData = new[] { new { result = 2 } };

            var handler = new FuncHandler()
            {
                PreProcess = (req, ct) =>
                {
                    // Make sure the default headers are in place
                    Assert.IsTrue(req.Headers.Contains("Keen-Sdk"));
                    Assert.AreEqual(KeenUtil.GetSdkVersion(), req.Headers.GetValues("Keen-Sdk").Single());

                    Assert.IsTrue(req.Headers.Contains("Authorization"));

                    var key = req.Headers.GetValues("Authorization").Single();
                    Assert.IsTrue(SettingsEnv.ReadKey == key ||
                                  SettingsEnv.WriteKey == key ||
                                  SettingsEnv.MasterKey == key);
                },
                ProduceResultAsync = (req, ct) =>
                {
                    return(CreateJsonStringResponseAsync(responseData));
                },
                DeferToDefault = false
            };

            var client = new KeenClient(SettingsEnv, new TestKeenHttpClientProvider()
            {
                ProvideKeenHttpClient =
                    (url) => KeenHttpClientFactory.Create(url,
                                                          new HttpClientCache(),
                                                          null,
                                                          new DelegatingHandlerMock(handler))
            });

            // Try out all the endpoints
            Assert.DoesNotThrow(() => client.GetSchemas());

            // Remaining operations expect an object, not an array of objects
            responseData = new { result = 2 };

            var @event = new { AProperty = "AValue" };

            Assert.DoesNotThrow(() => client.AddEvent("AddEventTest", @event));
            Assert.DoesNotThrow(() => client.AddEvents("AddEventTest", new[] { @event }));

            Assert.DoesNotThrow(() => client.DeleteCollection("DeleteColTest"));
            Assert.IsNotNull(client.GetSchema("AddEventTest"));

            // Currently all the queries/extraction go through the same KeenWebApiRequest() call.
            var count = await client.QueryAsync(
                QueryType.Count(),
                "testCollection",
                "",
                QueryRelativeTimeframe.ThisMonth());

            Assert.IsNotNull(count);
            Assert.AreEqual("2", count);
        }
Beispiel #3
0
        public async Task QueryFilter_NotContains_Success()
        {
            var queriesUrl = HttpTests.GetUriForResource(SettingsEnv,
                                                         KeenConstants.QueriesResource);

            var handler = new FuncHandler()
            {
                PreProcess = (req, ct) =>
                {
                    var queryStr = req.RequestUri.Query;

                    // Make sure our filter properties are in the query string
                    Assert.IsTrue(queryStr.Contains("propertyName") &&
                                  queryStr.Contains("four") &&
                                  queryStr.Contains(QueryFilter.FilterOperator.NotContains()));
                },
                ProduceResultAsync = (req, ct) =>
                {
                    return(HttpTests.CreateJsonStringResponseAsync(new { result = 2 }));
                },
                DeferToDefault = false
            };

            // NOTE : This example shows use of UrlToMessageHandler, but since we only make one
            // request to a single endpoint, we could just directly use the FuncHandler here.
            var urlHandler = new UrlToMessageHandler(
                new Dictionary <Uri, IHttpMessageHandler>
            {
                { queriesUrl, handler }
            })
            {
                DeferToDefault = false
            };

            var client = new KeenClient(SettingsEnv, new TestKeenHttpClientProvider()
            {
                ProvideKeenHttpClient =
                    (url) => KeenHttpClientFactory.Create(url,
                                                          new HttpClientCache(),
                                                          null,
                                                          new DelegatingHandlerMock(urlHandler))
            });

            var filters = new List <QueryFilter>
            {
                new QueryFilter("propertyName", QueryFilter.FilterOperator.NotContains(), "four")
            };

            var count = await client.QueryAsync(
                QueryType.Count(),
                "testCollection",
                "",
                QueryRelativeTimeframe.ThisMonth(),
                filters);

            Assert.IsNotNull(count);
            Assert.AreEqual("2", count);
        }
        public void Test_TimeframeConverter_Serializes()
        {
            var timeframeString = "this_4_hours";
            var timeframe       = QueryRelativeTimeframe.Create(timeframeString);

            string json = JsonConvert.SerializeObject(timeframe);

            Assert.AreEqual($"\"{timeframeString}\"", json);
        }
Beispiel #5
0
        public async Task Query_SimpleExtraction_Success()
        {
            var queryParameters = new ExtractionParameters()
            {
                Timeframe = QueryRelativeTimeframe.ThisNHours(2),
            };

            string resultsJson = @"[
                {
                    ""keen"": {
                        ""created_at"": ""2012-07-30T21:21:46.566000+00:00"",
                        ""timestamp"": ""2012-07-30T21:21:46.566000+00:00"",
                        ""id"": """"
                    },
                    ""user"": {
                        ""email"": ""*****@*****.**"",
                        ""id"": ""4f4db6c7777d66ffff000000""
                    },
                    ""user_agent"": {
                        ""browser"": ""chrome"",
                        ""browser_version"": ""20.0.1132.57"",
                        ""platform"": ""macos""
                    }
                },
                {
                    ""keen"": {
                        ""created_at"": ""2012-07-30T21:40:05.386000+00:00"",
                        ""timestamp"": ""2012-07-30T21:40:05.386000+00:00"",
                        ""id"": """"
                    },
                    ""user"": {
                        ""email"": ""*****@*****.**"",
                        ""id"": ""4fa2cccccf546ffff000006""
                    },
                    ""user_agent"": {
                        ""browser"": ""chrome"",
                        ""browser_version"": ""20.0.1132.57"",
                        ""platform"": ""macos""
                    }
                }
            ]";

            var expectedResults = JArray.Parse(resultsJson);

            var expectedResponse = new
            {
                result = expectedResults
            };

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResults = await client.Queries.Extract(
                queryParameters.EventCollection,
                queryParameters.Timeframe);

            Assert.That(actualResults, Is.EquivalentTo(expectedResults));
        }
        public async Task Query_SimpleSelectUniqueInterval_Success()
        {
            var queryParameters = new QueryParameters()
            {
                Analysis       = QueryType.SelectUnique(),
                TargetProperty = "someProperty",
                Timeframe      = QueryRelativeTimeframe.ThisNHours(2),
                Interval       = QueryInterval.EveryNHours(1)
            };

            var expectedCounts = new List <string[]>()
            {
                new string[] { "10", "20" }, new string[] { "30", "40" }
            };
            var expectedTimeframes = new List <QueryAbsoluteTimeframe>()
            {
                new QueryAbsoluteTimeframe(DateTime.Now.AddHours(-2), DateTime.Now.AddHours(-1)),
                new QueryAbsoluteTimeframe(DateTime.Now.AddHours(-1), DateTime.Now)
            };
            var expectedResults = expectedCounts.Zip(
                expectedTimeframes,
                (count, time) => new { timeframe = time, value = count });

            var expectedResponse = new
            {
                result = expectedResults
            };

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResults = await client.Queries.Metric(
                queryParameters.Analysis,
                queryParameters.EventCollection,
                queryParameters.TargetProperty,
                queryParameters.Timeframe,
                queryParameters.Interval);

            Assert.AreEqual(expectedResults.Count(), actualResults.Count());
            var expectedEnumerator = expectedResults.GetEnumerator();
            var actualEnumerator   = actualResults.GetEnumerator();

            while (expectedEnumerator.MoveNext() && actualEnumerator.MoveNext())
            {
                var expected = expectedEnumerator.Current;
                var actual   = actualEnumerator.Current;
                Assert.AreEqual(expected.timeframe.Start, actual.Start);
                Assert.AreEqual(expected.timeframe.End, actual.End);
                Assert.AreEqual(string.Join(",", expected.value), actual.Value);
            }
        }
Beispiel #7
0
        public async Task QueryFilter_NullPropertyValue_Success()
        {
            // TODO : Consolidate this FuncHandler/KeenClient setup into a helper method.

            var handler = new FuncHandler()
            {
                PreProcess = (req, ct) =>
                {
                    var queryStr = req.RequestUri.Query;

                    // Make sure our filter properties are in the query string
                    Assert.IsTrue(queryStr.Contains("propertyName") &&
                                  queryStr.Contains("null") &&
                                  queryStr.Contains(QueryFilter.FilterOperator.Equals()));
                },
                ProduceResultAsync = (req, ct) =>
                {
                    return(HttpTests.CreateJsonStringResponseAsync(new { result = 2 }));
                },
                DeferToDefault = false
            };

            var client = new KeenClient(SettingsEnv, new TestKeenHttpClientProvider()
            {
                ProvideKeenHttpClient =
                    (url) => KeenHttpClientFactory.Create(url,
                                                          new HttpClientCache(),
                                                          null,
                                                          new DelegatingHandlerMock(handler))
            });

            var filters = new List <QueryFilter>
            {
                new QueryFilter("propertyName", QueryFilter.FilterOperator.Equals(), null)
            };

            var count = await client.QueryAsync(
                QueryType.Count(),
                "testCollection",
                "",
                QueryRelativeTimeframe.ThisMonth(),
                filters);

            Assert.IsNotNull(count);
            Assert.AreEqual("2", count);
        }
Beispiel #8
0
        public async Task Query_SimpleSelectUniqueInterval_Success()
        {
            var queryParameters = new QueryParameters()
            {
                Analysis       = QueryType.SelectUnique(),
                TargetProperty = "someProperty",
                Timeframe      = QueryRelativeTimeframe.ThisNHours(2),
                Interval       = QueryInterval.EveryNHours(1)
            };

            var expectedCounts = new List <string[]>()
            {
                new string[] { "10", "20" }, new string[] { "30", "40" }
            };
            var expectedTimeframes = new List <QueryAbsoluteTimeframe>()
            {
                new QueryAbsoluteTimeframe(DateTime.Now.AddHours(-2), DateTime.Now.AddHours(-1)),
                new QueryAbsoluteTimeframe(DateTime.Now.AddHours(-1), DateTime.Now)
            };
            var expectedResults = expectedCounts.Zip(
                expectedTimeframes,
                (count, time) => new { timeframe = time, value = count });
            var expectedResponse = new
            {
                result = expectedResults
            };

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResult = await client.Queries.Metric(
                queryParameters.Analysis,
                queryParameters.EventCollection,
                queryParameters.TargetProperty,
                queryParameters.Timeframe,
                queryParameters.Interval);

            var expectedSdkResult = expectedResults.Select((result) =>
            {
                return(new QueryIntervalValue <string>(
                           string.Join(',', result.value),
                           result.timeframe.Start,
                           result.timeframe.End));
            });

            Assert.That(actualResult, Is.EquivalentTo(expectedSdkResult));
        }
Beispiel #9
0
        public async Task Query_SimpleFunnel_Success()
        {
            var queryParameters = new FunnelParameters()
            {
                Steps = new FunnelStep[]
                {
                    new FunnelStep()
                    {
                        EventCollection = "signed up", ActorProperty = "visitor.guid", Timeframe = QueryRelativeTimeframe.ThisNDays(7)
                    },
                    new FunnelStep()
                    {
                        EventCollection = "completed profile", ActorProperty = "user.guid", Timeframe = QueryRelativeTimeframe.ThisNDays(7)
                    },
                    new FunnelStep()
                    {
                        EventCollection = "referred user", ActorProperty = "user.guid", Timeframe = QueryRelativeTimeframe.ThisNDays(7)
                    },
                }
            };

            string responseJson = @"{
                ""result"": [
                    3,
                    1,
                    0
                ],
                ""steps"": [
                    {
                        ""actor_property"": ""visitor.guid"",
                        ""event_collection"": ""signed up"",
                        ""timeframe"": ""this_7_days""
                    },
                    {
                        ""actor_property"": ""user.guid"",
                        ""event_collection"": ""completed profile"",
                        ""timeframe"": ""this_7_days""
                    },
                    {
                        ""actor_property"": ""user.guid"",
                        ""event_collection"": ""referred user"",
                        ""timeframe"": ""this_7_days""
                    }
                ]
            }";

            var expectedResponse = JObject.Parse(responseJson);

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResults = await client.Queries.Funnel(
                queryParameters.Steps);

            var expectedResults = expectedResponse["result"].Values <int>();

            Assert.That(actualResults.Result, Is.EquivalentTo(expectedResults));

            var expectedSteps = queryParameters.Steps.Select((step) => new FunnelResultStep()
            {
                EventCollection = step.EventCollection, ActorProperty = step.ActorProperty, Timeframe = step.Timeframe
            });

            Assert.That(actualResults.Steps, Is.EquivalentTo(expectedSteps));
        }
Beispiel #10
0
        public async Task Query_SimpleSelectUniqueGroupByInterval_Success()
        {
            var queryParameters = new QueryParameters()
            {
                Analysis       = QueryType.SelectUnique(),
                TargetProperty = "someProperty",
                Timeframe      = QueryRelativeTimeframe.ThisNHours(2),
                Interval       = QueryInterval.EveryNHours(1),
                GroupBy        = "someGroupProperty"
            };

            string resultsJson = @"[
                {
                    ""timeframe"": {
                        ""start"": ""2017-10-14T00:00:00.000Z"",
                        ""end"": ""2017-10-15T00:00:00.000Z""
                    },
                    ""value"": [
                        {
                            ""someGroupProperty"": ""group1"",
                            ""result"": [
                                ""10"",
                                ""20""
                            ]
                        },
                        {
                            ""someGroupProperty"": ""group2"",
                            ""result"": [
                                ""30"",
                                ""40""
                            ]
                        }
                    ]
                },
                {
                    ""timeframe"": {
                        ""start"": ""2017-10-15T00:00:00.000Z"",
                        ""end"": ""2017-10-16T00:00:00.000Z""
                    },
                    ""value"": [
                        {
                            ""someGroupProperty"": ""group1"",
                            ""result"": [
                                ""50"",
                                ""60""
                            ]
                        },
                        {
                            ""someGroupProperty"": ""group2"",
                            ""result"": [
                                ""70"",
                                ""80""
                            ]
                        }
                    ]
                }
            ]";

            var expectedResults = JArray.Parse(resultsJson);

            var expectedResponse = new
            {
                result = expectedResults
            };

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResult = await client.Queries.Metric(
                queryParameters.Analysis,
                queryParameters.EventCollection,
                queryParameters.TargetProperty,
                queryParameters.GroupBy,
                queryParameters.Timeframe,
                queryParameters.Interval);

            var expectedSdkResult = expectedResults.Select((intervalToken) =>
            {
                return(new QueryIntervalValue <IEnumerable <QueryGroupValue <string> > >(
                           intervalToken["value"].Select((groupToken) =>
                {
                    return new QueryGroupValue <string>(
                        string.Join(',', groupToken["result"]),
                        groupToken[queryParameters.GroupBy].Value <string>());
                }),
                           intervalToken["timeframe"]["start"].Value <DateTime>(),
                           intervalToken["timeframe"]["end"].Value <DateTime>()));
            });

            // Use JArray objects as a way to normalize types here, since the
            // concrete types won't match for the QueryInternalValue IEnumerable implementation.
            Assert.That(JArray.FromObject(actualResult), Is.EquivalentTo(JArray.FromObject(expectedSdkResult)));
        }
Beispiel #11
0
        public async Task Query_SimpleCountGroupByInterval_Success()
        {
            var queryParameters = new QueryParameters()
            {
                TargetProperty = "someProperty",
                Timeframe      = QueryRelativeTimeframe.ThisNHours(2),
                Interval       = QueryInterval.EveryNHours(1),
                GroupBy        = "someGroupProperty"
            };

            var expectedResults = new[]
            {
                new
                {
                    timeframe = new QueryAbsoluteTimeframe(DateTime.Now.AddHours(-2), DateTime.Now.AddHours(-1)),
                    value     = new List <Dictionary <string, string> >
                    {
                        new Dictionary <string, string> {
                            { queryParameters.GroupBy, "group1" }, { "result", "10" }
                        },
                        new Dictionary <string, string> {
                            { queryParameters.GroupBy, "group2" }, { "result", "20" }
                        },
                    }
                },
                new
                {
                    timeframe = new QueryAbsoluteTimeframe(DateTime.Now.AddHours(-1), DateTime.Now),
                    value     = new List <Dictionary <string, string> >
                    {
                        new Dictionary <string, string> {
                            { queryParameters.GroupBy, "group1" }, { "result", "30" }
                        },
                        new Dictionary <string, string> {
                            { queryParameters.GroupBy, "group2" }, { "result", "40" }
                        },
                    }
                }
            };

            var expectedResponse = new
            {
                result = expectedResults
            };

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResult = (await client.Queries.Metric(
                                    queryParameters.Analysis,
                                    queryParameters.EventCollection,
                                    queryParameters.TargetProperty,
                                    queryParameters.GroupBy,
                                    queryParameters.Timeframe,
                                    queryParameters.Interval));

            var expectedSdkResult = expectedResults.Select((intervals) =>
            {
                return(new QueryIntervalValue <IEnumerable <QueryGroupValue <string> > >(
                           intervals.value.Select((group) => new QueryGroupValue <string>(
                                                      group["result"],
                                                      group[queryParameters.GroupBy])),
                           intervals.timeframe.Start,
                           intervals.timeframe.End
                           ));
            });

            // Use JArray objects as a way to normalize types here, since the
            // concrete types won't match for the QueryInternalValue IEnumerable implementation.
            Assert.That(JArray.FromObject(actualResult), Is.EquivalentTo(JArray.FromObject(expectedSdkResult)));
        }
Beispiel #12
0
        public async Task Funnel_Simple_Success()
        {
            var client    = new KeenClient(SettingsEnv);
            var timeframe = QueryRelativeTimeframe.ThisHour();

            IEnumerable <FunnelStep> funnelsteps = new List <FunnelStep>
            {
                new FunnelStep
                {
                    EventCollection = FunnelColA,
                    ActorProperty   = "id",
                },
                new FunnelStep
                {
                    EventCollection = FunnelColB,
                    ActorProperty   = "id"
                },
            };

            var expected = new FunnelResult
            {
                Steps = new[]
                {
                    new FunnelResultStep
                    {
                        EventCollection = FunnelColA,
                    },
                    new FunnelResultStep
                    {
                        EventCollection = FunnelColB,
                    },
                },
                Result = new[] { 3, 2 }
            };

            Mock <IQueries> queryMock = null;

            if (UseMocks)
            {
                queryMock = new Mock <IQueries>();
                queryMock.Setup(m => m.Funnel(
                                    It.Is <IEnumerable <FunnelStep> >(f => f.Equals(funnelsteps)),
                                    It.Is <IQueryTimeframe>(t => t == timeframe),
                                    It.Is <string>(t => t == "")
                                    ))
                .Returns(Task.FromResult(expected));

                client.Queries = queryMock.Object;
            }

            var reply = (await client.QueryFunnelAsync(funnelsteps, timeframe));

            Assert.NotNull(reply);
            Assert.NotNull(reply.Result);
            Assert.NotNull(reply.Steps);
            Assert.AreEqual(reply.Steps.Count(), 2);

            if (null != queryMock)
            {
                queryMock.VerifyAll();
            }
        }
Beispiel #13
0
        public async Task Funnel_ValidTimeframeInSteps_Success()
        {
            var client = new KeenClient(SettingsEnv);

            IEnumerable <FunnelStep> funnelsteps = new[]
            {
                new FunnelStep
                {
                    EventCollection = FunnelColA,
                    ActorProperty   = "id",
                    Timeframe       = QueryRelativeTimeframe.ThisMonth(),
                },
                new FunnelStep
                {
                    EventCollection = FunnelColB,
                    ActorProperty   = "id",
                    Timeframe       = new QueryAbsoluteTimeframe(DateTime.Now.AddDays(-30), DateTime.Now),
                },
            };

            var expected = new FunnelResult
            {
                Steps = new[]
                {
                    new FunnelResultStep
                    {
                        EventCollection = FunnelColA,
                    },
                    new FunnelResultStep
                    {
                        EventCollection = FunnelColB,
                    },
                },
                Result = new[] { 3, 2 }
            };

            Mock <IQueries> queryMock = null;

            if (UseMocks)
            {
                queryMock = new Mock <IQueries>();
                queryMock.Setup(m => m.Funnel(
                                    It.Is <IEnumerable <FunnelStep> >(f => f.Equals(funnelsteps)),
                                    It.Is <IQueryTimeframe>(t => null == t),
                                    It.Is <string>(t => t == "")
                                    ))
                .Returns(Task.FromResult(expected));

                client.Queries = queryMock.Object;
            }

            var reply = (await client.QueryFunnelAsync(funnelsteps, null));

            Assert.NotNull(reply);
            Assert.NotNull(reply.Result);
            Assert.True(reply.Result.SequenceEqual(expected.Result));
            Assert.NotNull(reply.Steps);
            Assert.AreEqual(reply.Steps.Count(), 2);

            if (null != queryMock)
            {
                queryMock.VerifyAll();
            }
        }
        public async Task Query_SimpleFunnel_Success()
        {
            var queryParameters = new FunnelParameters()
            {
                Steps = new FunnelStep[]
                {
                    new FunnelStep()
                    {
                        EventCollection = "signed up", ActorProperty = "visitor.guid", Timeframe = QueryRelativeTimeframe.ThisNDays(7)
                    },
                    new FunnelStep()
                    {
                        EventCollection = "completed profile", ActorProperty = "user.guid", Timeframe = QueryRelativeTimeframe.ThisNDays(7)
                    },
                    new FunnelStep()
                    {
                        EventCollection = "referred user", ActorProperty = "user.guid", Timeframe = QueryRelativeTimeframe.ThisNDays(7)
                    },
                }
            };

            string responseJson = @"{
                ""result"": [
                    3,
                    1,
                    0
                ],
                ""steps"": [
                    {
                        ""actor_property"": ""visitor.guid"",
                        ""event_collection"": ""signed up"",
                        ""timeframe"": ""this_7_days""
                    },
                    {
                        ""actor_property"": ""user.guid"",
                        ""event_collection"": ""completed profile"",
                        ""timeframe"": ""this_7_days""
                    },
                    {
                        ""actor_property"": ""user.guid"",
                        ""event_collection"": ""referred user"",
                        ""timeframe"": ""this_7_days""
                    }
                ]
            }";

            var expectedResponse = JObject.Parse(responseJson);

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResults = await client.Queries.Funnel(
                queryParameters.Steps);

            var expectedResults = expectedResponse["result"];

            Assert.AreEqual(expectedResults.Count(), actualResults.Result.Count());
            var actualEnumerator = actualResults.Result.GetEnumerator();

            foreach (var expected in expectedResults)
            {
                actualEnumerator.MoveNext();
                var actual = actualEnumerator.Current;
                // Validate the result is correct
                Assert.AreEqual(expected.Value <int>(), actual);
            }
        }
        public async Task Query_SimpleExtraction_Success()
        {
            var queryParameters = new ExtractionParameters()
            {
                Timeframe = QueryRelativeTimeframe.ThisNHours(2),
            };

            string resultsJson = @"[
                {
                    ""keen"": {
                        ""created_at"": ""2012-07-30T21:21:46.566000+00:00"",
                        ""timestamp"": ""2012-07-30T21:21:46.566000+00:00"",
                        ""id"": """"
                    },
                    ""user"": {
                        ""email"": ""*****@*****.**"",
                        ""id"": ""4f4db6c7777d66ffff000000""
                    },
                    ""user_agent"": {
                        ""browser"": ""chrome"",
                        ""browser_version"": ""20.0.1132.57"",
                        ""platform"": ""macos""
                    }
                },
                {
                    ""keen"": {
                        ""created_at"": ""2012-07-30T21:40:05.386000+00:00"",
                        ""timestamp"": ""2012-07-30T21:40:05.386000+00:00"",
                        ""id"": """"
                    },
                    ""user"": {
                        ""email"": ""*****@*****.**"",
                        ""id"": ""4fa2cccccf546ffff000006""
                    },
                    ""user_agent"": {
                        ""browser"": ""chrome"",
                        ""browser_version"": ""20.0.1132.57"",
                        ""platform"": ""macos""
                    }
                }
            ]";

            var expectedResults = JArray.Parse(resultsJson);

            var expectedResponse = new
            {
                result = expectedResults
            };

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResults = await client.Queries.Extract(
                queryParameters.EventCollection,
                queryParameters.Timeframe);

            Assert.AreEqual(expectedResults.Count(), actualResults.Count());
            var actualEnumerator = actualResults.GetEnumerator();

            foreach (var expected in expectedResults)
            {
                actualEnumerator.MoveNext();
                JToken actual = actualEnumerator.Current;
                // Validate the result is correct
                Assert.AreEqual(expected["user"]["email"].Value <string>(), actual["user"]["email"].Value <string>());
                Assert.AreEqual(expected["user"]["id"].Value <string>(), actual["user"]["id"].Value <string>());
                Assert.AreEqual(expected["user_agent"]["browser"].Value <string>(), actual["user_agent"]["browser"].Value <string>());
            }
        }
        public async Task Query_SimpleSelectUniqueGroupByInterval_Success()
        {
            var queryParameters = new QueryParameters()
            {
                Analysis       = QueryType.SelectUnique(),
                TargetProperty = "someProperty",
                Timeframe      = QueryRelativeTimeframe.ThisNHours(2),
                Interval       = QueryInterval.EveryNHours(1),
                GroupBy        = "someGroupProperty"
            };

            string resultsJson = @"[
                {
                    ""timeframe"": {
                        ""start"": ""2017-10-14T00:00:00.000Z"",
                        ""end"": ""2017-10-15T00:00:00.000Z""
                    },
                    ""value"": [
                        {
                            ""someGroupProperty"": ""group1"",
                            ""result"": [
                                ""10"",
                                ""20""
                            ]
                        },
                        {
                            ""someGroupProperty"": ""group2"",
                            ""result"": [
                                ""30"",
                                ""40""
                            ]
                        }
                    ]
                },
                {
                    ""timeframe"": {
                        ""start"": ""2017-10-15T00:00:00.000Z"",
                        ""end"": ""2017-10-16T00:00:00.000Z""
                    },
                    ""value"": [
                        {
                            ""someGroupProperty"": ""group1"",
                            ""result"": [
                                ""50"",
                                ""60""
                            ]
                        },
                        {
                            ""someGroupProperty"": ""group2"",
                            ""result"": [
                                ""70"",
                                ""80""
                            ]
                        }
                    ]
                }
            ]";

            var expectedResults = JArray.Parse(resultsJson);

            var expectedResponse = new
            {
                result = expectedResults
            };

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResults = await client.Queries.Metric(
                queryParameters.Analysis,
                queryParameters.EventCollection,
                queryParameters.TargetProperty,
                queryParameters.GroupBy,
                queryParameters.Timeframe,
                queryParameters.Interval);

            Assert.AreEqual(expectedResults.Count(), actualResults.Count());
            var actualEnumerator = actualResults.GetEnumerator();

            foreach (var expected in expectedResults)
            {
                actualEnumerator.MoveNext();
                var actual = actualEnumerator.Current;
                // Validate the interval is correct
                Assert.AreEqual(DateTime.Parse(expected["timeframe"]["start"].Value <string>()), actual.Start);
                Assert.AreEqual(DateTime.Parse(expected["timeframe"]["end"].Value <string>()), actual.End);

                // Validate the results for the group within the time interval
                Assert.AreEqual(expected["value"].Count(), actual.Value.Count());
                var actualGroupResultEnumerator = actual.Value.GetEnumerator();
                foreach (var expectedGroupResult in expected["value"])
                {
                    actualGroupResultEnumerator.MoveNext();
                    var actualGroupResult = actualGroupResultEnumerator.Current;
                    Assert.AreEqual(expectedGroupResult[queryParameters.GroupBy].Value <string>(), actualGroupResult.Group);
                    Assert.AreEqual(string.Join(",", expectedGroupResult["result"].Values <string>()), actualGroupResult.Value);
                }
            }
        }
        public async Task Query_SimpleCountGroupByInterval_Success()
        {
            var queryParameters = new QueryParameters()
            {
                TargetProperty = "someProperty",
                Timeframe      = QueryRelativeTimeframe.ThisNHours(2),
                Interval       = QueryInterval.EveryNHours(1),
                GroupBy        = "someGroupProperty"
            };

            var expectedResults = new[]
            {
                new
                {
                    timeframe = new QueryAbsoluteTimeframe(DateTime.Now.AddHours(-2), DateTime.Now.AddHours(-1)),
                    value     = new List <Dictionary <string, string> >
                    {
                        new Dictionary <string, string> {
                            { queryParameters.GroupBy, "group1" }, { "result", "10" }
                        },
                        new Dictionary <string, string> {
                            { queryParameters.GroupBy, "group2" }, { "result", "20" }
                        },
                    }
                },
                new
                {
                    timeframe = new QueryAbsoluteTimeframe(DateTime.Now.AddHours(-1), DateTime.Now),
                    value     = new List <Dictionary <string, string> >
                    {
                        new Dictionary <string, string> {
                            { queryParameters.GroupBy, "group1" }, { "result", "30" }
                        },
                        new Dictionary <string, string> {
                            { queryParameters.GroupBy, "group2" }, { "result", "40" }
                        },
                    }
                }
            };

            var expectedResponse = new
            {
                result = expectedResults
            };

            var client = CreateQueryTestKeenClient(queryParameters, expectedResponse);

            var actualResults = await client.Queries.Metric(
                queryParameters.Analysis,
                queryParameters.EventCollection,
                queryParameters.TargetProperty,
                queryParameters.GroupBy,
                queryParameters.Timeframe,
                queryParameters.Interval);

            Assert.AreEqual(expectedResults.Count(), actualResults.Count());
            var actualEnumerator = actualResults.GetEnumerator();

            foreach (var expected in expectedResults)
            {
                actualEnumerator.MoveNext();
                var actual = actualEnumerator.Current;
                // Validate the interval is correct
                Assert.AreEqual(expected.timeframe.Start, actual.Start);
                Assert.AreEqual(expected.timeframe.End, actual.End);

                // Validate the results for the group within the time interval
                Assert.AreEqual(expected.value.Count, actual.Value.Count());
                var actualGroupResultEnumerator = actual.Value.GetEnumerator();
                foreach (var expectedGroupResult in expected.value)
                {
                    actualGroupResultEnumerator.MoveNext();
                    var actualGroupResult = actualGroupResultEnumerator.Current;
                    Assert.AreEqual(expectedGroupResult[queryParameters.GroupBy], actualGroupResult.Group);
                    Assert.AreEqual(expectedGroupResult["result"], actualGroupResult.Value);
                }
            }
        }