Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

31 removing contract data from admin page #42

Merged
merged 9 commits into from
Apr 10, 2022
6 changes: 6 additions & 0 deletions src/Application/Contracts/ContractService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ public void Add(Contract contract)

_repo.Add(contract);
}

/// <inheritdoc />
public bool Remove(Guid id)
{
return _repo.Remove(id);
}
}
7 changes: 7 additions & 0 deletions src/Application/Contracts/IContractRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,11 @@ public interface IContractRepository
/// </summary>
/// <param name="contract">The new contract instance.</param>
void Add(Contract contract);

/// <summary>
/// Removes the contract with the given ID.
/// </summary>
/// <param name="id">The id of the contract to be removed.</param>
/// <returns>If the removal was successful.</returns>
public bool Remove(Guid id);
}
7 changes: 7 additions & 0 deletions src/Application/Contracts/IContractService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,11 @@ public interface IContractService
/// </summary>
/// <param name="contract">The new contract.</param>
void Add(Contract contract);

/// <summary>
/// Removes the specified contract.
/// </summary>
/// <param name="id">The id of the contract to be removed.</param>
/// <returns>Whether the removal was successful.</returns>
bool Remove(Guid id);
}
1 change: 0 additions & 1 deletion src/Client/Pages/Admin/AdminPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@
{
_contractList.Add(contract);
}

}
14 changes: 12 additions & 2 deletions src/Client/Pages/Admin/ContractList.razor
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ else
<div class="list-group">
@foreach (var contract in _contracts)
{
<ContractListItem Name=@contract.Name/>
<ContractListItem Contract=@contract OnContractRemoved=@OnContractRemoved/>
}
</div>
}
Expand All @@ -39,6 +39,16 @@ else
InvokeAsync(StateHasChanged);
}


/// <summary>
/// Removes a contract from the list.
/// </summary>
/// <param name="contract">The contract to remove.</param>
private void OnContractRemoved(Contract contract)
{
// Using null forgiving operator because because _contracts
// can not be null when remove button is pressed.
_contracts!.Remove(contract);
InvokeAsync(StateHasChanged);
}
}

29 changes: 26 additions & 3 deletions src/Client/Pages/Admin/ContractListItem.razor
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
<div id="@Name" class="list-group-item" style="max-width: 50%"> @Name </div>
@using Domain.Contracts
@inject HttpClient _http

<div id="@Contract.Name" class="list-group-item d-flex justify-content-between" style="max-width: 50%">
@Contract.Name

<button type="button" class="btn btn-danger" @onclick="RemoveContract">
<span class="oi oi-trash"></span>
</button>
</div>


@code {
/// <summary>
/// Called when a contract has been removed successfully.
/// </summary>
[Parameter]
public EventCallback<Contract> OnContractRemoved { get; set; } = EventCallback<Contract>.Empty;


/// <summary>
/// Name of the company.
/// The contract.
/// </summary>
[Parameter, EditorRequired,]
public string? Name { get; set; }
public Contract Contract { get; set; } = new();

private async Task RemoveContract()
{
HttpResponseMessage response = await _http.DeleteAsync($"api/v1/Contracts/{Contract.Id}");
if (response.IsSuccessStatusCode)
{
await OnContractRemoved.InvokeAsync(Contract);
}
}
}
2 changes: 1 addition & 1 deletion src/Domain/Contracts/Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class Contract
/// <summary>
/// Gets the unique identifier.
/// </summary>
public Guid Id { get; } = Guid.NewGuid();
public Guid Id { get; init; } = Guid.NewGuid();

/// <summary>
/// Gets or sets the name of the contract supplier.
Expand Down
8 changes: 7 additions & 1 deletion src/Infrastructure/Contracts/FakeContractRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Infrastructure.Contracts;
/// </summary>
public class FakeContractRepository : IContractRepository
{
private readonly ICollection<Contract> _contracts;
private readonly List<Contract> _contracts;
JacobBredin marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Creates a fake contract for SJ.
Expand All @@ -27,4 +27,10 @@ public void Add(Contract contract)
{
_contracts.Add(contract);
}

/// <inheritdoc />
public bool Remove(Guid id)
{
return _contracts.RemoveAll(o => o.Id == id) > 0;
}
}
13 changes: 13 additions & 0 deletions src/Server/Controllers/ContractsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,17 @@ public IActionResult CreateContract(Contract contract)

return Ok();
}

/// <summary>
/// Removes the specified contract.
/// </summary>
/// <param name="id">Id of the contract to be removed.</param>
/// <returns>If the contract was successfully removed.</returns>
[HttpDelete("{id:guid}")]
public IActionResult Remove(Guid id)
{
return _contracts.Remove(id) ?
Ok() :
NotFound();
}
}
29 changes: 29 additions & 0 deletions tests/Application.Tests/Contracts/ContractServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,33 @@ public void AddingContract_DoesNotThrow_IfIDIsUnique()
// Assert
add.Should().NotThrow();
}

[Fact]
public void RemovingContract_DoesReturnTrue_WhenAContractExists()
{
// Arrange
var contract = new Contract();
_mockRepo.Setup(repository => repository.Remove(contract.Id)).Returns(true);

// Act
bool actual = _cut.Remove(contract.Id);

// // Assert
actual.Should().BeTrue();
}

[Fact]
public void RemovingContract_DoesReturnFalse_WhenNoContractsExists()
{
// Arrange
_mockRepo.Setup(repository => repository.All).Returns(new List<Contract>());

var id = Guid.NewGuid();

// Act
bool actual = _cut.Remove(id);

// Assert
actual.Should().BeFalse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Linq;
using Infrastructure.Contracts;

namespace Infrastructure.Tests.Contracts;
public class FakeContractRepositoryTests
{
private readonly FakeContractRepository _cut;

public FakeContractRepositoryTests()
{
_cut = new FakeContractRepository();
}

[Fact]
public void RemoveContract_ReturnsFalse_WhenContractDoesNotExist()
{
// Arrange
var id = Guid.NewGuid();

// Act
bool actual = _cut.Remove(id);

// Assert
actual.Should().BeFalse();
}

[Fact]
public void RemoveContract_ReturnTrue_WhenContractExists()
{
// Arrange
Guid id = _cut.All.First().Id;

// Act
bool actual = _cut.Remove(id);

// Assert
actual.Should().BeTrue();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Client.Pages.Admin;
using Domain.Contracts;

namespace Presentation.Tests.Client.Pages.Admin;

Expand All @@ -21,15 +22,16 @@ public void ContractListItem_ContainsTitle()
{
// Arrange
const string name = "SJ";
var contract = new Contract() { Name = name };

static void ParameterBuilder(ComponentParameterCollectionBuilder<ContractListItem> parameters) =>
parameters.Add(property => property.Name, name);
void ParameterBuilder(ComponentParameterCollectionBuilder<ContractListItem> parameters) =>
parameters.Add(property => property.Contract, contract);

// Act
IRenderedComponent<ContractListItem> cut =
_context.RenderComponent<ContractListItem>(ParameterBuilder);

// Assert
cut.Find($"#{name}").TextContent.Should().Contain(name);
cut.Find($"#{contract.Name}").TextContent.Should().Contain(name);
}
}
24 changes: 24 additions & 0 deletions tests/Presentation.Tests/Client/Pages/Admin/ContractListTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Client.Pages.Admin;

using Domain.Contracts;
using Microsoft.AspNetCore.Components.Web;

namespace Presentation.Tests.Client.Pages.Admin;

Expand Down Expand Up @@ -58,4 +59,27 @@ public void AddingContract_DoesNotThrow_BeforeContractsAreFetched()
// Assert
add.Should().NotThrow();
}

[Fact]
public async Task RemovingContract_RendersWithoutTheContractAsync()
{
// Arrange
var firstContract = new Contract() { Name = "first", };
Contract[] contracts = { firstContract, new Contract() { Name = "Second", }, };
MockHttp.When("/api/v1/Contracts/All").RespondJson(contracts);
MockHttp.When(HttpMethod.Delete, $"/api/v1/Contracts/{firstContract.Id}").Respond(req => new HttpResponseMessage(HttpStatusCode.OK));

IRenderedComponent<ContractList> cut = Context.RenderComponent<ContractList>();
const string removeButton = ".btn.btn-danger";
cut.WaitForElement(removeButton);

// Act
await cut.Find(removeButton).ClickAsync(new MouseEventArgs()).ConfigureAwait(false);
cut.WaitForState(() => cut.FindAll(removeButton).Count == 1);

// Assert
Expression<Func<IElement, bool>>
elementWithNewName = contract => contract.TextContent.Contains(firstContract.Name);
cut.FindAll(".list-group-item").Should().NotContain(elementWithNewName);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Application.Contracts;

using Domain.Contracts;
using Microsoft.AspNetCore.Mvc;

namespace Presentation.Tests.Server.Controllers;

Expand Down Expand Up @@ -28,4 +29,46 @@ public void Get_AllContracts()
// Assert
actualWeather.Should().BeEquivalentTo(fakeContracts);
}

[Fact]
public void Remove_ReturnsOk_WhenIDExists()
{
// Arrange
var id = Guid.NewGuid();
_mockContracts.Setup(service => service.Remove(id)).Returns(true);

// Act
IActionResult actual = _cut.Remove(id);

// Assert
actual.Should().BeOfType<OkResult>();
}

[Fact]
public void Remove_CallsContractService_WhenIDExists()
{
// Arrange
var id = Guid.NewGuid();
_mockContracts.Setup(service => service.Remove(id)).Returns(true);

// Act
IActionResult actual = _cut.Remove(id);

// Assert
_mockContracts.Verify(o => o.Remove(id), Times.Once);
}

[Fact]
public void Remove_ReturnsNotFound_WhenIDDoesNotExist()
{
// Arrange
var id = Guid.NewGuid();
_mockContracts.Setup(service => service.Remove(id)).Returns(false);

// Act
IActionResult actual = _cut.Remove(id);

// Assert
actual.Should().BeOfType<NotFoundResult>();
}
}