public async Task A_dynamic_projector_can_access_the_metadata_of_unknown_event_types_dynamically()
        {
            StorableEvent storableEvent = null;

            using (var db = EventStoreDbContext())
            {
                storableEvent = new StorableEvent
                {
                    AggregateId = Guid.NewGuid(),
                    StreamName  = Any.CamelCaseName(),
                    Type        = Any.CamelCaseName(),
                    Body        = new { }.ToJson()
                };
                db.Events.Add(storableEvent);
                await db.SaveChangesAsync();
            }

            IEvent receivedEvent = null;

            var projector = Projector.CreateDynamic(e => receivedEvent = e);

            using (var catchup = CreateReadModelCatchup(projector))
            {
                await catchup.Run();
            }

            long absoluteSequenceNumber = ((IHaveExtensibleMetada)receivedEvent).Metadata.AbsoluteSequenceNumber;

            absoluteSequenceNumber.Should().Be(storableEvent.Id);
        }
        public async Task A_dynamic_projector_can_access_the_properties_of_unknown_event_types_dynamically()
        {
            using (var db = EventStoreDbContext())
            {
                Enumerable.Range(1, 10).ForEach(i => db.Events.Add(new StorableEvent
                {
                    AggregateId = Guid.NewGuid(),
                    StreamName  = Any.CamelCaseName(),
                    Type        = Any.CamelCaseName(),
                    Body        = new { SomeValue = i }.ToJson()
                }));
                await db.SaveChangesAsync();
            }
            var total = 0;

            using (var catchup = CreateReadModelCatchup(Projector.CreateDynamic(e =>
            {
                total += (int)e.SomeValue;
            })))
            {
                await catchup.Run();
            }

            total.Should().Be(55);
        }
        public async Task CreateDynamic_queries_all_events()
        {
            Events.Write(10);
            var projectedEventCount = 0;

            using (var catchup = CreateReadModelCatchup(Projector.CreateDynamic(e =>
            {
                projectedEventCount++;
            })))
            {
                await catchup.Run();
            }

            projectedEventCount.Should().Be(10);
        }
        public async Task A_dynamic_projector_receives_known_event_types_as_their_actual_type()
        {
            IEvent receivedEvent = null;

            Events.Write(1, _ => new Order.CustomerInfoChanged());

            using (var catchup = CreateReadModelCatchup(Projector.CreateDynamic(e =>
            {
                receivedEvent = e;
            })))
            {
                await catchup.Run();
            }

            receivedEvent.Should().BeOfType <Order.CustomerInfoChanged>();
        }
        public async Task A_dynamic_projector_can_access_the_metadata_of_known_event_types_dynamically()
        {
            var lastEventId = Events.Write(1, _ => new Order.CustomerInfoChanged());

            Order.CustomerInfoChanged receivedEvent = null;

            var projector = Projector.CreateDynamic(e => receivedEvent = e);

            using (var catchup = CreateReadModelCatchup(projector))
            {
                await catchup.Run();
            }

            long absoluteSequenceNumber = receivedEvent.Metadata.AbsoluteSequenceNumber;

            absoluteSequenceNumber.Should().Be(lastEventId);
        }
        public async Task Dynamic_projectors_can_access_the_event_properties_of_received_events()
        {
            var  expectedTimestamp       = DateTimeOffset.Parse("2014-07-03");
            var  expectedAggregateId     = Any.Guid();
            var  receivedAggregateId     = new Guid();
            var  expectedSequenceNumber  = Any.PositiveInt();
            long receivedSequenceNumber  = 0;
            var  receivedTimestamp       = new DateTimeOffset();
            var  receivedEventStreamName = "";
            var  receivedEventTypeName   = "";

            using (var db = EventStoreDbContext())
            {
                db.Events.Add(new StorableEvent
                {
                    AggregateId    = expectedAggregateId,
                    SequenceNumber = expectedSequenceNumber,
                    Timestamp      = expectedTimestamp,
                    StreamName     = "Reporting",
                    Type           = "DuckEvent",
                    Body           = new { Quacks = 9000 }.ToJson()
                });

                await db.SaveChangesAsync();
            }

            var projector = Projector.CreateDynamic(e =>
            {
                receivedAggregateId     = e.AggregateId;
                receivedSequenceNumber  = e.SequenceNumber;
                receivedTimestamp       = e.Timestamp;
                receivedEventStreamName = e.EventStreamName;
                receivedEventTypeName   = e.EventTypeName;
            });

            using (var catchup = CreateReadModelCatchup(projector))
            {
                await catchup.Run();
            }

            receivedAggregateId.Should().Be(expectedAggregateId);
            receivedSequenceNumber.Should().Be(expectedSequenceNumber);
            receivedTimestamp.Should().Be(expectedTimestamp);
            receivedEventStreamName.Should().Be("Reporting");
            receivedEventTypeName.Should().Be("DuckEvent");
        }
        public async Task A_dynamic_projector_can_specify_which_events_to_query()
        {
            var eventsQueried         = 0;
            var expectedEventsQueried = 0;

            Events.Write(20, _ =>
            {
                Event e = null;
                switch (Any.Int(1, 3))
                {
                case 1:
                    e = (Event)Events.Any();
                    break;

                case 2:
                    e = new Order.ItemAdded();
                    break;

                case 3:
                    e = new Order.ItemRemoved();
                    break;
                }

                if (e is Order.ItemAdded || e is Order.ItemRemoved)
                {
                    expectedEventsQueried++;
                }

                e.AggregateId = Guid.NewGuid();

                return(e);
            });

            using (var catchup = CreateReadModelCatchup(Projector.CreateDynamic(e =>
            {
                eventsQueried++;
            },
                                                                                "Order.ItemAdded",
                                                                                "Order.ItemRemoved")))
            {
                await catchup.Run();
            }

            eventsQueried.Should().Be(expectedEventsQueried);
        }
        public async Task A_dynamic_projector_can_access_the_properties_of_known_event_types_dynamically()
        {
            var    expectedName = Any.FullName();
            string actualName   = null;

            Events.Write(1, _ => new Order.CustomerInfoChanged
            {
                CustomerName = expectedName
            });

            using (var catchup = CreateReadModelCatchup(Projector.CreateDynamic(e =>
            {
                actualName = e.CustomerName;
            })))
            {
                await catchup.Run();
            }

            actualName.Should().Be(expectedName);
        }
        public async Task Catchup_continues_when_DynamicProjector_throws()
        {
            Events.Write(20);
            int counter       = 0;
            int eventsHandled = 0;
            var handler       = Projector.CreateDynamic(e =>
            {
                counter++;
                if (counter == 10)
                {
                    throw new Exception("oops!");
                }
                eventsHandled++;
            });

            await new ReadModelCatchup(handler)
            {
                StartAtEventId = HighestEventId + 1
            }.SingleBatchAsync();

            eventsHandled.Should().Be(19);
        }
        public async Task Catchup_continues_when_DynamicProjector_throws()
        {
            Events.Write(20);
            var counter       = 0;
            var eventsHandled = 0;
            var handler       = Projector.CreateDynamic(e =>
            {
                counter++;
                if (counter == 10)
                {
                    throw new Exception("oops!");
                }
                eventsHandled++;
            });

            await new ReadModelCatchup(
                eventStoreDbContext: () => EventStoreDbContext(),
                readModelDbContext: () => ReadModelDbContext(),
                startAtEventId: HighestEventId + 1,
                projectors: handler).SingleBatchAsync();

            eventsHandled.Should().Be(19);
        }