Skip to content

Commit 31e0393

Browse files
committed
Merge branch 'master' into openapi
2 parents c36e798 + 9830302 commit 31e0393

File tree

8 files changed

+257
-4
lines changed

8 files changed

+257
-4
lines changed

Diff for: .config/dotnet-tools.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
]
2222
},
2323
"docfx": {
24-
"version": "2.71.0",
24+
"version": "2.71.1",
2525
"commands": [
2626
"docfx"
2727
]

Diff for: .github/workflows/build.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,13 @@ jobs:
127127
dotnet build --no-restore --configuration Release /p:VersionSuffix=$env:PACKAGE_VERSION_SUFFIX
128128
- name: Test
129129
run: |
130-
dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --logger "GitHubActions;summary.includeSkippedTests=true" -- RunConfiguration.CollectSourceInformation=true DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.DeterministicReport=true
130+
dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --logger "GitHubActions;summary.includeSkippedTests=true"
131131
- name: Upload coverage to codecov.io
132132
if: matrix.os == 'ubuntu-latest'
133133
uses: codecov/codecov-action@v3
134+
with:
135+
fail_ci_if_error: true
136+
verbose: true
134137
- name: Generate packages
135138
shell: pwsh
136139
run: |

Diff for: Build.ps1

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ Write-Host "$(pwsh --version)"
1010
Write-Host "Active .NET SDK: $(dotnet --version)"
1111
Write-Host "Using version suffix: $versionSuffix"
1212

13+
Remove-Item -Recurse -Force artifacts -ErrorAction SilentlyContinue
14+
Remove-Item -Recurse -Force * -Include coverage.cobertura.xml
15+
1316
dotnet tool restore
1417
VerifySuccessExitCode
1518

1619
dotnet build --configuration Release /p:VersionSuffix=$versionSuffix
1720
VerifySuccessExitCode
1821

19-
dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.DeterministicReport=true
22+
dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage"
2023
VerifySuccessExitCode
2124

2225
dotnet reportgenerator -reports:**\coverage.cobertura.xml -targetdir:artifacts\coverage -filefilters:-*.g.cs

Diff for: Directory.Build.props

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<IsPackable>false</IsPackable>
6060
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
6161
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodingGuidelines.ruleset</CodeAnalysisRuleSet>
62+
<RunSettingsFilePath>$(MSBuildThisFileDirectory)tests.runsettings</RunSettingsFilePath>
6263
<JsonApiDotNetCoreVersionPrefix>5.4.1</JsonApiDotNetCoreVersionPrefix>
6364
</PropertyGroup>
6465
</Project>

Diff for: JsonApiDotNetCore.sln

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1313
CodingGuidelines.ruleset = CodingGuidelines.ruleset
1414
CSharpGuidelinesAnalyzer.config = CSharpGuidelinesAnalyzer.config
1515
Directory.Build.props = Directory.Build.props
16+
tests.runsettings = tests.runsettings
1617
EndProjectSection
1718
EndProject
1819
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{026FBC6C-AF76-4568-9B87-EC73457899FD}"

Diff for: test/NoEntityFrameworkTests/TagTests.cs

+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
using System.Net;
2+
using System.Text.Json;
3+
using FluentAssertions;
4+
using JsonApiDotNetCore.Configuration;
5+
using JsonApiDotNetCore.Serialization.Objects;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using NoEntityFrameworkExample.Models;
8+
using TestBuildingBlocks;
9+
using Xunit;
10+
11+
namespace NoEntityFrameworkTests;
12+
13+
public sealed class TagTests : IntegrationTest, IClassFixture<NoLoggingWebApplicationFactory<Tag>>
14+
{
15+
private readonly NoLoggingWebApplicationFactory<Tag> _factory;
16+
17+
protected override JsonSerializerOptions SerializerOptions
18+
{
19+
get
20+
{
21+
var options = _factory.Services.GetRequiredService<IJsonApiOptions>();
22+
return options.SerializerOptions;
23+
}
24+
}
25+
26+
public TagTests(NoLoggingWebApplicationFactory<Tag> factory)
27+
{
28+
_factory = factory;
29+
}
30+
31+
[Fact]
32+
public async Task Can_get_primary_resources()
33+
{
34+
// Arrange
35+
const string route = "/api/tags";
36+
37+
// Act
38+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
39+
40+
// Assert
41+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
42+
43+
responseDocument.Data.ManyValue.ShouldHaveCount(3);
44+
45+
responseDocument.Meta.Should().ContainTotal(3);
46+
}
47+
48+
[Fact]
49+
public async Task Can_filter_in_primary_resources()
50+
{
51+
// Arrange
52+
const string route = "/api/tags?filter=equals(name,'Personal')";
53+
54+
// Act
55+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
56+
57+
// Assert
58+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
59+
60+
responseDocument.Data.ManyValue.ShouldHaveCount(1);
61+
responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be("Personal"));
62+
63+
responseDocument.Meta.Should().ContainTotal(1);
64+
}
65+
66+
[Fact]
67+
public async Task Can_filter_in_related_resources()
68+
{
69+
// Arrange
70+
const string route = "/api/tags?filter=has(todoItems,equals(description,'Check emails'))";
71+
72+
// Act
73+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
74+
75+
// Assert
76+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
77+
78+
responseDocument.Data.ManyValue.ShouldHaveCount(1);
79+
responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be("Business"));
80+
81+
responseDocument.Meta.Should().ContainTotal(1);
82+
}
83+
84+
[Fact]
85+
public async Task Can_sort_on_attribute_in_primary_resources()
86+
{
87+
// Arrange
88+
const string route = "/api/tags?sort=-id";
89+
90+
// Act
91+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
92+
93+
// Assert
94+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
95+
96+
responseDocument.Data.ManyValue.ShouldHaveCount(3);
97+
responseDocument.Data.ManyValue[0].Id.Should().Be("3");
98+
responseDocument.Data.ManyValue[1].Id.Should().Be("2");
99+
responseDocument.Data.ManyValue[2].Id.Should().Be("1");
100+
}
101+
102+
[Fact]
103+
public async Task Can_sort_on_count_in_primary_resources()
104+
{
105+
// Arrange
106+
const string route = "/api/tags?sort=-count(todoItems),id";
107+
108+
// Act
109+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
110+
111+
// Assert
112+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
113+
114+
responseDocument.Data.ManyValue.ShouldHaveCount(3);
115+
responseDocument.Data.ManyValue[0].Id.Should().Be("1");
116+
responseDocument.Data.ManyValue[1].Id.Should().Be("2");
117+
responseDocument.Data.ManyValue[2].Id.Should().Be("3");
118+
}
119+
120+
[Fact]
121+
public async Task Can_paginate_in_primary_resources()
122+
{
123+
// Arrange
124+
const string route = "/api/tags?page[size]=1&page[number]=2&sort=id";
125+
126+
// Act
127+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
128+
129+
// Assert
130+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
131+
132+
responseDocument.Data.ManyValue.ShouldHaveCount(1);
133+
responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("name").With(value => value.Should().Be("Family"));
134+
135+
responseDocument.Meta.Should().ContainTotal(3);
136+
}
137+
138+
[Fact]
139+
public async Task Can_select_fields_in_primary_resources()
140+
{
141+
// Arrange
142+
const string route = "/api/tags?fields[tags]=todoItems";
143+
144+
// Act
145+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
146+
147+
// Assert
148+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
149+
150+
responseDocument.Data.ManyValue.ShouldNotBeEmpty();
151+
responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Attributes.Should().BeNull());
152+
responseDocument.Data.ManyValue.Should().AllSatisfy(resource => resource.Relationships.ShouldOnlyContainKeys("todoItems"));
153+
}
154+
155+
[Fact]
156+
public async Task Can_include_in_primary_resources()
157+
{
158+
// Arrange
159+
const string route = "/api/tags?include=todoItems.owner";
160+
161+
// Act
162+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
163+
164+
// Assert
165+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
166+
167+
responseDocument.Data.ManyValue.Should().NotBeEmpty();
168+
responseDocument.Included.Should().NotBeEmpty();
169+
}
170+
171+
[Fact]
172+
public async Task Can_get_primary_resource()
173+
{
174+
// Arrange
175+
const string route = "/api/tags/1";
176+
177+
// Act
178+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
179+
180+
// Assert
181+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
182+
183+
responseDocument.Data.SingleValue.ShouldNotBeNull();
184+
responseDocument.Data.SingleValue.Id.Should().Be("1");
185+
}
186+
187+
[Fact]
188+
public async Task Can_get_secondary_resources()
189+
{
190+
// Arrange
191+
const string route = "/api/tags/1/todoItems?sort=id";
192+
193+
// Act
194+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
195+
196+
// Assert
197+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
198+
199+
responseDocument.Data.ManyValue.ShouldHaveCount(3);
200+
responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Make homework"));
201+
responseDocument.Data.ManyValue[1].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Book vacation"));
202+
responseDocument.Data.ManyValue[2].Attributes.ShouldContainKey("description").With(value => value.Should().Be("Cook dinner"));
203+
204+
responseDocument.Meta.Should().ContainTotal(3);
205+
}
206+
207+
[Fact]
208+
public async Task Can_get_ToMany_relationship()
209+
{
210+
// Arrange
211+
const string route = "/api/tags/2/relationships/todoItems";
212+
213+
// Act
214+
(HttpResponseMessage httpResponse, Document responseDocument) = await ExecuteGetAsync<Document>(route);
215+
216+
// Assert
217+
httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK);
218+
219+
responseDocument.Data.ManyValue.ShouldHaveCount(1);
220+
responseDocument.Data.ManyValue[0].Id.Should().Be("3");
221+
222+
responseDocument.Meta.Should().ContainTotal(1);
223+
}
224+
225+
protected override HttpClient CreateClient()
226+
{
227+
return _factory.CreateClient();
228+
}
229+
}

Diff for: test/TestBuildingBlocks/AssemblyInfo.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
using System.Diagnostics.CodeAnalysis;
22

3-
// https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/MSBuildIntegration.md#excluding-from-coverage
3+
// Justification: This assembly contains building blocks for writing tests. It does not contain code that ships.
44
[assembly: ExcludeFromCodeCoverage]

Diff for: tests.runsettings

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RunSettings>
3+
<RunConfiguration>
4+
<CollectSourceInformation>true</CollectSourceInformation>
5+
</RunConfiguration>
6+
<DataCollectionRunSettings>
7+
<DataCollectors>
8+
<DataCollector friendlyName="XPlat Code Coverage">
9+
<Configuration>
10+
<ExcludeByAttribute>ObsoleteAttribute,GeneratedCodeAttribute</ExcludeByAttribute>
11+
<DeterministicReport>true</DeterministicReport>
12+
</Configuration>
13+
</DataCollector>
14+
</DataCollectors>
15+
</DataCollectionRunSettings>
16+
</RunSettings>

0 commit comments

Comments
 (0)