public void CanGetLoans()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var loan1 = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };
            var loan2 = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };
            var loan3 = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };
            var loan4 = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            member.AddLoan(loan1);
            member.AddLoan(loan2);
            member.AddLoan(loan3);

            Assert.Equal(3, member.Loans.Count());
            Assert.Contains(loan1, member.Loans);
            Assert.DoesNotContain(loan4, member.Loans);
        }
        public void AddLoanThrowsInvalidOperationExceptionIfMemberIsNotAllowedToBorrow()
        {
            // Set member to BORROWING_DISALLOWED
            var member = new Member("test", "member", "phone", "email", 1) { State = MemberState.BORROWING_DISALLOWED };

            var loan = Substitute.For<ILoan>();

            var ex = Assert.Throws<InvalidOperationException>(() => member.AddLoan(loan));

            Assert.Equal("Cannot add a loan when member is not allowed to borrow", ex.Message);
        }
        public void AddLoanThrowsArgumentNullExceptionIfLoanIsNull()
        {
            var member = new Member("test", "member", "phone", "email", 1);

            // Null loan.
            ILoan loan = null;

            var ex = Assert.Throws<ArgumentException>(() => member.AddLoan(loan));

            Assert.Equal("Loan cannot be null", ex.Message);
        }
        public void CanAddLoanToMember()
        {
            var member = new Member("test", "member", "phone", "email", 1);

            // Can add a loan.
            var loan = Substitute.For<ILoan>();

            member.AddLoan(loan);

            Assert.Contains(loan, member.Loans);
        }
        public void AddLoanThrowsInvalidOperationExceptionIfMemberIsNotAllowedToBorrow()
        {
            var book = new Book("author", "title", "call number", 1);

            // Set member to BORROWING_DISALLOWED
            var member = new Member("first", "last", "phone", "email", 1) { State = MemberState.BORROWING_DISALLOWED };

            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            var ex = Assert.Throws<InvalidOperationException>(() => member.AddLoan(loan));

            Assert.Equal("Cannot add a loan when member is not allowed to borrow", ex.Message);
        }
        public void CanAddLoanToMember()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            // Add a loan.
            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            member.AddLoan(loan);

            Assert.Contains(loan, member.Loans);
        }
        public void CanRemoveLoanFromMember()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            member.AddLoan(loan);

            // Make sure Member has Loan.
            Assert.Contains(loan, member.Loans);

            member.RemoveLoan(loan);

            // Make sure Loan has been removed from Member.
            Assert.DoesNotContain(loan, member.Loans);
        }
        public void WhenBorrowingAllowedAndHasOverdueLoansBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            var loan = Substitute.For<ILoan>();

            loan.CheckOverDue(DateTime.Today).Returns(true);
            loan.IsOverDue.Returns(true);

            member.AddLoan(loan);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);

            foreach (var l in member.Loans) l.CheckOverDue(DateTime.Today);

            Assert.True(member.HasOverDueLoans);

            loan.Received().CheckOverDue(DateTime.Today);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingAllowedAndNoOverdueLoansBorrowingAllowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            member.AddLoan(loan);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);

            foreach (var l in member.Loans) l.CheckOverDue(DateTime.Today);

            Assert.False(member.HasOverDueLoans);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndLoanRemovedButHasOverdueLoanBorrowingDisallowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var overdue = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

            member.AddLoan(overdue);

            // Set it to overdue
            overdue.CheckOverDue(DateTime.Today.AddMonths(1));

            while (!member.HasReachedLoanLimit)
            {
                var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

                member.AddLoan(loan);
            }

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            // Remove the first one that isn't the overdue mock.
            member.RemoveLoan(member.Loans.First(l => l != overdue));

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndLoanRemovedButHasFinesBorrowingDisallowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            while (!member.HasReachedLoanLimit)
            {
                var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

                member.AddLoan(loan);
            }

            member.AddFine(BookConstants.FINE_LIMIT + 1.00f);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            // Remove the first one that isn't the overdue mock.
            member.RemoveLoan(member.Loans[0]);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndLoanRemovedBorrowingAllowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            while (!member.HasReachedLoanLimit)
            {
                var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

                member.AddLoan(loan);
            }

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.RemoveLoan(member.Loans[0]);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);
        }
        public void CanRemoveLoanFromMember()
        {
            var member = new Member("test", "member", "phone", "email", 1);

            var loan = Substitute.For<ILoan>();

            member.AddLoan(loan);

            // Make sure Member has Loan.
            Assert.Contains(loan, member.Loans);

            member.RemoveLoan(loan);

            // Make sure Loan has been removed from Member.
            Assert.DoesNotContain(loan, member.Loans);
        }
        public void WhenBorrowingDisallowedAndLoanRemovedButHasFinesBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            while (!member.HasReachedLoanLimit)
            {
                var loan = Substitute.For<ILoan>();

                member.AddLoan(loan);
            }

            member.AddFine(BookConstants.FINE_LIMIT + 1.00f);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            // Remove the first one that isn't the overdue mock.
            member.RemoveLoan(member.Loans[0]);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButHasOverdueLoansBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            var loan = Substitute.For<ILoan>();

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            member.AddLoan(loan);

            member.AddFine(fineAmount);

            loan.IsOverDue.Returns(true);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void RemoveLoanThrowsArgumentExceptionIfLoanIsNotInCollection()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var loan1 = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            var loan2 = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            member.AddLoan(loan1);

            var ex = Assert.Throws<ArgumentException>(() => member.RemoveLoan(loan2));

            Assert.Equal("Loan was not found in member's loans", ex.Message);
        }
        public void HasReachedLoanLimitReturnsTrueIfLoanCountEqualsLoanLimit()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            // Add a loan.
            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            member.AddLoan(loan);

            // Test that Loan Limit is not reached.
            Assert.True(member.Loans.Count() < BookConstants.LOAN_LIMIT);
            Assert.False(member.HasReachedLoanLimit);

            // Add additional loans.
            while (member.Loans.Count() < BookConstants.LOAN_LIMIT)
            {
                member.AddLoan(new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)));
            }

            // Test that Loan Limit has been reached.
            Assert.True(member.Loans.Count() == BookConstants.LOAN_LIMIT);
            Assert.True(member.HasReachedLoanLimit);
        }
        public void HasOverdueLoansReturnsTrueIfAnyLoanIsOverdue()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            // Add a single loan that is not overdue.
            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            member.AddLoan(loan);

            // Add a second loan that is overdue.
            var secondLoan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

            member.AddLoan(secondLoan);

            // Check if overdue

            foreach (var l in member.Loans)
            {
                l.CheckOverDue(DateTime.Today.AddDays(10));
            }

            Assert.True(member.HasOverDueLoans);
        }
        public void RemoveLoanThrowsArgumentExceptionIfLoanIsNotInCollection()
        {
            var member = new Member("test", "member", "phone", "email", 1);

            var loan1 = Substitute.For<ILoan>();
            var loan2 = Substitute.For<ILoan>();

            member.AddLoan(loan1);

            var ex = Assert.Throws<ArgumentException>(() => member.RemoveLoan(loan2));

            Assert.Equal("Loan was not found in member's loans", ex.Message);
        }
        public void WhenBorrowingAllowedAndRemovingLoanBorrowingAllowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            var loan = Substitute.For<ILoan>();

            member.AddLoan(loan);

            Assert.False(member.HasReachedLoanLimit);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);

            member.RemoveLoan(loan);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);
        }
        public void WhenBorrowingAllowedAndRemovingLoanBorrowingAllowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(14)) { State = LoanState.CURRENT };

            member.AddLoan(loan);

            Assert.False(member.HasReachedLoanLimit);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);

            member.RemoveLoan(loan);

            Assert.Equal(MemberState.BORROWING_ALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButLoanLimitStillReachedBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            while (!member.HasReachedLoanLimit)
            {
                var loan = Substitute.For<ILoan>();

                member.AddLoan(loan);
            }

            member.AddFine(fineAmount);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount);

            Assert.True(member.HasReachedLoanLimit);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButHasOverdueLoansBorrowingDisallowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            member.AddLoan(loan);

            member.AddFine(fineAmount);

            foreach (var l in member.Loans) l.CheckOverDue(DateTime.Today.AddMonths(1));

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndLoanRemovedButHasOverdueLoanBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            var overdue = Substitute.For<ILoan>();

            member.AddLoan(overdue);

            overdue.IsOverDue.Returns(true);

            while (!member.HasReachedLoanLimit)
            {
                var loan = Substitute.For<ILoan>();

                member.AddLoan(loan);
            }

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            // Remove the first one that isn't the overdue mock.
            member.RemoveLoan(member.Loans.First(l => l != overdue));

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingDisallowedAndFinePaidButLoanLimitStillReachedBorrowingDisallowed()
        {
            var book = new Book("author", "title", "call number", 1);

            var member = new Member("first", "last", "phone", "email", 1);

            var fineAmount = BookConstants.FINE_LIMIT + 5.00f;

            while (!member.HasReachedLoanLimit)
            {
                var loan = new Loan(book, member, DateTime.Today, DateTime.Today.AddDays(7)) { State = LoanState.CURRENT };

                member.AddLoan(loan);
            }

            member.AddFine(fineAmount);

            // Borrowing state disallowed.
            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);

            member.PayFine(fineAmount);

            Assert.True(member.HasReachedLoanLimit);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void WhenBorrowingAllowedAndLoanAddedAndLimitReachedBorrowingDisallowed()
        {
            var member = new Member("firstName", "lastName", "contactPhone", "emailAddress", 1);

            while (!member.HasReachedLoanLimit)
            {
                var loan = Substitute.For<ILoan>();

                member.AddLoan(loan);
            }

            Assert.True(member.HasReachedLoanLimit);

            Assert.Equal(MemberState.BORROWING_DISALLOWED, member.State);
        }
        public void CanGetLoans()
        {
            var member = new Member("test", "member", "phone", "email", 1);

            var loan1 = Substitute.For<ILoan>();
            var loan2 = Substitute.For<ILoan>();
            var loan3 = Substitute.For<ILoan>();
            var loan4 = Substitute.For<ILoan>();

            member.AddLoan(loan1);
            member.AddLoan(loan2);
            member.AddLoan(loan3);

            Assert.Equal(3, member.Loans.Count());
            Assert.Contains(loan1, member.Loans);
            Assert.DoesNotContain(loan4, member.Loans);
        }