Skip to content

Commit c9464b8

Browse files
authored
Merge pull request #504 from Shane32/apiapprovals
Add API approvals to tests
2 parents ffe2461 + 50f40ec commit c9464b8

File tree

14 files changed

+3932
-59
lines changed

14 files changed

+3932
-59
lines changed

.github/workflows/wf-build-release-ci.yml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,13 @@ jobs:
2020
1.0.x
2121
2.0.x
2222
5.0.x
23-
6.0.x
23+
6.0.x
2424
25-
- name: Setup MSBuild Path
26-
uses: microsoft/setup-msbuild@v1
27-
28-
- name: Setup NuGet
29-
uses: NuGet/setup-nuget@v2
30-
3125
- name: Restore NuGet Packages
32-
run: nuget restore QRCoder.sln
26+
run: dotnet restore
3327

3428
- name: Build library
35-
run: msbuild QRCoder.sln /p:Configuration=Release /p:NoWarn="1182" /p:NoWarn="1701" /nr:false /t:Rebuild
29+
run: dotnet build -c Release --no-restore
3630

3731
- name: Upload artifacts
3832
uses: actions/upload-artifact@v4
@@ -60,28 +54,40 @@ jobs:
6054
6.0.x
6155
6256
- name: Run test .NET 3.5
57+
working-directory: QRCoderTests
6358
run: dotnet test -c Release -f net35 --nologo --no-build # No coverage for NET3.5 because of bug in combination with Coverlet+Stronh naming
6459

6560
- name: Run test .NET 4.52
61+
working-directory: QRCoderTests
6662
run: dotnet test -c Release -f net452 --nologo --no-build # No coverage for NET4.5 because of bug in combination with Coverlet+Strong naming
6763

6864
- name: Run test .NET Core 1.1
65+
working-directory: QRCoderTests
6966
run: dotnet test -c Release -f netcoreapp1.1 --nologo # No coverage for .NETCORE 1.1 because Coverlet doesn't support it https://github.com/coverlet-coverage/coverlet/issues/466
7067

7168
- name: Run test .NET Core 2.0
69+
working-directory: QRCoderTests
7270
run: dotnet test -c Release -f netcoreapp2.0 --nologo /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
7371

7472
- name: Run test .NET 5.0
73+
working-directory: QRCoderTests
7574
run: dotnet test -c Release -f net5.0 --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
7675

7776
- name: Run test .NET 5.0 Windows
77+
working-directory: QRCoderTests
7878
run: dotnet test -c Release -f net5.0-windows --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
7979

8080
- name: Run test .NET 6.0
81+
working-directory: QRCoderTests
8182
run: dotnet test -c Release -f net6.0 --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
8283

8384
- name: Run test .NET 6.0 Windows
85+
working-directory: QRCoderTests
8486
run: dotnet test -c Release -f net6.0-windows --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
87+
88+
- name: Run API approval tests
89+
working-directory: QRCoderApiTests
90+
run: dotnet test -c Release --nologo --no-build
8591

8692
- name: Codecov update netcoreapp2.0
8793
uses: codecov/codecov-action@v2

.github/workflows/wf-build-release.yml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,13 @@ jobs:
2121
1.0.x
2222
2.0.x
2323
5.0.x
24-
6.0.x
24+
6.0.x
2525
26-
- name: Setup MSBuild Path
27-
uses: microsoft/setup-msbuild@v1
28-
29-
- name: Setup NuGet
30-
uses: NuGet/setup-nuget@v2
31-
3226
- name: Restore NuGet Packages
33-
run: nuget restore QRCoder.sln
27+
run: dotnet restore
3428

3529
- name: Build library
36-
run: msbuild QRCoder.sln /p:Configuration=Release /p:NoWarn="1182" /p:NoWarn="1701" /nr:false /t:Rebuild
30+
run: dotnet build -c Release --no-restore
3731

3832
- name: Upload artifacts
3933
uses: actions/upload-artifact@v4
@@ -61,28 +55,40 @@ jobs:
6155
6.0.x
6256
6357
- name: Run test .NET 3.5
58+
working-directory: QRCoderTests
6459
run: dotnet test -c Release -f net35 --nologo --no-build # No coverage for NET3.5 because of bug in combination with Coverlet+Stronh naming
6560

6661
- name: Run test .NET 4.52
62+
working-directory: QRCoderTests
6763
run: dotnet test -c Release -f net452 --nologo --no-build # No coverage for NET4.5 because of bug in combination with Coverlet+Strong naming
6864

6965
- name: Run test .NET Core 1.1
66+
working-directory: QRCoderTests
7067
run: dotnet test -c Release -f netcoreapp1.1 --nologo # No coverage for .NETCORE 1.1 because Coverlet doesn't support it https://github.com/coverlet-coverage/coverlet/issues/466
7168

7269
- name: Run test .NET Core 2.0
70+
working-directory: QRCoderTests
7371
run: dotnet test -c Release -f netcoreapp2.0 --nologo /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
7472

7573
- name: Run test .NET 5.0
74+
working-directory: QRCoderTests
7675
run: dotnet test -c Release -f net5.0 --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
7776

7877
- name: Run test .NET 5.0 Windows
78+
working-directory: QRCoderTests
7979
run: dotnet test -c Release -f net5.0-windows --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
8080

8181
- name: Run test .NET 6.0
82+
working-directory: QRCoderTests
8283
run: dotnet test -c Release -f net6.0 --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
8384

8485
- name: Run test .NET 6.0 Windows
86+
working-directory: QRCoderTests
8587
run: dotnet test -c Release -f net6.0-windows --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
88+
89+
- name: Run API approval tests
90+
working-directory: QRCoderApiTests
91+
run: dotnet test -c Release --nologo --no-build
8692

8793
- name: Codecov update netcoreapp2.0
8894
uses: codecov/codecov-action@v2

.github/workflows/wf-build-test.yml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,13 @@ jobs:
2020
1.0.x
2121
2.0.x
2222
5.0.x
23-
6.0.x
24-
25-
- name: Setup MSBuild Path
26-
uses: microsoft/setup-msbuild@v1
27-
28-
- name: Setup NuGet
29-
uses: NuGet/setup-nuget@v2
30-
23+
6.0.x
24+
3125
- name: Restore NuGet Packages
32-
run: nuget restore QRCoder.sln
26+
run: dotnet restore
3327

3428
- name: Build library
35-
run: msbuild QRCoder.sln /p:Configuration=Release /p:NoWarn="1182" /p:NoWarn="1701" /nr:false /t:Rebuild
29+
run: dotnet build -c Release --no-restore
3630

3731
- name: Upload artifacts
3832
uses: actions/upload-artifact@v4
@@ -60,29 +54,41 @@ jobs:
6054
6.0.x
6155
6256
- name: Run test .NET 3.5
57+
working-directory: QRCoderTests
6358
run: dotnet test -c Release -f net35 --nologo --no-build # No coverage for NET3.5 because of bug in combination with Coverlet+Stronh naming
6459

6560
- name: Run test .NET 4.52
61+
working-directory: QRCoderTests
6662
run: dotnet test -c Release -f net452 --nologo --no-build # No coverage for NET4.5 because of bug in combination with Coverlet+Strong naming
6763

6864
- name: Run test .NET Core 1.1
65+
working-directory: QRCoderTests
6966
run: dotnet test -c Release -f netcoreapp1.1 --nologo # No coverage for .NETCORE 1.1 because Coverlet doesn't support it https://github.com/coverlet-coverage/coverlet/issues/466
7067

7168
- name: Run test .NET Core 2.0
69+
working-directory: QRCoderTests
7270
run: dotnet test -c Release -f netcoreapp2.0 --nologo /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
7371

7472
- name: Run test .NET 5.0
73+
working-directory: QRCoderTests
7574
run: dotnet test -c Release -f net5.0 --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
7675

7776
- name: Run test .NET 5.0 Windows
77+
working-directory: QRCoderTests
7878
run: dotnet test -c Release -f net5.0-windows --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
7979

8080
- name: Run test .NET 6.0
81+
working-directory: QRCoderTests
8182
run: dotnet test -c Release -f net6.0 --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
8283

8384
- name: Run test .NET 6.0 Windows
85+
working-directory: QRCoderTests
8486
run: dotnet test -c Release -f net6.0-windows --nologo --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
8587

88+
- name: Run API approval tests
89+
working-directory: QRCoderApiTests
90+
run: dotnet test -c Release --nologo --no-build
91+
8692
clean:
8793
needs: [build, test]
8894
if: always()

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,6 @@ pip-log.txt
219219
*.userprefs
220220

221221
QRCoder/PortabilityAnalysis.html
222+
223+
# Unaccepted approval files
224+
*.received.txt

QRCoder.sln

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QRCoderTests", "QRCoderTest
1515
EndProject
1616
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QRCoder.Xaml", "QRCoder.Xaml\QRCoder.Xaml.csproj", "{A7A7E073-2504-4BA2-A63B-87AC34174789}"
1717
EndProject
18+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QRCoderApiTests", "QRCoderApiTests\QRCoderApiTests.csproj", "{5FACE5F6-53C9-4B89-91D4-162677893574}"
19+
EndProject
1820
Global
1921
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2022
Debug|Any CPU = Debug|Any CPU
@@ -119,6 +121,22 @@ Global
119121
{A7A7E073-2504-4BA2-A63B-87AC34174789}.Release|x64.Build.0 = Release|Any CPU
120122
{A7A7E073-2504-4BA2-A63B-87AC34174789}.Release|x86.ActiveCfg = Release|Any CPU
121123
{A7A7E073-2504-4BA2-A63B-87AC34174789}.Release|x86.Build.0 = Release|Any CPU
124+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
125+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Debug|Any CPU.Build.0 = Debug|Any CPU
126+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Debug|ARM.ActiveCfg = Debug|Any CPU
127+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Debug|ARM.Build.0 = Debug|Any CPU
128+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Debug|x64.ActiveCfg = Debug|Any CPU
129+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Debug|x64.Build.0 = Debug|Any CPU
130+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Debug|x86.ActiveCfg = Debug|Any CPU
131+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Debug|x86.Build.0 = Debug|Any CPU
132+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Release|Any CPU.ActiveCfg = Release|Any CPU
133+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Release|Any CPU.Build.0 = Release|Any CPU
134+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Release|ARM.ActiveCfg = Release|Any CPU
135+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Release|ARM.Build.0 = Release|Any CPU
136+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Release|x64.ActiveCfg = Release|Any CPU
137+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Release|x64.Build.0 = Release|Any CPU
138+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Release|x86.ActiveCfg = Release|Any CPU
139+
{5FACE5F6-53C9-4B89-91D4-162677893574}.Release|x86.Build.0 = Release|Any CPU
122140
EndGlobalSection
123141
GlobalSection(SolutionProperties) = preSolution
124142
HideSolutionNode = FALSE

QRCoderApiTests/ApiApprovalTests.cs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using PublicApiGenerator;
2+
using Shouldly;
3+
using System;
4+
using System.Diagnostics;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Reflection;
8+
using System.Xml.Linq;
9+
using Xunit;
10+
11+
/*********************************************
12+
*
13+
* This file copied from GraphQL.NET on 4/26/2024
14+
* https://github.com/graphql-dotnet/graphql-dotnet/blob/dce3a8d9335eb2ff0674a1e48af01fdd6b942119/src/GraphQL.ApiTests/ApiApprovalTests.cs
15+
*
16+
* Unmodified portions of this file are subject to the following license:
17+
* https://github.com/graphql-dotnet/graphql-dotnet/blob/dce3a8d9335eb2ff0674a1e48af01fdd6b942119/LICENSE.md
18+
*
19+
* The MIT License (MIT)
20+
*
21+
* Copyright (c) 2015-2023 Joseph T. McBride, Ivan Maximov, Shane Krueger, et al. All rights reserved.
22+
*
23+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
24+
* associated documentation files (the "Software"), to deal in the Software without restriction, including
25+
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26+
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
27+
* following conditions:
28+
*
29+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
30+
*
31+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
32+
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
33+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
34+
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
35+
* IN THE SOFTWARE.
36+
*
37+
*********************************************/
38+
39+
namespace QRCoderApiTests
40+
{
41+
/// <summary>
42+
/// See more info about API approval tests here <see href="https://github.com/JakeGinnivan/ApiApprover"/>.
43+
/// </summary>
44+
public class ApiApprovalTests
45+
{
46+
[Theory]
47+
[InlineData(typeof(QRCoder.QRCodeData))]
48+
[InlineData(typeof(QRCoder.Xaml.XamlQRCode))]
49+
public void PublicApi(Type type)
50+
{
51+
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
52+
string projectName = type.Assembly.GetName().Name!;
53+
string testDir = Path.Combine(baseDir, $"..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..");
54+
string projectDir = Path.Combine(testDir, "..");
55+
string buildDir = Path.Combine(projectDir, projectName, "bin",
56+
#if DEBUG
57+
"Debug");
58+
#else
59+
"Release");
60+
#endif
61+
Debug.Assert(Directory.Exists(buildDir), $"Directory '{buildDir}' doesn't exist");
62+
string csProject = Path.Combine(projectDir, projectName, projectName + ".csproj");
63+
var project = XDocument.Load(csProject);
64+
string[] tfms = project.Descendants("TargetFrameworks").Union(project.Descendants("TargetFramework")).First().Value.Split(";", StringSplitOptions.RemoveEmptyEntries);
65+
66+
// There may be old stuff from earlier builds like net45, netcoreapp3.0, etc. so filter it out
67+
string[] actualTfmDirs = Directory.GetDirectories(buildDir).Where(dir => tfms.Any(tfm => dir.EndsWith(tfm))).ToArray();
68+
Debug.Assert(actualTfmDirs.Length > 0, $"Directory '{buildDir}' doesn't contain subdirectories matching {string.Join(";", tfms)}");
69+
70+
(string tfm, string content)[] publicApi = actualTfmDirs.Select(tfmDir => (new DirectoryInfo(tfmDir).Name.Replace(".", ""), Assembly.LoadFile(Path.Combine(tfmDir, projectName + ".dll")).GeneratePublicApi(new ApiGeneratorOptions
71+
{
72+
IncludeAssemblyAttributes = false,
73+
//AllowNamespacePrefixes = new[] { "Microsoft.Extensions.DependencyInjection" },
74+
ExcludeAttributes = new[] { "System.Diagnostics.DebuggerDisplayAttribute", "System.Diagnostics.CodeAnalysis.AllowNullAttribute" }
75+
}) + Environment.NewLine)).ToArray();
76+
77+
if (publicApi.DistinctBy(item => item.content).Count() == 1)
78+
{
79+
AutoApproveOrFail(publicApi[0].content, "");
80+
}
81+
else
82+
{
83+
foreach (var item in publicApi.ToLookup(item => item.content))
84+
{
85+
AutoApproveOrFail(item.Key, string.Join("+", item.Select(x => x.tfm).OrderBy(x => x)));
86+
}
87+
}
88+
89+
// Approval test should (re)generate approved.txt files locally if needed.
90+
// Approval test should fail on CI.
91+
// https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables
92+
void AutoApproveOrFail(string publicApi, string folder)
93+
{
94+
string file = null!;
95+
96+
try
97+
{
98+
publicApi.ShouldMatchApproved(options => options.SubFolder(folder).NoDiff().WithFilenameGenerator((testMethodInfo, discriminator, fileType, fileExtension) => file = $"{type.Assembly.GetName().Name}.{fileType}.{fileExtension}"));
99+
}
100+
catch (ShouldMatchApprovedException) when (Environment.GetEnvironmentVariable("CI") == null)
101+
{
102+
string? received = Path.Combine(testDir, folder, file);
103+
string? approved = received.Replace(".received.txt", ".approved.txt");
104+
if (File.Exists(received) && File.Exists(approved))
105+
{
106+
File.Copy(received, approved, overwrite: true);
107+
File.Delete(received);
108+
}
109+
else
110+
{
111+
throw;
112+
}
113+
}
114+
}
115+
}
116+
}
117+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace QRCoder.Xaml
2+
{
3+
public class XamlQRCode : QRCoder.AbstractQRCode, System.IDisposable
4+
{
5+
public XamlQRCode() { }
6+
public XamlQRCode(QRCoder.QRCodeData data) { }
7+
public System.Windows.Media.DrawingImage GetGraphic(int pixelsPerModule) { }
8+
public System.Windows.Media.DrawingImage GetGraphic(int pixelsPerModule, bool drawQuietZones) { }
9+
public System.Windows.Media.DrawingImage GetGraphic(System.Windows.Size viewBox, bool drawQuietZones = true) { }
10+
public System.Windows.Media.DrawingImage GetGraphic(int pixelsPerModule, string darkColorHex, string lightColorHex, bool drawQuietZones = true) { }
11+
public System.Windows.Media.DrawingImage GetGraphic(System.Windows.Size viewBox, System.Windows.Media.Brush darkBrush, System.Windows.Media.Brush lightBrush, bool drawQuietZones = true) { }
12+
public double GetUnitsPerModule(System.Windows.Size viewBox, bool drawQuietZones = true) { }
13+
}
14+
public static class XamlQRCodeHelper
15+
{
16+
public static System.Windows.Media.DrawingImage GetQRCode(string plainText, int pixelsPerModule, string darkColorHex, string lightColorHex, QRCoder.QRCodeGenerator.ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, QRCoder.QRCodeGenerator.EciMode eciMode = 0, int requestedVersion = -1, bool drawQuietZones = true) { }
17+
}
18+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0-windows</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<IsTestProject>true</IsTestProject>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<ProjectReference Include="..\QRCoder.Xaml\QRCoder.Xaml.csproj" />
11+
<ProjectReference Include="..\QRCoder\QRCoder.csproj" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="PublicApiGenerator" Version="11.1.0" />
16+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
17+
<PackageReference Include="xunit" Version="2.4.1" />
18+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
19+
<PackageReference Include="shouldly" Version="4.0.3" />
20+
</ItemGroup>
21+
22+
</Project>

0 commit comments

Comments
 (0)