Skip to content

Commit 0d638b5

Browse files
authored
feat: percy snapshot (#9747)
1 parent bebcd35 commit 0d638b5

File tree

45 files changed

+146
-6617
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+146
-6617
lines changed

.github/workflows/ci.yml

+8
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ jobs:
3535
- run: dotnet test -c Release -f net6.0 --no-build --collect:"XPlat Code Coverage"
3636
if: matrix.os == 'ubuntu-latest'
3737

38+
- run: npm i -g @percy/cli
39+
if: matrix.os == 'ubuntu-latest'
40+
41+
- run: percy exec -- dotnet test -c Release -f net8.0 --filter Stage=Percy --no-build --collect:"XPlat Code Coverage"
42+
if: matrix.os == 'ubuntu-latest'
43+
env:
44+
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
45+
3846
- uses: codecov/codecov-action@v4
3947
if: matrix.os == 'ubuntu-latest'
4048

Directory.Packages.props

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
<!-- Test only -->
4040
<PackageVersion Include="coverlet.collector" Version="6.0.1" />
4141
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
42-
<PackageVersion Include="Magick.NET-Q16-AnyCPU" Version="13.6.0" />
4342
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
4443
<PackageVersion Include="PublicApiGenerator" Version="11.1.0" />
4544
<PackageVersion Include="Verify.DiffPlex" Version="2.3.0" />
+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics;
5+
using System.Net.Http.Json;
6+
using System.Net.NetworkInformation;
7+
using System.Text.RegularExpressions;
8+
using Docfx.Common;
9+
using Microsoft.Playwright;
10+
11+
namespace Docfx.Tests;
12+
13+
[Trait("Stage", "Percy")]
14+
public class PercyTest
15+
{
16+
private class PercyFactAttribute : FactAttribute
17+
{
18+
public PercyFactAttribute()
19+
{
20+
Skip = IsActiveLocalTcpPort(5338) ? null : "Run percy tests with `percy exec`";
21+
}
22+
}
23+
24+
private static readonly string s_samplesDir = Path.GetFullPath("../../../../../samples");
25+
26+
private static readonly string[] s_screenshotUrls =
27+
[
28+
"index.html",
29+
"articles/markdown.html?tabs=windows%2Ctypescript#markdown-extensions",
30+
"articles/markdown.html?dark",
31+
"articles/csharp_coding_standards.html",
32+
"api/BuildFromProject.Class1.html",
33+
"api/CatLibrary.html?dark",
34+
"api/CatLibrary.html?term=cat",
35+
"api/CatLibrary.Cat-2.html?q=cat",
36+
"restapi/petstore.html",
37+
];
38+
39+
static PercyTest()
40+
{
41+
Microsoft.Playwright.Program.Main(["install", "chromium"]);
42+
}
43+
44+
[PercyFact]
45+
public async Task SeedHtml()
46+
{
47+
var samplePath = $"{s_samplesDir}/seed";
48+
Clean(samplePath);
49+
50+
var docfxPath = Path.GetFullPath(OperatingSystem.IsWindows() ? "docfx.exe" : "docfx");
51+
Assert.Equal(0, Exec(docfxPath, $"metadata {samplePath}/docfx.json"));
52+
Assert.Equal(0, Exec(docfxPath, $"build {samplePath}/docfx.json"));
53+
54+
const int port = 8089;
55+
var _ = Task.Run(() => Program.Main(["serve", "--port", $"{port}", $"{samplePath}/_site"]))
56+
.ContinueWith(x =>
57+
{
58+
Logger.LogError("Failed to run `dotnet serve` command. " + x.Exception.ToString());
59+
}, TaskContinuationOptions.OnlyOnFaulted);
60+
61+
// Wait until web server started.
62+
bool isStarted = SpinWait.SpinUntil(() => { Thread.Sleep(100); return IsActiveLocalTcpPort(port); }, TimeSpan.FromSeconds(10));
63+
64+
using var playwright = await Playwright.CreateAsync();
65+
var browser = await playwright.Chromium.LaunchAsync();
66+
var page = await browser.NewPageAsync(new());
67+
68+
foreach (var url in s_screenshotUrls)
69+
{
70+
await page.GotoAsync($"http://localhost:{port}/{url}");
71+
await page.WaitForFunctionAsync("window.docfx.ready");
72+
await page.WaitForFunctionAsync("window.docfx.searchReady");
73+
74+
if (url.Contains("?dark"))
75+
{
76+
await page.EvaluateAsync($"() => document.documentElement.setAttribute('data-bs-theme', 'dark')");
77+
}
78+
79+
await Task.Delay(200);
80+
81+
if (url.Contains("?term=cat"))
82+
{
83+
await (await page.QuerySelectorAsync("#search-query")).FillAsync("cat");
84+
await page.WaitForFunctionAsync("window.docfx.searchResultReady");
85+
}
86+
87+
var name = $"{Regex.Replace(url, "[^a-zA-Z0-9-_.]", "-")}";
88+
await PercySnapshot(page, name);
89+
}
90+
91+
await page.CloseAsync();
92+
}
93+
94+
private static async Task PercySnapshot(IPage page, string name)
95+
{
96+
using (var http = new HttpClient())
97+
{
98+
// https://www.browserstack.com/docs/percy/integrate/build-your-sdk
99+
// # Step 2: Fetch and inject the DOM JavaScript into the browser
100+
var domjs = await http.GetStringAsync("http://localhost:5338/percy/dom.js");
101+
await page.AddScriptTagAsync(new() { Content = domjs });
102+
var domSnapshot = await page.EvaluateAsync("PercyDOM.serialize()");
103+
var res = await http.PostAsJsonAsync("http://localhost:5338/percy/snapshot", new
104+
{
105+
domSnapshot,
106+
url = page.Url,
107+
name
108+
});
109+
}
110+
}
111+
112+
private static int Exec(string filename, string args, string workingDirectory = null)
113+
{
114+
var psi = new ProcessStartInfo(filename, args);
115+
psi.EnvironmentVariables.Add("DOCFX_SOURCE_BRANCH_NAME", "main");
116+
if (workingDirectory != null)
117+
psi.WorkingDirectory = Path.GetFullPath(workingDirectory);
118+
var process = Process.Start(psi);
119+
process.WaitForExit();
120+
return process.ExitCode;
121+
}
122+
123+
private static void Clean(string samplePath)
124+
{
125+
if (Directory.Exists($"{samplePath}/_site"))
126+
Directory.Delete($"{samplePath}/_site", recursive: true);
127+
128+
if (Directory.Exists($"{samplePath}/_site_pdf"))
129+
Directory.Delete($"{samplePath}/_site_pdf", recursive: true);
130+
}
131+
132+
private static bool IsActiveLocalTcpPort(int port)
133+
{
134+
var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
135+
var tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
136+
return tcpConnInfoArray.Any(x => x.Port == port);
137+
}
138+
}

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1152x648/api-BuildFromProject.Class1.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1152x648/api-CatLibrary.Cat-2.html-q-cat.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1152x648/api-CatLibrary.html-term-cat.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1152x648/api-CatLibrary.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1152x648/articles-csharp_coding_standards.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1152x648/articles-markdown.html-tabs-windows-2Ctypescript-markdown-extensions.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1152x648/index.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1152x648/restapi-petstore.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1920x1080/api-BuildFromProject.Class1.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1920x1080/api-CatLibrary.Cat-2.html-q-cat.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1920x1080/api-CatLibrary.html-term-cat.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1920x1080/api-CatLibrary.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1920x1080/articles-csharp_coding_standards.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1920x1080/articles-markdown.html-tabs-windows-2Ctypescript-markdown-extensions.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1920x1080/index.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/1920x1080/restapi-petstore.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/375x812/api-BuildFromProject.Class1.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/375x812/api-CatLibrary.Cat-2.html-q-cat.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/375x812/api-CatLibrary.html-term-cat.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/375x812/api-CatLibrary.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/375x812/articles-csharp_coding_standards.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/375x812/articles-markdown.html-tabs-windows-2Ctypescript-markdown-extensions.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/375x812/index.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/375x812/restapi-petstore.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/768x600/api-BuildFromProject.Class1.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/768x600/api-CatLibrary.Cat-2.html-q-cat.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/768x600/api-CatLibrary.html-term-cat.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/768x600/api-CatLibrary.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/768x600/articles-csharp_coding_standards.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/768x600/articles-markdown.html-tabs-windows-2Ctypescript-markdown-extensions.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/768x600/index.html.verified.png

-3
This file was deleted.

test/docfx.Snapshot.Tests/SamplesTest.SeedHtml/768x600/restapi-petstore.html.verified.png

-3
This file was deleted.

0 commit comments

Comments
 (0)