Skip to content

Commit

Permalink
🔀Merge pull request #11 from ERNI-Academy/feature/AddSonarCloud
Browse files Browse the repository at this point in the history
✅ Add unit tests
  • Loading branch information
Rabosa616 authored May 30, 2022
2 parents b238423 + c51dbfd commit 0595f65
Show file tree
Hide file tree
Showing 30 changed files with 1,296 additions and 112 deletions.
47 changes: 38 additions & 9 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,53 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0


- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 1.11

- name: Install dotnet SonarCloud scanner
shell: powershell

- name: Cache SonarCloud packages
uses: actions/cache@v1
with:
path: ~\sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar

- name: Cache SonarCloud scanner
id: cache-sonar-scanner
uses: actions/cache@v1
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
restore-keys: ${{ runner.os }}-sonar-scanner

- name: Install SonarCloud scanner
if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
shell: pwsh
run: |
dotnet tool install --global dotnet-sonarscanner
New-Item -Path .\.sonar\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: |
dotnet sonarscanner begin /k:"ERNI-Academy_asset-restfullapi-hateoas" /o:"erni-academy" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.dotnet.excludeTestProjects="true"
dotnet restore
dotnet tool install --global dotnet-coverage
.\.sonar\scanner\dotnet-sonarscanner begin /k:"ERNI-Academy_asset-restfullapi-hateoas" /o:"erni-academy" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml
dotnet build --configuration Release
dotnet sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
dotnet-coverage collect 'dotnet test' -f xml -o 'coverage.xml'
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
# shell: pwsh
# run: |
# .\.sonar\scanner\dotnet-sonarscanner begin /k:"erni-academy_asset-restfullapi-hateoas" /o:"erni-academy" /d:sonar.login="${{ secrets.sonar_token }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.dotnet.excludetestprojects="true" /d:sonar.cs.opencover.reportspaths="**\coverage.cobertura.xml" /d:sonar.cs.xunit.reportspaths=testresults/*.trx
# dotnet restore
# dotnet build
# dotnet test --logger "trx;logfilename=unittests.trx" --results-directory testresults /p:collectcoverage=true /p:coverletoutputformat=cobertura /p:coverletoutput=testresults\coverage\ --collect:"xplat code coverage"
# .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.sonar_token }}"

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ bld/

# Visual Studio 2015/2017 cache/options directory
.vs/
.sonarqube
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

Expand Down
11 changes: 10 additions & 1 deletion ERNI.Api.Hateoas.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{4CD75E
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ERNI.Api.Hateoas", "src\ERNI.Api.Hateoas\ERNI.Api.Hateoas.csproj", "{1831AA36-4DD6-4B63-9F26-D32BB91296DB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ERNI.Api.Hateoas.Sample", "sample\ERNI.Api.Hateoas.Sample\ERNI.Api.Hateoas.Sample.csproj", "{73F372C0-815D-4FBA-A6A3-BDD276FDB4EF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ERNI.Api.Hateoas.Sample", "sample\ERNI.Api.Hateoas.Sample\ERNI.Api.Hateoas.Sample.csproj", "{73F372C0-815D-4FBA-A6A3-BDD276FDB4EF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{7649D450-8BA7-4712-AB47-AA8C85EA033D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ERNI.Api.Hateoas.Test", "tests\ERNI.Api.Hateoas.Test\ERNI.Api.Hateoas.Test.csproj", "{ADD95AC6-E353-48C3-AE48-0ED5C617EC74}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -25,13 +29,18 @@ Global
{73F372C0-815D-4FBA-A6A3-BDD276FDB4EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73F372C0-815D-4FBA-A6A3-BDD276FDB4EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73F372C0-815D-4FBA-A6A3-BDD276FDB4EF}.Release|Any CPU.Build.0 = Release|Any CPU
{ADD95AC6-E353-48C3-AE48-0ED5C617EC74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADD95AC6-E353-48C3-AE48-0ED5C617EC74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADD95AC6-E353-48C3-AE48-0ED5C617EC74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADD95AC6-E353-48C3-AE48-0ED5C617EC74}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{1831AA36-4DD6-4B63-9F26-D32BB91296DB} = {AF6D31A1-E1DB-4C74-BD6C-9AB832E4F4BF}
{73F372C0-815D-4FBA-A6A3-BDD276FDB4EF} = {4CD75E9A-1745-44B4-84C8-90A7E76D8138}
{ADD95AC6-E353-48C3-AE48-0ED5C617EC74} = {7649D450-8BA7-4712-AB47-AA8C85EA033D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {76BCDD11-7344-4418-8B17-31D0B010987B}
Expand Down
4 changes: 2 additions & 2 deletions src/ERNI.Api.Hateoas/Dto/PagedList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

public class PagedList<T> : List<T>
{
public int CurrentPage { get; private set; }
public int CurrentPage { get; private set; } = 1;
public int TotalPages { get; private set; }
public int PageSize { get; private set; }
public int PageSize { get; private set; } = 1;
public int TotalCount { get; private set; }

public bool HasPrevious => CurrentPage > 1;
Expand Down
4 changes: 2 additions & 2 deletions src/ERNI.Api.Hateoas/Dto/PaginationFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ public class PaginationFilter
public PaginationFilter()
{
PageNumber = 1;
PageSize = 10;
PageSize = 1;
}
public PaginationFilter(int pageNumber, int pageSize)
{
PageNumber = pageNumber < 1 ? 1 : pageNumber;
PageSize = pageSize > 10 ? 10 : pageSize;
PageSize = pageSize < 1 ? 1 : pageSize;
}
}
14 changes: 10 additions & 4 deletions src/ERNI.Api.Hateoas/Dto/QueryStringParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@

public class QueryStringParameters
{
const int maxPageSize = 50;
public int PageNumber { get; set; } = 1;
private int _pageSize = 1;
private int _pageNumber = 1;

public int PageNumber
{
get { return _pageNumber; }
set { _pageNumber = value < 0 ? 1 : value; }
}


private int _pageSize = 10;
public int PageSize
{
get
Expand All @@ -14,7 +20,7 @@ public int PageSize
}
set
{
_pageSize = value > maxPageSize ? maxPageSize : value;
_pageSize = value <= 0 ? 1 : value;
}
}

Expand Down
74 changes: 38 additions & 36 deletions src/ERNI.Api.Hateoas/Dto/ResponseDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,39 +66,26 @@ public void WriteXml(XmlWriter writer)
}
}

private void WriteXmlElement(string key, object value, XmlWriter writer)
public void Add(string key, object value)
{
writer.WriteStartElement(key);

if (value.GetType() == typeof(List<Link>))
{
foreach (var val in value as List<Link>)
{
writer.WriteStartElement(nameof(Link));
WriteXmlElement(nameof(val.Href), val.Href, writer);
WriteXmlElement(nameof(val.Method), val.Method, writer);
WriteXmlElement(nameof(val.Rel), val.Rel, writer);
writer.WriteEndElement();
}
}
else
{
writer.WriteString(value.ToString());
}

writer.WriteEndElement();
expando.Add(key, value);
}

public void Add(string key, object value)
public void Add(KeyValuePair<string, object> item)
{
expando.Add(key, value);
expando.Add(item);
}

public bool ContainsKey(string key)
{
return expando.ContainsKey(key);
}

public bool Contains(KeyValuePair<string, object> item)
{
return expando.Contains(item);
}

public ICollection<string> Keys
{
get { return expando.Keys; }
Expand All @@ -109,6 +96,11 @@ public bool Remove(string key)
return expando.Remove(key);
}

public bool Remove(KeyValuePair<string, object> item)
{
return expando.Remove(item);
}

public bool TryGetValue(string key, out object value)
{
return expando.TryGetValue(key, out value);
Expand All @@ -131,21 +123,11 @@ public object this[string key]
}
}

public void Add(KeyValuePair<string, object> item)
{
expando.Add(item);
}

public void Clear()
{
expando.Clear();
}

public bool Contains(KeyValuePair<string, object> item)
{
return expando.Contains(item);
}

public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
expando.CopyTo(array, arrayIndex);
Expand All @@ -161,14 +143,34 @@ public bool IsReadOnly
get { return expando.IsReadOnly; }
}

public bool Remove(KeyValuePair<string, object> item)
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return expando.Remove(item);
return expando.GetEnumerator();
}

public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
private void WriteXmlElement(string key, object value, XmlWriter writer)
{
return expando.GetEnumerator();
writer.WriteStartElement(key);

if (value != null)
{
if (value.GetType() == typeof(List<Link>))
{
foreach (var val in value as List<Link>)
{
writer.WriteStartElement(nameof(Link));
WriteXmlElement(nameof(val.Href), val.Href, writer);
WriteXmlElement(nameof(val.Method), val.Method, writer);
WriteXmlElement(nameof(val.Rel), val.Rel, writer);
writer.WriteEndElement();
}
}
else
{
writer.WriteString(value.ToString());
}
}
writer.WriteEndElement();
}

IEnumerator IEnumerable.GetEnumerator()
Expand Down
3 changes: 1 addition & 2 deletions src/ERNI.Api.Hateoas/Extensions/ServicesExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ public static IMvcBuilder AddHateoas(this IMvcBuilder builder, params Assembly[]
builder.Services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
builder.Services.AddScoped<IUrlHelper>(factory =>
{
var actionContext = factory.GetService<IActionContextAccessor>()
.ActionContext;
var actionContext = factory.GetService<IActionContextAccessor>().ActionContext;
return new UrlHelper(actionContext);
});

Expand Down
40 changes: 13 additions & 27 deletions src/ERNI.Api.Hateoas/Formatter/GenericFormatter.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
using ERNI.Api.Hateoas.Dto;
using ERNI.Api.Hateoas.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using System.Reflection;

namespace ERNI.Api.Hateoas.Formatter;

public class GenericFormatter
{
internal IActionContextAccessor contextAccessor;
internal IUrlHelperFactory urlHelperFactory;
internal IDataShaper dataShaper;
internal IActionDescriptorCollectionProvider actionDescriptorProvider;
internal IUrlHelper urlHelper;
internal OutputFormatterWriteContext context;

public GenericFormatter(OutputFormatterWriteContext context)
public GenericFormatter(OutputFormatterWriteContext outputFormatterWriteContext)
{
InitializeServices(context);
context = outputFormatterWriteContext;
dataShaper = GetService<IDataShaper>();
}

internal static IEnumerable<Type> GetLinkGenerators()
Expand All @@ -32,34 +27,25 @@ internal static IEnumerable<Type> GetLinkGenerators()
internal string GetProperties()
{
var properties = string.Empty;
if (contextAccessor.ActionContext.HttpContext.Request.Query.ContainsKey("Fields"))
if (context.HttpContext.Request.Query.ContainsKey("Fields"))
{
properties = contextAccessor.ActionContext.HttpContext.Request.Query["Fields"];
properties = context.HttpContext.Request.Query["Fields"];
}

return properties;
}

internal static T GetService<T>(OutputFormatterWriteContext context)
internal T GetService<T>()
{
return (T)context.HttpContext.RequestServices.GetService(typeof(T));
}

internal static T GetService<T>(OutputFormatterWriteContext context, Type typeOfService)
internal T GetService<T>(Type typeOfService)
{
return (T)context.HttpContext.RequestServices.GetService(typeOfService);
}

internal void InitializeServices(OutputFormatterWriteContext context)
{
contextAccessor = GetService<IActionContextAccessor>(context);
urlHelperFactory = GetService<IUrlHelperFactory>(context);
dataShaper = GetService<IDataShaper>(context);
actionDescriptorProvider = GetService<IActionDescriptorCollectionProvider>(context);
urlHelper = urlHelperFactory.GetUrlHelper(contextAccessor.ActionContext);
}

internal static ILinkGenerator GetLinkGenerator(OutputFormatterWriteContext context)
internal ILinkGenerator GetLinkGenerator()
{
var currentResponseType = context.ObjectType.GenericTypeArguments.FirstOrDefault() != null ?
context.ObjectType.GenericTypeArguments.FirstOrDefault() :
Expand All @@ -69,17 +55,17 @@ internal static ILinkGenerator GetLinkGenerator(OutputFormatterWriteContext cont
var linkGenerators = GetLinkGenerators();
var resultClass = Type.GetType(linkGenerators.FirstOrDefault(i => i.GetInterfaces().Any(j => j.GenericTypeArguments.Any(t => t == currentResponseType))).GetTypeInfo().AssemblyQualifiedName);
var interfacef = resultClass.GetInterface(typeof(ILinkGenerator<>).Name);
var linkGenerator = GetService<ILinkGenerator>(context, interfacef);
var linkGenerator = GetService<ILinkGenerator>(interfacef);
return linkGenerator;
}

internal object GetResultResponse(OutputFormatterWriteContext context)
internal object GetResultResponse()
{
var linkGenerator = GetLinkGenerator(context);
var linkGenerator = GetLinkGenerator();
string properties = GetProperties();

var collection = context.Object as IEnumerable<object>;
object resultResponse = null;
object resultResponse;
if (collection != null)
{
var shapedData = dataShaper.ShapeData(context.Object, properties).ToList();
Expand Down
2 changes: 1 addition & 1 deletion src/ERNI.Api.Hateoas/Formatter/JsonHateoasFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
}

var genericFormatter = new GenericFormatter(context);
var resultResponse = genericFormatter.GetResultResponse(context);
var resultResponse = genericFormatter.GetResultResponse();

var output = JsonConvert.SerializeObject(resultResponse, serializerSettings);
response.ContentType = "application/json+hateoas";
Expand Down
Loading

0 comments on commit 0595f65

Please sign in to comment.