Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public enum CommonActions
SearchPatrons = 4,
RenewPatronMembership = 8,
ReturnLoanedBook = 16,
ExtendLoanedBook = 32
}
ExtendLoanedBook = 32,
SearchBooks = 64
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using Library.ApplicationCore;
using System;
using System.Linq;
using Library.ApplicationCore;
using Library.ApplicationCore.Entities;
using Library.ApplicationCore.Enums;
using Library.Console;
using Library.Infrastructure.Data;

public class ConsoleApp
{
Expand All @@ -16,13 +19,15 @@ public class ConsoleApp
ILoanRepository _loanRepository;
ILoanService _loanService;
IPatronService _patronService;
JsonData _jsonData;

public ConsoleApp(ILoanService loanService, IPatronService patronService, IPatronRepository patronRepository, ILoanRepository loanRepository)
public ConsoleApp(ILoanService loanService, IPatronService patronService, IPatronRepository patronRepository, ILoanRepository loanRepository, JsonData jsonData)
{
_patronRepository = patronRepository;
_loanRepository = loanRepository;
_loanService = loanService;
_patronService = patronService;
_jsonData = jsonData;
}

public async Task Run()
Expand Down Expand Up @@ -139,6 +144,7 @@ static CommonActions ReadInputOptions(CommonActions options, out int optionNumbe
"m" when options.HasFlag(CommonActions.RenewPatronMembership) => CommonActions.RenewPatronMembership,
"e" when options.HasFlag(CommonActions.ExtendLoanedBook) => CommonActions.ExtendLoanedBook,
"r" when options.HasFlag(CommonActions.ReturnLoanedBook) => CommonActions.ReturnLoanedBook,
"b" when options.HasFlag(CommonActions.SearchBooks) => CommonActions.SearchBooks,
_ when int.TryParse(userInput, out optionNumber) => CommonActions.Select,
_ => CommonActions.Repeat
};
Expand Down Expand Up @@ -170,6 +176,10 @@ static void WriteInputOptions(CommonActions options)
{
Console.WriteLine(" - \"s\" for new search");
}
if (options.HasFlag(CommonActions.SearchBooks))
{
Console.WriteLine(" - \"b\" to check for book availability");
}
if (options.HasFlag(CommonActions.Quit))
{
Console.WriteLine(" - \"q\" to quit");
Expand All @@ -193,8 +203,9 @@ async Task<ConsoleState> PatronDetails()
loanNumber++;
}

CommonActions options = CommonActions.SearchPatrons | CommonActions.Quit | CommonActions.Select | CommonActions.RenewPatronMembership;
CommonActions options = CommonActions.SearchPatrons | CommonActions.Quit | CommonActions.Select | CommonActions.RenewPatronMembership | CommonActions.SearchBooks;
CommonActions action = ReadInputOptions(options, out int selectedLoanNumber);

if (action == CommonActions.Select)
{
if (selectedLoanNumber >= 1 && selectedLoanNumber <= selectedPatronDetails.Loans.Count())
Expand Down Expand Up @@ -225,10 +236,52 @@ async Task<ConsoleState> PatronDetails()
selectedPatronDetails = (await _patronRepository.GetPatron(selectedPatronDetails.Id))!;
return ConsoleState.PatronDetails;
}
else if (action == CommonActions.SearchBooks)
{
return await SearchBooks();
}

throw new InvalidOperationException("An input option is not handled.");
}

async Task<ConsoleState> SearchBooks()
{
string? bookTitle = null;
while (string.IsNullOrWhiteSpace(bookTitle))
{
Console.Write("Enter a book title to search for: ");
bookTitle = Console.ReadLine();
}

await _jsonData.EnsureDataLoaded();

var book = _jsonData.Books!.FirstOrDefault(b => string.Equals(b.Title, bookTitle, StringComparison.OrdinalIgnoreCase));
if (book == null)
{
Console.WriteLine($"No book found with the title \"{bookTitle}\".");
return ConsoleState.PatronDetails;
}

var bookItem = _jsonData.BookItems!.FirstOrDefault(bi => bi.BookId == book.Id);
if (bookItem == null)
{
Console.WriteLine($"No book item found for the title \"{book.Title}\".");
return ConsoleState.PatronDetails;
}

var loan = _jsonData.Loans!.FirstOrDefault(l => l.BookItemId == bookItem.Id && l.ReturnDate == null);
if (loan == null)
{
Console.WriteLine($"\"{book.Title}\" is available for loan.");
}
else
{
Console.WriteLine($"\"{book.Title}\" is on loan to another patron. The return due date is {loan.DueDate}.");
}

return ConsoleState.PatronDetails;
}

async Task<ConsoleState> LoanDetails()
{
Console.WriteLine($"Book title: {selectedLoanDetails.BookItem!.Book!.Title}");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using NSubstitute;
using Library.ApplicationCore;
using Library.ApplicationCore.Entities;
using Library.Infrastructure.Data;
using Microsoft.Extensions.Configuration;
using Xunit;

namespace UnitTests.Infrastructure.JsonLoanRepositoryTests;

public class GetLoanTest
{
private readonly ILoanRepository _mockLoanRepository;
private readonly JsonLoanRepository _jsonLoanRepository;
private readonly IConfiguration _configuration;
private readonly JsonData _jsonData;

public GetLoanTest()
{
_mockLoanRepository = Substitute.For<ILoanRepository>();
_configuration = new ConfigurationBuilder().Build();
_jsonData = new JsonData(_configuration);
_jsonLoanRepository = new JsonLoanRepository(_jsonData);
}

[Fact(DisplayName = "JsonLoanRepository.GetLoan: Returns loan when loan ID is found")]
public async Task GetLoan_ReturnsLoanWhenLoanIdIsFound()
{
// Arrange
var loanId = 1; // Use a loan ID that exists in the Loans.json file
var expectedLoan = new Loan
{
Id = loanId,
BookItemId = 17,
PatronId = 22,
LoanDate = DateTime.Parse("2023-12-08T00:40:43.1808862"),
DueDate = DateTime.Parse("2023-12-22T00:40:43.1808862"),
ReturnDate = null
};

_mockLoanRepository.GetLoan(loanId).Returns(expectedLoan);

// Act
var actualLoan = await _jsonLoanRepository.GetLoan(loanId);

// Assert
Assert.NotNull(actualLoan);
Assert.Equal(expectedLoan.Id, actualLoan?.Id);
}

[Fact(DisplayName = "JsonLoanRepository.GetLoan: Returns null when loan ID is not found")]
public async Task GetLoan_ReturnsNullWhenLoanIdIsNotFound()
{
// Arrange
var loanId = 999; // Use a loan ID that does not exist in the Loans.json file

_mockLoanRepository.GetLoan(loanId).Returns((Loan?)null);

// Act
var actualLoan = await _jsonLoanRepository.GetLoan(loanId);

// Assert
Assert.Null(actualLoan);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@

<ItemGroup>
<ProjectReference Include="..\..\src\Library.ApplicationCore\Library.ApplicationCore.csproj" />
<ProjectReference Include="..\..\src\Library.Infrastructure\Library.Infrastructure.csproj" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\src\Library.Console\Json\**\*">
<Link>Json\%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<None Include="..\..\src\Library.Console\Json\**\*">
<Link>Json\%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>