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
76 changes: 76 additions & 0 deletions .github/workflows/AareonTechnicalTest20220120110002.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Build and deploy .NET Core application to windows webapp AareonTechnicalTest20220120110002 with API Management Service AareonTechnicalTestapi
on:
push:
branches:
- completed_test
env:
AZURE_WEBAPP_NAME: AareonTechnicalTest20220120110002
DOTNET_CORE_VERSION: 6.0.x
WORKING_DIRECTORY: AareonTechnicalTest
CONFIGURATION: Release
AZURE_WEBAPP_PACKAGE_PATH: AareonTechnicalTest/publish
AZURE_APIM_RESOURCE_PATH: /
AZURE_APIM_RESOURCEGROUP: AareonTechnicalTest20220120105445ResourceGroup
AZURE_APIM_SERVICENAME: AareonTechnicalTestapi
AZURE_APIM_API_ID: AareonTechnicalTest
AZURE_APIM_APPSERVICEURL: https://aareontechnicaltest20220120110002.azurewebsites.net
SWASHBUCLE_ASPNET_CORE_CLI_PACKAGE_VERSION: 5.6.3
SWASHBUCKLE_DOTNET_CORE_VERSION: 3.1.x
API_IMPORT_SPECIFICATION_PATH: AareonTechnicalTest/publish/swagger.json
API_IMPORT_DLL: AareonTechnicalTest/publish/AareonTechnicalTest.dll
API_IMPORT_VERSION: v1
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.DOTNET_CORE_VERSION }}
- name: Setup SwashBuckle .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.SWASHBUCKLE_DOTNET_CORE_VERSION }}
- name: Restore
run: dotnet restore ${{ env.WORKING_DIRECTORY }}
- name: Build
run: dotnet build ${{ env.WORKING_DIRECTORY }} --configuration ${{ env.CONFIGURATION }} --no-restore
- name: Test
run: dotnet test ${{ env.WORKING_DIRECTORY }} --no-build
- name: Publish
run: dotnet publish ${{ env.WORKING_DIRECTORY }} --configuration ${{ env.CONFIGURATION }} --no-build --output ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
- name: Install Swashbuckle CLI .NET Global Tool
run: dotnet tool install --global Swashbuckle.AspNetCore.Cli --version ${{ env.SWASHBUCLE_ASPNET_CORE_CLI_PACKAGE_VERSION }}
working-directory: ${{ env.WORKING_DIRECTORY }}
- name: Generate Open API Specification Document
run: swagger tofile --output "${{ env.API_IMPORT_SPECIFICATION_PATH }}" "${{ env.API_IMPORT_DLL }}" "${{ env.API_IMPORT_VERSION }}"
- name: Publish Artifacts
uses: actions/upload-artifact@v1.0.0
with:
name: webapp
path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
deploy:
runs-on: windows-latest
needs: build
steps:
- name: Download artifact from build job
uses: actions/download-artifact@v2
with:
name: webapp
path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
- name: Deploy to Azure WebApp
uses: azure/webapps-deploy@v2
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
publish-profile: ${{ secrets.AareonTechnicalTest20220120110002_4333 }}
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AareonTechnicalTestapi_spn }}
- name: Import API into Azure API Management
run: az apim api import --path "${{ env.AZURE_APIM_RESOURCE_PATH }}" --resource-group "${{ env.AZURE_APIM_RESOURCEGROUP }}" --service-name "${{ env.AZURE_APIM_SERVICENAME }}" --api-id "${{ env.AZURE_APIM_API_ID }}" --service-url "${{ env.AZURE_APIM_APPSERVICEURL }}" --specification-path "${{ env.API_IMPORT_SPECIFICATION_PATH }}" --specification-format OpenApi --subscription-required false
- name: logout
run: >
az logout
24 changes: 24 additions & 0 deletions AareonTechnicalTest.Tests/AareonTechnicalTest.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="NSubstitute" Version="4.2.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\AareonTechnicalTest\AareonTechnicalTest.csproj" />
</ItemGroup>

</Project>
102 changes: 102 additions & 0 deletions AareonTechnicalTest.Tests/NotesServiceShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using AareonTechnicalTest.Models;
using AareonTechnicalTest.Repositories;
using AareonTechnicalTest.Services;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute;
using System.Threading.Tasks;

namespace AareonTechnicalTest.Tests
{
[TestClass]
public class NotesServiceShould
{
private INoteRepository? _noteRepository;
private NoteService? _noteService;
private IPersonRepository? _personRepository;

[TestInitialize]
public void Initialise()
{
_noteRepository = Substitute.For<INoteRepository>();
_personRepository = Substitute.For<IPersonRepository>();

_noteService = new NoteService(_noteRepository, _personRepository);
}

[TestMethod]
public async Task FailDeleteNoteWhenNoteNotFound()
{
var personId = 1;
var noteId = 1;

Note? noteMock = null;
_noteRepository!.FindNoteAsync(noteId).Returns(noteMock);

var response = await _noteService!.DeleteNoteAsync(personId, noteId);
var x = response
.Should()
.BeOfType<NotFoundResult>();
}

[TestMethod]
public async Task FailDeleteNoteWhenPersonNotFound()
{
var personId = 1;
var noteId = 1;

Note? noteMock = new Note { Id = noteId };
_noteRepository!.FindNoteAsync(noteId).Returns(noteMock);

Person? personMock = null;
_personRepository!.FindPersonAsync(noteId).Returns(personMock);

var response = await _noteService!.DeleteNoteAsync(personId, noteId);
var x = response
.Should()
.BeOfType<UnprocessableEntityObjectResult>();
}

[TestMethod]
public async Task FailDeleteNoteWhenPersonIsNotAdmin()
{
var personId = 1;
var noteId = 1;

Note? noteMock = new Note { Id = noteId };
_noteRepository!.FindNoteAsync(noteId).Returns(noteMock);

Person? personMock = new Person { Id = personId, IsAdmin = false };
_personRepository!.FindPersonAsync(noteId).Returns(personMock);

var response = await _noteService!.DeleteNoteAsync(personId, noteId);
var x = response
.Should()
.BeOfType<UnprocessableEntityObjectResult>();

var problemDetails = x.Subject.Value.Should().BeOfType<ProblemDetails>().Which;

problemDetails.Detail.Should().Be($"The person with ID {personId} is not an administrator.", because: "The person was not an administrator");
}


[TestMethod]
public async Task DeleteNoteWhenPersonIsAdmin()
{
var personId = 1;
var noteId = 1;

Note? noteMock = new Note { Id = noteId };
_noteRepository!.FindNoteAsync(noteId).Returns(noteMock);

Person? personMock = new Person { Id = personId, IsAdmin = true };
_personRepository!.FindPersonAsync(noteId).Returns(personMock);

var response = await _noteService!.DeleteNoteAsync(personId, noteId);
var x = response
.Should()
.BeOfType<NoContentResult>();
}
}
}
12 changes: 9 additions & 3 deletions AareonTechnicalTest.sln
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31624.102
# Visual Studio Version 17
VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AareonTechnicalTest", "AareonTechnicalTest\AareonTechnicalTest.csproj", "{1FB831BF-946F-4526-AB25-E5CAFC6A8E4F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AareonTechnicalTest", "AareonTechnicalTest\AareonTechnicalTest.csproj", "{1FB831BF-946F-4526-AB25-E5CAFC6A8E4F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AareonTechnicalTest.Tests", "AareonTechnicalTest.Tests\AareonTechnicalTest.Tests.csproj", "{E46C0B0C-69A8-432B-9ABB-086E0B62740A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -15,6 +17,10 @@ Global
{1FB831BF-946F-4526-AB25-E5CAFC6A8E4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FB831BF-946F-4526-AB25-E5CAFC6A8E4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FB831BF-946F-4526-AB25-E5CAFC6A8E4F}.Release|Any CPU.Build.0 = Release|Any CPU
{E46C0B0C-69A8-432B-9ABB-086E0B62740A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E46C0B0C-69A8-432B-9ABB-086E0B62740A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E46C0B0C-69A8-432B-9ABB-086E0B62740A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E46C0B0C-69A8-432B-9ABB-086E0B62740A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
17 changes: 11 additions & 6 deletions AareonTechnicalTest/AareonTechnicalTest.csproj
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.11">
<PackageReference Include="Audit.NET" Version="19.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.1" />
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.2.22" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions AareonTechnicalTest/ApplicationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public ApplicationContext(DbContextOptions<ApplicationContext> options)

public virtual DbSet<Ticket> Tickets { get; set; }

public virtual DbSet<Note> Notes { get; set; }

public string DatabasePath { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder options)
Expand All @@ -29,6 +31,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
{
PersonConfig.Configure(modelBuilder);
TicketConfig.Configure(modelBuilder);
NoteConfig.Configure(modelBuilder);
}
}
}
50 changes: 50 additions & 0 deletions AareonTechnicalTest/Controllers/NotesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using AareonTechnicalTest.Models;
using AareonTechnicalTest.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace AareonTechnicalTest.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class NotesController : ControllerBase
{
private readonly INoteService _noteService;

public NotesController(INoteService noteService)
{
_noteService = noteService;
}

[HttpGet]
public async Task<ActionResult<IEnumerable<Note>>> GetNotes()
{
return await _noteService.GetNotesAsync();
}

[HttpGet("{id}")]
public async Task<ActionResult<Note>> GetNote(int id)
{
return await _noteService.GetNoteAsync(id);
}

[HttpPut("{id}")]
public async Task<IActionResult> PutNote(int id, Note note)
{
return await _noteService.PutNoteAsync(id, note);
}

[HttpPost]
public async Task<ActionResult<Note>> PostNote(Note note)
{
return await _noteService.PostNoteAsync(note);
}

[HttpDelete("{id}")]
public async Task<IActionResult> DeleteNote(int personId, int id)
{
return await _noteService.DeleteNoteAsync(personId, id);
}
}
}
50 changes: 50 additions & 0 deletions AareonTechnicalTest/Controllers/TicketsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using AareonTechnicalTest.Models;
using AareonTechnicalTest.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace AareonTechnicalTest.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TicketsController : ControllerBase
{
private readonly ITicketService _ticketService;

public TicketsController(ITicketService ticketService)
{
_ticketService = ticketService;
}

[HttpGet]
public async Task<ActionResult<IEnumerable<Ticket>>> GetTickets()
{
return await _ticketService.GetTicketsAsync();
}

[HttpGet("{id}")]
public async Task<ActionResult<Ticket>> GetTicket(int id)
{
return await _ticketService.GetTicketAsync(id);
}

[HttpPut("{id}")]
public async Task<IActionResult> PutTicket(int id, Ticket ticket)
{
return await _ticketService.PutTicketAsync(id, ticket);
}

[HttpPost]
public async Task<ActionResult<Ticket>> PostTicket(Ticket ticket)
{
return await _ticketService.PostTicketAsync(ticket);
}

[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTicket(int id)
{
return await _ticketService.DeleteTicketAsync(id);
}
}
}
Loading