Skip to content

Commit b87a9d7

Browse files
authoredMar 12, 2024··
[BREAKING] Introduce new headless mode (#2492)
* Introduce new headless mode * Add reference * Change workflow title * fix actions * fix test * fix a test * fix formatting * Fix auth tests * Fix a webworker test * Fix requestFinished * fix should be able to fetch dataURL and fire dataURL requests * dotnet format * Undo debugging thing * Improve test * Fix more tests * Fix CloseAsync race * fix build * change a test name * Fix response from cache test. * oops * Some fixes * fix test * Ignore a flaky test
1 parent da30a58 commit b87a9d7

26 files changed

+355
-247
lines changed
 

‎.github/workflows/dotnet.yml

+37-3
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,45 @@ env:
2020

2121
jobs:
2222
build:
23-
name: build-${{ matrix.browser }}/${{ matrix.os }}
23+
name: build-${{ matrix.browser }}-${{ matrix.mode }}-${{ matrix.os }}
2424
runs-on: ${{ matrix.os }}
2525
strategy:
2626
fail-fast: false
2727
matrix:
2828
os: [ubuntu-latest, windows-latest]
29-
browser: [FIREFOX,CHROME]
29+
browser: [CHROME, FIREFOX]
30+
mode: [headless, headful, headless-shell]
31+
include:
32+
- os: ubuntu-latest
33+
browser: CHROME
34+
mode: headless
35+
- os: ubuntu-latest
36+
browser: CHROME
37+
mode: headful
38+
- os: ubuntu-latest
39+
browser: CHROME
40+
mode: headless-shell
41+
- os: ubuntu-latest
42+
browser: FIREFOX
43+
mode: headless
44+
- os: ubuntu-latest
45+
browser: FIREFOX
46+
mode: headful
47+
- os: windows-latest
48+
browser: CHROME
49+
mode: headless
50+
- os: windows-latest
51+
browser: CHROME
52+
mode: headful
53+
- os: windows-latest
54+
browser: CHROME
55+
mode: headless-shell
56+
- os: windows-latest
57+
browser: FIREFOX
58+
mode: headless
59+
- os: windows-latest
60+
browser: FIREFOX
61+
mode: headful
3062
steps:
3163
- uses: actions/checkout@v3
3264
- name: Setup .NET Core
@@ -54,7 +86,7 @@ jobs:
5486
New-SelfSignedCertificate -Subject "localhost" -FriendlyName "Puppeteer" -CertStoreLocation "cert:\CurrentUser\My"
5587
Get-ChildItem -Path cert:\CurrentUSer\my | where { $_.friendlyname -eq "Puppeteer" } | Export-Certificate -FilePath $env:GITHUB_WORKSPACE\lib\PuppeteerSharp.TestServer\testCert.cer
5688
- name: Check formatting
57-
if: ${{ matrix.os == 'ubuntu-latest' && matrix.browser == 'CHROME' }}
89+
if: ${{ matrix.os == 'ubuntu-latest' && matrix.browser == 'CHROME' && matrix.mode == 'headless' }}
5890
run: dotnet format ./lib/PuppeteerSharp.sln --verify-no-changes
5991
- name: Build
6092
working-directory: lib
@@ -63,6 +95,7 @@ jobs:
6395
if: matrix.os == 'ubuntu-latest'
6496
env:
6597
PRODUCT: ${{ matrix.browser }}
98+
HEADLESS_MODE: ${{ matrix.mode }}
6699
run: |
67100
Xvfb :1 -screen 5 1024x768x8 &
68101
export DISPLAY=:1.5
@@ -72,6 +105,7 @@ jobs:
72105
if: matrix.os == 'windows-latest'
73106
env:
74107
PRODUCT: ${{ matrix.browser }}
108+
HEADLESS_MODE: ${{ matrix.mode }}
75109
run: |
76110
cd .\lib\PuppeteerSharp.Tests
77111
dotnet test -s test.runsettings --blame-hang-timeout 300000

‎lib/PuppeteerSharp.Nunit/PuppeteerSharp.Nunit.csproj

+3
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@
1212
<EmbeddedResource Include="TestExpectations\TestExpectations.local.json" />
1313
<EmbeddedResource Include="TestExpectations\TestExpectations.upstream.json" />
1414
</ItemGroup>
15+
<ItemGroup>
16+
<ProjectReference Include="..\PuppeteerSharp\PuppeteerSharp.csproj" />
17+
</ItemGroup>
1518
<Import Project="../Common/CommonProps.props" />
1619
</Project>

‎lib/PuppeteerSharp.Nunit/PuppeteerTestAttribute.cs

+19-7
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,21 @@ public class PuppeteerTestAttribute : NUnitAttribute, IApplyToTest
2323
public static readonly bool IsChrome = Environment.GetEnvironmentVariable("PRODUCT") != "FIREFOX";
2424
// TODO: Change implementation when we implement Webdriver Bidi
2525
public static readonly bool IsCdp = true;
26-
public static readonly bool Headless = Convert.ToBoolean(
27-
Environment.GetEnvironmentVariable("HEADLESS") ??
28-
(System.Diagnostics.Debugger.IsAttached ? "false" : "true"),
29-
System.Globalization.CultureInfo.InvariantCulture);
26+
public static readonly HeadlessMode Headless =
27+
string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HEADLESS_MODE")) ?
28+
(System.Diagnostics.Debugger.IsAttached ? HeadlessMode.False : HeadlessMode.True) :
29+
GetHeadlessModeFromEnvVar(Environment.GetEnvironmentVariable("HEADLESS_MODE"));
30+
31+
private static HeadlessMode GetHeadlessModeFromEnvVar(string getEnvironmentVariable)
32+
{
33+
return getEnvironmentVariable switch
34+
{
35+
"headless" => HeadlessMode.True,
36+
"headful" => HeadlessMode.False,
37+
"headless-shell" => HeadlessMode.Shell,
38+
_ => throw new ArgumentException("Invalid value for HEADLESS_MODE environment variable"),
39+
};
40+
}
3041

3142
/// <summary>
3243
/// Creates a new instance of the attribute.
@@ -92,17 +103,18 @@ private bool ShouldSkipByExpectation(Test test, out TestExpectation output)
92103
var currentExpectationPlatform = GetCurrentExpectationPlatform();
93104
List<TestExpectation.TestExpectationsParameter> parameters =
94105
[
95-
96106
IsChrome
97107
? TestExpectation.TestExpectationsParameter.Chrome
98108
: TestExpectation.TestExpectationsParameter.Firefox,
99109

100110
IsCdp
101111
? TestExpectation.TestExpectationsParameter.Cdp
102112
: TestExpectation.TestExpectationsParameter.WebDriverBiDi,
103-
Headless
113+
Headless.Equals(HeadlessMode.True)
104114
? TestExpectation.TestExpectationsParameter.Headless
105-
: TestExpectation.TestExpectationsParameter.Headful,
115+
: Headless.Equals(HeadlessMode.False)
116+
? TestExpectation.TestExpectationsParameter.Headful
117+
: TestExpectation.TestExpectationsParameter.ChromeHeadlessShell
106118
];
107119

108120
var localExpectations = GetLocalExpectations();

‎lib/PuppeteerSharp.Nunit/TestExpectations/TestExpectation.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ public enum TestExpectationsParameter
7272
Chrome,
7373
WebDriverBiDi,
7474
Cdp,
75-
[EnumMember(Value = "chrome-headless-shell")] ChromeHeadlessShell,
75+
[EnumMember(Value = "chrome-headless-shell")]
76+
ChromeHeadlessShell,
7677
Headless,
7778
Headful,
7879
}

‎lib/PuppeteerSharp.Nunit/TestExpectations/TestExpectations.local.json

+7
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,12 @@
4747
"platforms": ["darwin", "linux", "win32"],
4848
"parameters": ["firefox"],
4949
"expectations": ["FAIL"]
50+
},
51+
{
52+
"comment": "This is passing on my machine but failing on CI/CD",
53+
"testIdPattern": "[click.spec] Page.click should fire aux event on middle click",
54+
"platforms": ["win32"],
55+
"parameters": ["firefox", "headful"],
56+
"expectations": ["FAIL"]
5057
}
5158
]
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// This injects a box into the page that moves with the mouse;
22
// Useful for debugging
33
(function () {
4-
const box = document.createElement('div');
5-
box.classList.add('mouse-helper');
6-
const styleElement = document.createElement('style');
7-
styleElement.innerHTML = `
4+
const box = document.createElement('div');
5+
box.classList.add('mouse-helper');
6+
const styleElement = document.createElement('style');
7+
styleElement.innerHTML = `
88
.mouse-helper {
99
pointer-events: none;
1010
position: absolute;
@@ -40,35 +40,35 @@
4040
border-color: rgba(0,255,0,0.9);
4141
}
4242
`;
43-
document.head.appendChild(styleElement);
44-
document.body.appendChild(box);
45-
document.addEventListener(
46-
'mousemove',
47-
(event) => {
48-
box.style.left = event.pageX + 'px';
49-
box.style.top = event.pageY + 'px';
50-
updateButtons(event.buttons);
51-
},
52-
true
53-
);
54-
document.addEventListener(
55-
'mousedown',
56-
(event) => {
57-
updateButtons(event.buttons);
58-
box.classList.add('button-' + event.which);
59-
},
60-
true
61-
);
62-
document.addEventListener(
63-
'mouseup',
64-
(event) => {
65-
updateButtons(event.buttons);
66-
box.classList.remove('button-' + event.which);
67-
},
68-
true
69-
);
70-
function updateButtons(buttons) {
71-
for (let i = 0; i < 5; i++)
72-
box.classList.toggle('button-' + i, buttons & (1 << i));
73-
}
43+
document.head.appendChild(styleElement);
44+
document.body.appendChild(box);
45+
document.addEventListener(
46+
'mousemove',
47+
(event) => {
48+
box.style.left = event.pageX + 'px';
49+
box.style.top = event.pageY + 'px';
50+
updateButtons(event.buttons);
51+
},
52+
true
53+
);
54+
document.addEventListener(
55+
'mousedown',
56+
(event) => {
57+
updateButtons(event.buttons);
58+
box.classList.add('button-' + event.which);
59+
},
60+
true
61+
);
62+
document.addEventListener(
63+
'mouseup',
64+
(event) => {
65+
updateButtons(event.buttons);
66+
box.classList.remove('button-' + event.which);
67+
},
68+
true
69+
);
70+
function updateButtons(buttons) {
71+
for (let i = 0; i < 5; i++)
72+
{box.classList.toggle('button-' + i, buttons & (1 << i));}
73+
}
7474
})();
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
<!DOCTYPE html>
22
<html>
3-
<head>
3+
<head>
44
<title>Scrollable test</title>
5-
</head>
6-
<body>
7-
<script src='mouse-helper.js'></script>
8-
<script>
9-
for (let i = 0; i < 100; i++) {
10-
let button = document.createElement('button');
11-
button.textContent = i + ': not clicked';
12-
button.id = 'button-' + i;
13-
button.onclick = () => button.textContent = 'clicked';
14-
button.oncontextmenu = event => {
15-
if (![2].includes(event.button)) {
5+
</head>
6+
<body>
7+
<script src='mouse-helper.js'></script>
8+
<script>
9+
for (let i = 0; i < 100; i++) {
10+
let button = document.createElement('button');
11+
button.textContent = i + ': not clicked';
12+
button.id = 'button-' + i;
13+
button.onclick = () => button.textContent = 'clicked';
14+
button.oncontextmenu = event => {
15+
if (![2].includes(event.button)) {
1616
return;
17-
}
18-
event.preventDefault();
19-
button.textContent = 'context menu';
2017
}
21-
button.onmouseup = event => {
22-
if (![1,3,4].includes(event.button)) {
18+
event.preventDefault();
19+
button.textContent = 'context menu';
20+
}
21+
button.onmouseup = event => {
22+
if (![1,3,4].includes(event.button)) {
2323
return;
24-
}
25-
event.preventDefault();
26-
button.textContent = {
24+
}
25+
event.preventDefault();
26+
button.textContent = {
2727
3: 'back click',
2828
4: 'forward click',
2929
1: 'aux click',
30-
}[event.button];
31-
}
32-
document.body.appendChild(button);
33-
document.body.appendChild(document.createElement('br'));
30+
}[event.button];
3431
}
35-
</script>
36-
</body>
32+
document.body.appendChild(button);
33+
document.body.appendChild(document.createElement('br'));
34+
}
35+
</script>
36+
</body>
3737
</html>

‎lib/PuppeteerSharp.TestServer/wwwroot/input/textarea.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<title>Textarea test</title>
55
</head>
66
<body>
7-
<textarea></textarea>
7+
<textarea rows="5" cols="20"></textarea>
88
<script src='mouse-helper.js'></script>
99
<script>
1010
globalThis.result = '';

‎lib/PuppeteerSharp.Tests/BrowserTests/BrowserVersionTests.cs

+3-6
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@ namespace PuppeteerSharp.Tests.BrowserTests
66
{
77
public class BrowserVersionTests : PuppeteerBrowserBaseTest
88
{
9-
public BrowserVersionTests() : base()
10-
{
11-
}
12-
13-
[Test, Retry(2), PuppeteerTest("browser.spec", "Browser.version", "should return whether we are in headless")]
14-
public async Task ShouldReturnWhetherWeAreInHeadless()
9+
[Test, Retry(2), PuppeteerTest("browser.spec", "Browser.version", "should return version")]
10+
public async Task ShouldReturnVersion()
1511
{
1612
var version = await Browser.GetVersionAsync();
1713
Assert.IsNotEmpty(version);
14+
StringAssert.Contains(PuppeteerTestAttribute.IsChrome ? "chrome" : "firefox", version.ToLower());
1815
}
1916
}
2017
}

0 commit comments

Comments
 (0)
Please sign in to comment.