WHEN_client_recieves_patch_THEN_it_should_call_onpatch_and_updateddata()
        {
            var client = StreamdataClient <StockMarketOrders> .WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine <FakeEngine>();
            });

            StockMarketOrders testData             = null;
            StockMarketOrders expectedMarketOrders = new StockMarketOrders();

            expectedMarketOrders.Add(new Order()
            {
                Price = 10, Title = "test1"
            });
            expectedMarketOrders.Add(new Order()
            {
                Price = 20, Title = "test2"
            });

            client.OnData(data => testData = data);
            client.OnPatch(patch => patch.ApplyTo(testData));
            client.Start("fakeurl");

            FakeEngineWrapper.Instance.SendData(expectedMarketOrders);
            var patchDoc = new JsonPatchDocument <StockMarketOrders>(new List <Operation <StockMarketOrders> >
            {
                new Operation <StockMarketOrders>("replace", "0/price", "0/price", 30)
            });

            FakeEngineWrapper.Instance.SendPatch(patchDoc);
            Check.That(testData).IsNotNull();
            Check.That(testData).HasSize(2);
            Check.That(testData.GetTotal()).IsEqualTo(50);
        }
        WHEN_client_recieves_patch_THEN_it_should_call_onpatch_and_updateddata()
        {
            var client = StreamdataClient<StockMarketOrders>.WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine<FakeEngine>();
            });

            StockMarketOrders testData = null;
            StockMarketOrders expectedMarketOrders = new StockMarketOrders();
            expectedMarketOrders.Add(new Order() { Price = 10, Title = "test1" });
            expectedMarketOrders.Add(new Order() { Price = 20, Title = "test2" });

            client.OnData(data => testData = data);
            client.OnPatch(patch => patch.ApplyTo(testData));
            client.Start("fakeurl");

            FakeEngineWrapper.Instance.SendData(expectedMarketOrders);
            var patchDoc = new JsonPatchDocument<StockMarketOrders>(new List<Operation<StockMarketOrders>>
            {
                new Operation<StockMarketOrders>("replace","0/price","0/price",30)
            });
            FakeEngineWrapper.Instance.SendPatch(patchDoc);
            Check.That(testData).IsNotNull();
			Check.That(testData).HasSize(2);
            Check.That(testData.GetTotal()).IsEqualTo(50);
        }
        WHEN_client_recieves_data_THEN_it_should_call_ondata()
        {
            var client = StreamdataClient <StockMarketOrders> .WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine <FakeEngine>();
            });

            StockMarketOrders testData             = null;
            StockMarketOrders expectedMarketOrders = new StockMarketOrders();

            expectedMarketOrders.Add(new Order()
            {
                Price = 10, Title = "test1"
            });
            expectedMarketOrders.Add(new Order()
            {
                Price = 20, Title = "test2"
            });

            client.OnData(data => testData = data);

            client.Start("fakeurl");

            FakeEngineWrapper.Instance.SendData(expectedMarketOrders);

            Check.That(testData).IsNotNull();
            Check.That(testData.GetTotal()).IsEqualTo(30);
        }
        WHEN_client_has_data_and_patch_THEN_state_is_updated()
        {
            var client = StreamdataClient <StockMarketOrders> .WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine <FakeEngine>();
                conf.KeepStateUpdated();
            });

            StockMarketOrders expectedMarketOrders = new StockMarketOrders();

            expectedMarketOrders.Add(new Order()
            {
                Price = 10, Title = "test1"
            });
            expectedMarketOrders.Add(new Order()
            {
                Price = 20, Title = "test2"
            });
            StockMarketOrders actualState = null;

            client.Start("fakeurl");
            client.OnUpdatedState += state => actualState = state;
            FakeEngineWrapper.Instance.SendData(expectedMarketOrders);
            var patch = new JsonPatchDocument <StockMarketOrders>(new List <Operation <StockMarketOrders> >
            {
                new Operation <StockMarketOrders>("replace", "0/price", "0/price", 20)
            });

            FakeEngineWrapper.Instance.SendPatch(patch);
            Check.That(actualState).IsNotNull();
            Check.That(actualState.GetTotal()).IsEqualTo(40);
        }
        WHEN_client_has_no_data_THEN_state_is_default_and_dont_throw_exception()
        {
            var client = StreamdataClient <StockMarketOrders> .WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine <FakeEngine>();
            });

            client.Start("fakeurl");
            StockMarketOrders actualState = null;

            Check.ThatCode(() => actualState = client.State)
            .DoesNotThrow();

            Check.That(actualState).IsEqualTo(default(StockMarketOrders));
        }
        WHEN_client_starts_THEN_it_should_order_engine_to_start()
        {
            var client = StreamdataClient <StockMarketOrders> .WithDefaultConfiguration();

            StockMarketOrders orders = null;
            int counter    = 0;
            var testApiUrl = "http://stockmarket.streamdata.io/prices";

            client.OnData(o => orders = o);
            client.OnPatch(p => counter++);
            client.Start(testApiUrl);
            var expectedUrl = $"{StreamdataOfficialUrls.PRODUCTION}/{testApiUrl}?X-Sd-Token={client.Configuration.SecretKey}";

            Check.That(client.ListenUrl).IsEqualTo(expectedUrl);
            //we wait 10s, after this time, we should already
            //have some first data and at least, one update
            Thread.Sleep(10 * 1000);
            Check.That(orders).IsNotNull();
            Check.That(counter).IsGreaterThan(0);
        }
        WHEN_client_recieves_data_THEN_it_should_call_ondata()
        {
            var client = StreamdataClient<StockMarketOrders>.WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine<FakeEngine>();
            });

            StockMarketOrders testData = null;
            StockMarketOrders expectedMarketOrders = new StockMarketOrders();
            expectedMarketOrders.Add(new Order() { Price = 10, Title = "test1" });
            expectedMarketOrders.Add(new Order() { Price = 20, Title = "test2" });

            client.OnData(data => testData = data);

            client.Start("fakeurl");

            FakeEngineWrapper.Instance.SendData(expectedMarketOrders);

            Check.That(testData).IsNotNull();
            Check.That(testData.GetTotal()).IsEqualTo(30);
        }
        WHEN_engine_receives_data_without_ondata_configured_THEN_it_should_not_throw_exception()
        {
            var client = StreamdataClient <StockMarketOrders> .WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine <FakeEngine>();
            });

            StockMarketOrders expectedMarketOrders = new StockMarketOrders();

            expectedMarketOrders.Add(new Order()
            {
                Price = 10, Title = "test1"
            });
            expectedMarketOrders.Add(new Order()
            {
                Price = 20, Title = "test2"
            });

            client.Start("fakeurl");

            Check.ThatCode(() => FakeEngineWrapper.Instance.SendData(expectedMarketOrders)).DoesNotThrow();
        }
       WHEN_engine_receives_data_without_ondata_configured_THEN_it_should_not_throw_exception()
        {
            var client = StreamdataClient<StockMarketOrders>.WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine<FakeEngine>();
            });

            StockMarketOrders expectedMarketOrders = new StockMarketOrders();
            expectedMarketOrders.Add(new Order() { Price = 10, Title = "test1" });
            expectedMarketOrders.Add(new Order() { Price = 20, Title = "test2" });

            client.Start("fakeurl");

            Check.ThatCode(()=> FakeEngineWrapper.Instance.SendData(expectedMarketOrders)).DoesNotThrow();
            
        }
        WHEN_client_has_data_and_patch_THEN_state_is_updated()
        {
            var client = StreamdataClient<StockMarketOrders>.WithConfiguration(conf =>
            {
                conf.UseSandbox();
                conf.UserServerSentEventEngine<FakeEngine>();
                conf.KeepStateUpdated();
            });
            StockMarketOrders expectedMarketOrders = new StockMarketOrders();
            expectedMarketOrders.Add(new Order() { Price = 10, Title = "test1" });
            expectedMarketOrders.Add(new Order() { Price = 20, Title = "test2" });
            StockMarketOrders actualState=null;

            client.Start("fakeurl");
            client.OnUpdatedState += state => actualState = state;
            FakeEngineWrapper.Instance.SendData(expectedMarketOrders);
            var patch = new JsonPatchDocument<StockMarketOrders>(new List<Operation<StockMarketOrders>>
            {
                new Operation<StockMarketOrders>("replace","0/price","0/price",20)
            });
            FakeEngineWrapper.Instance.SendPatch(patch);
            Check.That(actualState).IsNotNull();
            Check.That(actualState.GetTotal()).IsEqualTo(40);
        }