Skip to content

Commit

Permalink
Showing 21 changed files with 229 additions and 210 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#nullable enable
using System;
using System.Net.Http;
using GovUk.Education.ExploreEducationStatistics.Common.Extensions;
using Xunit;
@@ -34,6 +35,13 @@ public static T AssertOk<T>(this HttpResponseMessage message, T expectedBody)
return message.AssertBodyEqualTo(expectedBody);
}

public static T AssertCreated<T>(this HttpResponseMessage message, T expectedBody, string expectedLocation)
{
Assert.Equal(Created, message.StatusCode);
Assert.Equal(new Uri(expectedLocation), message.Headers.Location);
return message.AssertBodyEqualTo(expectedBody);
}

public static void AssertNoContent(this HttpResponseMessage message)
{
Assert.Equal(NoContent, message.StatusCode);
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
using GovUk.Education.ExploreEducationStatistics.Common.Model;
using GovUk.Education.ExploreEducationStatistics.Common.Tests.Extensions;
using GovUk.Education.ExploreEducationStatistics.Common.Tests.Fixtures;
using GovUk.Education.ExploreEducationStatistics.Common.Tests.Utils;
using GovUk.Education.ExploreEducationStatistics.Common.Utils;
using GovUk.Education.ExploreEducationStatistics.Data.Api.Requests;
using GovUk.Education.ExploreEducationStatistics.Data.Api.Services.Interfaces;
@@ -18,8 +19,6 @@
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
using static GovUk.Education.ExploreEducationStatistics.Common.Tests.Utils.MockUtils;
using static Moq.MockBehavior;

namespace GovUk.Education.ExploreEducationStatistics.Data.Api.Tests.Controllers;

@@ -36,9 +35,12 @@ public PermalinkControllerTests(TestApplicationFactory<TestStartup> testApp)
public async Task CreatePermalink()
{
var createRequest = new PermalinkCreateRequest();
var expectedResult = new PermalinkViewModel();
var expectedResult = new PermalinkViewModel
{
Id = Guid.NewGuid()
};

var permalinkService = new Mock<IPermalinkService>(Strict);
var permalinkService = new Mock<IPermalinkService>(MockBehavior.Strict);

permalinkService
.Setup(s => s.CreatePermalink(It.Is<PermalinkCreateRequest>(r => r.IsDeepEqualTo(createRequest)),
@@ -49,38 +51,12 @@ public async Task CreatePermalink()
.CreateClient();

var response = await client.PostAsync(
requestUri: "/api/permalink-snapshot",
content: new JsonNetContent(createRequest));

VerifyAllMocks(permalinkService);

response.AssertOk(expectedResult);
}

[Fact]
public async Task CreatePermalink_WithReleaseId()
{
var releaseId = Guid.NewGuid();
var createRequest = new PermalinkCreateRequest();
var expectedResult = new PermalinkViewModel();

var permalinkService = new Mock<IPermalinkService>(Strict);

permalinkService
.Setup(s => s.CreatePermalink(releaseId, It.Is<PermalinkCreateRequest>(r => r.IsDeepEqualTo(createRequest)),
It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedResult);

var client = SetupApp(permalinkService: permalinkService.Object)
.CreateClient();

var response = await client.PostAsync(
requestUri: $"/api/permalink-snapshot/release/{releaseId}",
requestUri: "/api/permalink",
content: new JsonNetContent(createRequest));

VerifyAllMocks(permalinkService);
MockUtils.VerifyAllMocks(permalinkService);

response.AssertOk(expectedResult);
response.AssertCreated(expectedResult, $"http://localhost/api/permalink/{expectedResult.Id}");
}

[Fact]
@@ -92,7 +68,7 @@ public async Task GetPermalink()
Id = permalinkId
};

var permalinkService = new Mock<IPermalinkService>(Strict);
var permalinkService = new Mock<IPermalinkService>(MockBehavior.Strict);

permalinkService
.Setup(s => s.GetPermalink(permalinkId, It.IsAny<CancellationToken>()))
@@ -102,14 +78,14 @@ public async Task GetPermalink()
.CreateClient();

var response = await client.GetAsync(
uri: $"/api/permalink-snapshot/{permalinkId}",
uri: $"/api/permalink/{permalinkId}",
headers: new Dictionary<string, string>
{
{ HeaderNames.Accept, "application/json" }
}
);

VerifyAllMocks(permalinkService);
MockUtils.VerifyAllMocks(permalinkService);

response.AssertOk(permalink);
}
@@ -119,7 +95,7 @@ public async Task GetPermalink_NotFound()
{
var permalinkId = Guid.NewGuid();

var permalinkService = new Mock<IPermalinkService>(Strict);
var permalinkService = new Mock<IPermalinkService>(MockBehavior.Strict);

permalinkService
.Setup(s => s.GetPermalink(permalinkId, It.IsAny<CancellationToken>()))
@@ -129,14 +105,14 @@ public async Task GetPermalink_NotFound()
.CreateClient();

var response = await client.GetAsync(
uri: $"/api/permalink-snapshot/{permalinkId}",
uri: $"/api/permalink/{permalinkId}",
headers: new Dictionary<string, string>
{
{ HeaderNames.Accept, "application/json" }
}
);

VerifyAllMocks(permalinkService);
MockUtils.VerifyAllMocks(permalinkService);

response.AssertNotFound();
}
@@ -145,7 +121,7 @@ public async Task GetPermalink_NotFound()
public async Task GetPermalink_Csv()
{
var permalinkId = Guid.NewGuid();
var permalinkService = new Mock<IPermalinkService>(Strict);
var permalinkService = new Mock<IPermalinkService>(MockBehavior.Strict);

permalinkService
.Setup(s => s
@@ -159,14 +135,14 @@ public async Task GetPermalink_Csv()
.CreateClient();

var response = await client.GetAsync(
uri: $"/api/permalink-snapshot/{permalinkId}",
uri: $"/api/permalink/{permalinkId}",
headers: new Dictionary<string, string>
{
{ HeaderNames.Accept, ContentTypes.Csv }
}
);

VerifyAllMocks(permalinkService);
MockUtils.VerifyAllMocks(permalinkService);

response.AssertOk("Test csv");
}
@@ -176,7 +152,7 @@ public async Task GetPermalink_Csv_NotFound()
{
var permalinkId = Guid.NewGuid();

var permalinkService = new Mock<IPermalinkService>(Strict);
var permalinkService = new Mock<IPermalinkService>(MockBehavior.Strict);

permalinkService
.Setup(s => s
@@ -187,14 +163,14 @@ public async Task GetPermalink_Csv_NotFound()
.CreateClient();

var response = await client.GetAsync(
uri: $"/api/permalink-snapshot/{permalinkId}",
uri: $"/api/permalink/{permalinkId}",
headers: new Dictionary<string, string>
{
{ HeaderNames.Accept, ContentTypes.Csv }
}
);

VerifyAllMocks(permalinkService);
MockUtils.VerifyAllMocks(permalinkService);

response.AssertNotFound();
}
@@ -204,15 +180,18 @@ public async Task GetPermalink_InvalidIdReturnsNotFound()
{
var client = SetupApp().CreateClient();

var response = await client.GetAsync("/api/permalink-snapshot/not-a-guid");
var response = await client.GetAsync("/api/permalink/not-a-guid");

response.AssertNotFound();
}

private WebApplicationFactory<TestStartup> SetupApp(IPermalinkService? permalinkService = null)
{
return _testApp.ConfigureServices(
services => { services.AddTransient(_ => permalinkService ?? Mock.Of<IPermalinkService>(Strict)); }
services =>
{
services.AddTransient(_ => permalinkService ?? Mock.Of<IPermalinkService>(MockBehavior.Strict));
}
);
}
}
Original file line number Diff line number Diff line change
@@ -188,18 +188,6 @@ public async Task CreatePermalink_WithoutReleaseId()

var footnoteViewModels = FootnotesViewModelBuilder.BuildFootnotes(footnotes);

var request = new PermalinkCreateRequest
{
Configuration = new TableBuilderConfiguration
{
TableHeaders = new TableHeaders()
},
Query =
{
SubjectId = subject.Id
}
};

var tableResult = new TableBuilderResultViewModel
{
SubjectMeta = new SubjectResultMetaViewModel
@@ -278,6 +266,19 @@ public async Task CreatePermalink_WithoutReleaseId()
}
};

var request = new PermalinkCreateRequest
{
ReleaseId = null,
Configuration = new TableBuilderConfiguration
{
TableHeaders = new TableHeaders()
},
Query =
{
SubjectId = subject.Id
}
};

var publicBlobStorageService = new Mock<IPublicBlobStorageService>(MockBehavior.Strict);

Guid expectedPermalinkId;
@@ -519,18 +520,6 @@ public async Task CreatePermalink_WithReleaseId()

var footnoteViewModels = FootnotesViewModelBuilder.BuildFootnotes(footnotes);

var request = new PermalinkCreateRequest
{
Configuration = new TableBuilderConfiguration
{
TableHeaders = new TableHeaders()
},
Query =
{
SubjectId = subject.Id
}
};

var tableResult = new TableBuilderResultViewModel
{
SubjectMeta = new SubjectResultMetaViewModel
@@ -609,6 +598,19 @@ public async Task CreatePermalink_WithReleaseId()
}
};

var request = new PermalinkCreateRequest
{
ReleaseId = release.Id,
Configuration = new TableBuilderConfiguration
{
TableHeaders = new TableHeaders()
},
Query =
{
SubjectId = subject.Id
}
};

var publicBlobStorageService = new Mock<IPublicBlobStorageService>(MockBehavior.Strict);

Guid expectedPermalinkId;
@@ -705,7 +707,7 @@ public async Task CreatePermalink_WithReleaseId()
permalinkCsvMetaService: permalinkCsvMetaService.Object,
tableBuilderService: tableBuilderService.Object);

var result = (await service.CreatePermalink(release.Id, request)).AssertRight();
var result = (await service.CreatePermalink(request)).AssertRight();

MockUtils.VerifyAllMocks(
publicBlobStorageService,
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ public PermalinkController(IPermalinkService permalinkService)
_permalinkService = permalinkService;
}

[HttpGet("permalink-snapshot/{permalinkId:guid}")]
[HttpGet("permalink/{permalinkId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Produces("application/json", "text/csv")]
@@ -58,27 +58,19 @@ public async Task GetPermalink(Guid permalinkId,
await result.ExecuteResultAsync(ControllerContext);
}

[HttpPost("permalink-snapshot")]
[ProducesResponseType(StatusCodes.Status200OK)]
[HttpPost("permalink")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<PermalinkViewModel>> CreatePermalink(
[FromBody] PermalinkCreateRequest request,
CancellationToken cancellationToken = default)
{
return await _permalinkService
.CreatePermalink(request, cancellationToken)
.HandleFailuresOrOk();
}

[HttpPost("permalink-snapshot/release/{releaseId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<PermalinkViewModel>> CreatePermalink(
Guid releaseId,
[FromBody] PermalinkCreateRequest request,
CancellationToken cancellationToken = default)
{
return await _permalinkService
.CreatePermalink(releaseId, request, cancellationToken)
.HandleFailuresOrOk();
.HandleFailuresOr(permalink => CreatedAtAction(nameof(GetPermalink), new
{
permalinkId = permalink.Id
}, permalink));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#nullable enable
using System;
using GovUk.Education.ExploreEducationStatistics.Common.Model.Data;
using GovUk.Education.ExploreEducationStatistics.Common.Model.Data.Query;

namespace GovUk.Education.ExploreEducationStatistics.Data.Api.Requests;

public record PermalinkCreateRequest
{
public Guid? ReleaseId { get; init; }

public TableBuilderConfiguration Configuration { get; init; } = new();

public ObservationQueryContext Query { get; init; } = new();
Original file line number Diff line number Diff line change
@@ -15,10 +15,6 @@ public interface IPermalinkService
Task<Either<ActionResult, PermalinkViewModel>> CreatePermalink(PermalinkCreateRequest request,
CancellationToken cancellationToken = default);

Task<Either<ActionResult, PermalinkViewModel>> CreatePermalink(Guid releaseId,
PermalinkCreateRequest request,
CancellationToken cancellationToken = default);

Task<Either<ActionResult, PermalinkViewModel>> GetPermalink(Guid permalinkId,
CancellationToken cancellationToken = default);

Loading

0 comments on commit c38a080

Please sign in to comment.