-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Run Blazor E2E tests on SauceLabs #18456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Uses Scheduled Triggers, which aren't supported in YAML yet. | ||
# https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=vsts&tabs=yaml#scheduled | ||
|
||
# Daily Tests for Blazor | ||
# These use Sauce Labs resources, hence they run daily rather than per-commit. | ||
|
||
# We just need one Windows machine because all it does is trigger SauceLabs. | ||
variables: | ||
SAUCE_CONNECT_DOWNLOAD_ON_INSTALL: true | ||
E2ETESTS_SauceTest: true | ||
E2ETESTS_Sauce__TunnelIdentifier: 'blazor-e2e-sc-proxy-tunnel' | ||
E2ETESTS_Sauce__HostName: 'sauce.local' | ||
jobs: | ||
- template: jobs/default-build.yml | ||
parameters: | ||
buildDirectory: src/Components | ||
isTestingJob: true | ||
agentOs: Windows | ||
jobName: BlazorDailyTests | ||
jobDisplayName: "Blazor Daily Tests" | ||
afterBuild: | ||
|
||
# macOS/Safari | ||
- script: 'dotnet test --filter "StandaloneAppTest"' | ||
workingDirectory: 'src/Components/test/E2ETest' | ||
displayName: 'Run Blazor tests - macOS/Safari' | ||
condition: succeededOrFailed() | ||
env: | ||
# Secrets need to be explicitly mapped to env variables. | ||
E2ETESTS_Sauce__Username: '$(asplab-sauce-labs-username)' | ||
E2ETESTS_Sauce__AccessKey: '$(asplab-sauce-labs-access-key)' | ||
# Set platform/browser configuration. | ||
E2ETESTS_Sauce__TestName: 'Blazor Daily Tests - macOS/Safari' | ||
E2ETESTS_Sauce__PlatformName: 'macOS 10.14' | ||
E2ETESTS_Sauce__BrowserName: 'Safari' | ||
# Need to explicitly set version here because some older versions don't support timeouts in Safari. | ||
E2ETESTS_Sauce__SeleniumVersion: '3.4.0' | ||
|
||
# Android/Chrome | ||
- script: 'dotnet test --filter "StandaloneAppTest"' | ||
workingDirectory: 'src/Components/test/E2ETest' | ||
displayName: 'Run Blazor tests - Android/Chrome' | ||
condition: succeededOrFailed() | ||
env: | ||
# Secrets need to be explicitly mapped to env variables. | ||
E2ETESTS_Sauce__Username: '$(asplab-sauce-labs-username)' | ||
E2ETESTS_Sauce__AccessKey: '$(asplab-sauce-labs-access-key)' | ||
# Set platform/browser configuration. | ||
E2ETESTS_Sauce__TestName: 'Blazor Daily Tests - Android/Chrome' | ||
E2ETESTS_Sauce__PlatformName: 'Android' | ||
E2ETESTS_Sauce__PlatformVersion: '10.0' | ||
E2ETESTS_Sauce__BrowserName: 'Chrome' | ||
E2ETESTS_Sauce__DeviceName: 'Android GoogleAPI Emulator' | ||
E2ETESTS_Sauce__DeviceOrientation: 'portrait' | ||
E2ETESTS_Sauce__AppiumVersion: '1.9.1' | ||
artifacts: | ||
- name: Windows_Logs | ||
path: ../../artifacts/log/ | ||
publishOnError: true |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -461,7 +461,7 @@ async Task GetDetails(int msg_id, int object_id, CancellationToken token, string | |
{ | ||
result = var_list | ||
}); | ||
} catch (Exception e) { | ||
} catch (Exception) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no beuno. We should fix this in Mono and flow it through. But given how small these changes are, I think we can live with this for now. |
||
Debug ($"failed to parse {res.Value}"); | ||
} | ||
SendResponse(msg_id, Result.Ok(o), token); | ||
|
@@ -534,7 +534,7 @@ async Task GetScopeProperties (int msg_id, int scope_id, CancellationToken token | |
}); | ||
SendResponse (msg_id, Result.Ok (o), token); | ||
} | ||
catch (Exception exc) { | ||
catch (Exception) { | ||
SendResponse (msg_id, res, token); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
{ | ||
"DefaultWaitTimeoutInSeconds": 20, | ||
"ScreenShotsPath": "../../screenshots" | ||
"ScreenShotsPath": "../../screenshots", | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { EOL } from "os"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this a typescript file? There's nothing typescript specific here and we shouldn't need typescript for something as simple as this. Can we change this to be a plain JavaScript file? Any recent version of node will handle modern javascript. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I took the easy path as we do similar things in SignalR which is in typescript. IMO there is no downside to using typescript for this. It is nicer :) |
||
import * as _fs from "fs"; | ||
import { promisify } from "util"; | ||
|
||
// Promisify things from fs we want to use. | ||
const fs = { | ||
createWriteStream: _fs.createWriteStream, | ||
exists: promisify(_fs.exists), | ||
mkdir: promisify(_fs.mkdir), | ||
appendFile: promisify(_fs.appendFile), | ||
readFile: promisify(_fs.readFile), | ||
}; | ||
|
||
process.on("unhandledRejection", (reason) => { | ||
console.error(`Unhandled promise rejection: ${reason}`); | ||
process.exit(1); | ||
}); | ||
|
||
let sauceUser = null; | ||
let sauceKey = null; | ||
let tunnelIdentifier = null; | ||
let hostName = null; | ||
|
||
for (let i = 0; i < process.argv.length; i += 1) { | ||
switch (process.argv[i]) { | ||
case "--sauce-user": | ||
i += 1; | ||
sauceUser = process.argv[i]; | ||
break; | ||
case "--sauce-key": | ||
i += 1; | ||
sauceKey = process.argv[i]; | ||
break; | ||
case "--sauce-tunnel": | ||
i += 1; | ||
tunnelIdentifier = process.argv[i]; | ||
break; | ||
case "--use-hostname": | ||
i += 1; | ||
hostName = process.argv[i]; | ||
break; | ||
} | ||
} | ||
|
||
const HOSTSFILE_PATH = process.platform === "win32" ? `${process.env.SystemRoot}\\System32\\drivers\\etc\\hosts` : null; | ||
|
||
(async () => { | ||
|
||
if (hostName) { | ||
// Register a custom hostname in the hosts file (requires Admin, but AzDO agents run as Admin) | ||
// Used to work around issues in Sauce Labs. | ||
if (process.platform !== "win32") { | ||
throw new Error("Can't use '--use-hostname' on non-Windows platform."); | ||
} | ||
|
||
try { | ||
|
||
console.log(`Updating Hosts file (${HOSTSFILE_PATH}) to register host name '${hostName}'`); | ||
await fs.appendFile(HOSTSFILE_PATH, `${EOL}127.0.0.1 ${hostName}${EOL}`); | ||
|
||
} catch (error) { | ||
console.log(`Unable to update hosts file at ${HOSTSFILE_PATH}. Error: ${error}`); | ||
} | ||
} | ||
|
||
|
||
// Creates a persistent proxy tunnel using Sauce Connect. | ||
var sauceConnectLauncher = require('sauce-connect-launcher'); | ||
|
||
sauceConnectLauncher({ | ||
username: sauceUser, | ||
accessKey: sauceKey, | ||
tunnelIdentifier: tunnelIdentifier, | ||
}, function (err, sauceConnectProcess) { | ||
if (err) { | ||
console.error(err.message); | ||
return; | ||
} | ||
|
||
console.log("Sauce Connect ready"); | ||
}); | ||
})(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy to start with this, but is there a limitation that requires this?