public void Add_GivenMessageWithRecipientsAndSender_AddsMessageRecipientsAndSender()
        {
            var hollie = new Person {
                GivenName = "Hollie", FamilyName = "Marin"
            };
            var randall = new Person {
                GivenName = "Randall", FamilyName = "Bloom"
            };
            var glen = new Person {
                GivenName = "Glen", FamilyName = "Hensley"
            };

            var message = new Message
            {
                Sender = hollie,
                Text   = "Hello world!"
            };

            message.Recipients.Add(randall);
            message.Recipients.Add(glen);

            var messageRepository = uow.Repository <Message>();

            messageRepository.Add(message);
            uow.Complete();

            var personRepository = uow.Repository <Person>();

            hollie = personRepository.Find(p => p.FamilyName == "Marin", EntityIncludePaths.ForEntity <Person>().Include(p => p.SentMessages)).Single();
            Assert.IsTrue(hollie.SentMessages.Any());

            glen = personRepository.Find(p => p.FamilyName == "Hensley", EntityIncludePaths.ForEntity <Person>().Include(p => p.ReceivedMessages)).Single();
            Assert.IsTrue(glen.ReceivedMessages.Any());
        }
        public void Add_PersonWithMessages_AddsMessagesAsWell()
        {
            // Arrange
            var repository = uow.Repository <Person>();

            var hollie = new Person
            {
                GivenName  = "Hollie",
                FamilyName = "Marin"
            };

            hollie.SentMessages.Add(new Message
            {
                Sender = hollie,
                Text   = "Hello world!"
            });

            // Act
            repository.Add(hollie);
            uow.Complete();

            var result = repository.Find(new PersonByNameFilter {
                FamilyName = "Marin"
            }, EntityIncludePaths.ForEntity <Person>().Include(p => p.ReceivedMessages));

            hollie = result.Single();

            // Assert
            Assert.AreEqual(hollie.GivenName, "Hollie");
            Assert.IsTrue(hollie.SentMessages.Any());
            Assert.IsFalse(hollie.ReceivedMessages.Any());
        }
        public void ForEntity_ByDefault_HasNoPaths()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act

            // Assert
            Assert.IsFalse(includePaths.Any());
        }
        public void Include_GivenCollectionProperty_AddsExpectedPath()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Book>();

            // Act
            includePaths = includePaths.Include(book => book.Authors);

            // Assert
            Assert.IsTrue(includePaths.Contains(nameof(Book.Authors)));
        }
        public void Include_GivenObjectProperty_AddsExpectedPath()
        {
            // Arrange
            var include = EntityIncludePaths.ForEntity <Person>();

            // Act
            include = include.Include(person => person.FavoriteBook);

            // Assert
            Assert.IsTrue(include.Contains(nameof(Person.FavoriteBook)));
        }
        public void Include_CalledTwiceForDifferentProperties_AddsBothPaths()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            includePaths = includePaths.Include(person => person.GivenName).Include(person => person.FamilyName);

            // Assert
            Assert.AreEqual(2, includePaths.Count());
        }
        public void Include_GivenSimpleProperty_AddsExpectedPath()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            includePaths = includePaths.Include(person => person.FamilyName);

            // Assert
            Assert.IsTrue(includePaths.Contains(nameof(Person.FamilyName)));
        }
        public void Include_CalledOnce_AddsOnePath()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            includePaths = includePaths.Include(person => person.FamilyName);

            // Assert
            Assert.AreEqual(1, includePaths.Count());
        }
        public void Include_GivenUndefinedProperty_ThrowsException()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            void action() => includePaths.Include(person => "UndefinedProperty");

            // Assert
            Assert.ThrowsException <ArgumentNullException>(action);
        }
        public void Add_GivenNull_ThrowsArgumentNullException()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            void action() => includePaths.Add(null);

            // Assert
            Assert.ThrowsException <ArgumentNullException>(action);
        }
        public void Add_GivenValidPath_AddsPath()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            includePaths.Add(nameof(Person.FamilyName));

            // Assert
            Assert.IsTrue(includePaths.Contains(nameof(Person.FamilyName)));
        }
        public void Add_GivenInvalidPath_StillAddsPath()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            includePaths.Add("UndefinedProperty");

            // Assert
            Assert.IsTrue(includePaths.Contains("UndefinedProperty"));
        }
        public void ThenInclude_GivenNestedPropertyWithSomePathAlreadySet_RetainsThatPath()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Book>();

            // Act
            includePaths = includePaths.Include(book => book.Title).Include(book => book.Authors).ThenInclude(author => author.FavoriteBook);

            // Assert
            Assert.IsTrue(includePaths.Contains(nameof(Book.Title)));
        }
        public void Add_GivenEmptyString_ThrowsArgumentException()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            void action() => includePaths.Add(string.Empty);

            // Assert
            Assert.ThrowsException <ArgumentException>(action);
        }
        public void ThenInclude_GivenNestedProperty_AddsExpectedPath()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Book>();

            // Act
            includePaths = includePaths.Include(book => book.Authors).ThenInclude(author => author.FavoriteBook);

            // Assert
            Assert.IsTrue(includePaths.Contains(nameof(Book.Authors) + '.' + nameof(Person.FavoriteBook)));
        }
        public void ThenInclude_GivenUndefinedProperty_ThrowsException()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            Action action = () => includePaths.Include(person => person.FavoriteBook).ThenInclude(b => "UndefinedProperty");

            // Assert
            Assert.ThrowsException <ArgumentNullException>(action);
        }
        public void Add_GivenTwoDifferentPaths_AddsBothPaths()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            // Act
            includePaths.Add(nameof(Person.GivenName));
            includePaths.Add(nameof(Person.FamilyName));

            // Assert
            Assert.AreEqual(2, includePaths.Count());
        }
        public void ThenInclude_GivenNullPropertySelector_ThrowsException()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();
            Expression <Func <Book, Person> > propertySelector = null;

            // Act
            Action action = () => includePaths.Include(person => person.FavoriteBook).ThenInclude(propertySelector);

            // Assert
            Assert.ThrowsException <ArgumentNullException>(action);
        }
        public void Include_GivenNullPropertySelector_ThrowsException()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();
            Expression <Func <Person, string> > propertySelector = null;

            // Act
            void action() => includePaths.Include(propertySelector);

            // Assert
            Assert.ThrowsException <ArgumentNullException>(action);
        }
        public void Remove_GivenExistingPath_RemovesPath()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            includePaths.Add(nameof(Person.FamilyName));

            // Act
            includePaths.Remove(nameof(Person.FamilyName));

            // Assert
            Assert.IsFalse(includePaths.Any());
        }
        public void Remove_GivenExistingPathWithDuplicates_RemovesOnlyOne()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            includePaths.Add(nameof(Person.FamilyName));
            includePaths.Add(nameof(Person.FamilyName));

            // Act
            includePaths.Remove(nameof(Person.FamilyName));

            // Assert
            Assert.AreEqual(1, includePaths.Count());
        }
        public void Remove_GivenExistingPathWithDuplicates_RemovesLastOccurrence()
        {
            // Arrange
            var includePaths = EntityIncludePaths.ForEntity <Person>();

            includePaths.Add(nameof(Person.FamilyName));
            includePaths.Add(nameof(Person.GivenName));
            includePaths.Add(nameof(Person.FamilyName)); // Duplicated

            // Act
            includePaths.Remove(nameof(Person.FamilyName));

            // Assert
            Assert.AreEqual(nameof(Person.FamilyName), includePaths.ElementAt(0));
            Assert.AreEqual(nameof(Person.GivenName), includePaths.ElementAt(1));
        }