mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-05 19:04:43 +03:00
feat: support npx playwright install msedge
(#6861)
This commit is contained in:
parent
46a0213769
commit
cfd49b5c01
27
.github/workflows/tests_secondary.yml
vendored
27
.github/workflows/tests_secondary.yml
vendored
@ -333,6 +333,31 @@ jobs:
|
||||
name: firefox-stable-mac-test-results
|
||||
path: test-results
|
||||
|
||||
edge_stable_mac:
|
||||
name: "Edge Stable (Mac)"
|
||||
runs-on: macos-10.15
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 12
|
||||
- run: npm ci
|
||||
env:
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
- run: npm run build
|
||||
- run: node lib/cli/cli install msedge
|
||||
- run: npm run ctest
|
||||
env:
|
||||
PWTEST_CHANNEL: msedge
|
||||
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
||||
if: always()
|
||||
- uses: actions/upload-artifact@v1
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: msedge-stable-mac-test-results
|
||||
path: test-results
|
||||
|
||||
|
||||
edge_stable_win:
|
||||
name: "Edge Stable (Win)"
|
||||
runs-on: windows-latest
|
||||
@ -345,7 +370,7 @@ jobs:
|
||||
env:
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
- run: npm run build
|
||||
- run: node lib/cli/cli install ffmpeg
|
||||
- run: node lib/cli/cli install msedge
|
||||
- run: npm run ctest
|
||||
shell: bash
|
||||
env:
|
||||
|
@ -13,3 +13,4 @@ wget https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb
|
||||
sudo apt-get install -y ./google-chrome-beta_current_amd64.deb
|
||||
rm -rf ./google-chrome-beta_current_amd64.deb
|
||||
cd -
|
||||
google-chrome-beta --version
|
||||
|
@ -8,3 +8,6 @@ curl -o ./googlechromebeta.dmg -k https://dl.google.com/chrome/mac/beta/googlech
|
||||
hdiutil attach -nobrowse -quiet -noautofsck -noautoopen -mountpoint /Volumes/googlechromebeta.dmg ./googlechromebeta.dmg
|
||||
cp -rf "/Volumes/googlechromebeta.dmg/Google Chrome Beta.app" /Applications
|
||||
hdiutil detach /Volumes/googlechromebeta.dmg
|
||||
rm -rf /tmp/googlechromebeta.dmg
|
||||
|
||||
/Applications/Google\ Chrome\ Beta.app/Contents/MacOS/Google\ Chrome\ Beta --version
|
||||
|
@ -4,17 +4,22 @@ if ([Environment]::Is64BitProcess) {
|
||||
$url = 'https://dl.google.com/tag/s/dl/chrome/install/beta/googlechromebetastandaloneenterprise64.msi'
|
||||
}
|
||||
|
||||
$app = Get-WmiObject -Class Win32_Product | Where-Object {
|
||||
$_.Name -match "Google Chrome Beta"
|
||||
}
|
||||
if ($app) {
|
||||
$app.Uninstall()
|
||||
}
|
||||
|
||||
Write-Host "Downloading Google Chrome Beta"
|
||||
$wc = New-Object net.webclient
|
||||
$msiInstaller = "$env:temp\google-chrome-beta.msi"
|
||||
Remove-Item $msiInstaller
|
||||
$wc.Downloadfile($url, $msiInstaller)
|
||||
|
||||
Write-Host "Installing Google Chrome Beta"
|
||||
$arguments = "/i `"$msiInstaller`" /quiet"
|
||||
Start-Process msiexec.exe -ArgumentList $arguments -Wait
|
||||
Remove-Item $msiInstaller
|
||||
|
||||
$suffix = "\\Google\\Chrome Beta\\Application\\chrome.exe"
|
||||
if (Test-Path "${env:ProgramFiles(x86)}$suffix") {
|
||||
(Get-Item "${env:ProgramFiles(x86)}$suffix").VersionInfo
|
||||
} elseif (Test-Path "${env:ProgramFiles}$suffix") {
|
||||
(Get-Item "${env:ProgramFiles}$suffix").VersionInfo
|
||||
} else {
|
||||
write-host "ERROR: failed to install Google Chrome Beta"
|
||||
exit 1
|
||||
}
|
||||
|
@ -14,3 +14,4 @@ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
sudo apt-get install -y ./google-chrome-stable_current_amd64.deb
|
||||
rm -rf ./google-chrome-stable_current_amd64.deb
|
||||
cd -
|
||||
google-chrome --version
|
||||
|
@ -4,7 +4,9 @@ set -x
|
||||
|
||||
rm -rf "/Applications/Google Chrome.app"
|
||||
cd /tmp
|
||||
curl -o ./googlechrome.dmg -k https://dl.google.com/chrome/mac/beta/googlechrome.dmg
|
||||
curl -o ./googlechrome.dmg -k https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg
|
||||
hdiutil attach -nobrowse -quiet -noautofsck -noautoopen -mountpoint /Volumes/googlechrome.dmg ./googlechrome.dmg
|
||||
cp -rf "/Volumes/googlechrome.dmg/Google Chrome.app" /Applications
|
||||
hdiutil detach /Volumes/googlechrome.dmg
|
||||
rm -rf /tmp/googlechrome.dmg
|
||||
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version
|
||||
|
@ -1,20 +1,26 @@
|
||||
$url = 'https://dl.google.com/tag/s/dl/chrome/install/beta/googlechromestandaloneenterprise.msi';
|
||||
$url = 'https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise.msi';
|
||||
|
||||
if ([Environment]::Is64BitProcess) {
|
||||
$url = 'https://dl.google.com/tag/s/dl/chrome/install/beta/googlechromestandaloneenterprise64.msi'
|
||||
}
|
||||
|
||||
$app = Get-WmiObject -Class Win32_Product | Where-Object {
|
||||
$_.Name -eq "Google Chrome"
|
||||
}
|
||||
if ($app) {
|
||||
$app.Uninstall()
|
||||
$url = 'https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi'
|
||||
}
|
||||
|
||||
$wc = New-Object net.webclient
|
||||
$msiInstaller = "$env:temp\google-chrome.msi"
|
||||
Remove-Item $msiInstaller
|
||||
Write-Host "Downloading Google Chrome"
|
||||
$wc.Downloadfile($url, $msiInstaller)
|
||||
|
||||
Write-Host "Installing Google Chrome"
|
||||
$arguments = "/i `"$msiInstaller`" /quiet"
|
||||
Start-Process msiexec.exe -ArgumentList $arguments -Wait
|
||||
Remove-Item $msiInstaller
|
||||
|
||||
|
||||
$suffix = "\\Google\\Chrome\\Application\\chrome.exe"
|
||||
if (Test-Path "${env:ProgramFiles(x86)}$suffix") {
|
||||
(Get-Item "${env:ProgramFiles(x86)}$suffix").VersionInfo
|
||||
} elseif (Test-Path "${env:ProgramFiles}$suffix") {
|
||||
(Get-Item "${env:ProgramFiles}$suffix").VersionInfo
|
||||
} else {
|
||||
write-host "ERROR: failed to install Google Chrome"
|
||||
exit 1
|
||||
}
|
||||
|
11
bin/reinstall_msedge_stable_mac.sh
Executable file
11
bin/reinstall_msedge_stable_mac.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
set -x
|
||||
|
||||
cd /tmp
|
||||
curl -o ./msedge_stable.pkg -k "$1"
|
||||
# Note: there's no way to uninstall previously installed MSEdge.
|
||||
# However, running PKG again seems to update installation.
|
||||
sudo installer -pkg /tmp/msedge_stable.pkg -target /
|
||||
rm -rf /tmp/msedge_stable.pkg
|
||||
/Applications/Microsoft\ Edge.app/Contents/MacOS/Microsoft\ Edge --version
|
21
bin/reinstall_msedge_stable_win.ps1
Normal file
21
bin/reinstall_msedge_stable_win.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
$url = $args[0]
|
||||
|
||||
Write-Host "Downloading Microsoft Edge"
|
||||
$wc = New-Object net.webclient
|
||||
$msiInstaller = "$env:temp\microsoft-edge-stable.msi"
|
||||
$wc.Downloadfile($url, $msiInstaller)
|
||||
|
||||
Write-Host "Installing Microsoft Edge"
|
||||
$arguments = "/i `"$msiInstaller`" /quiet"
|
||||
Start-Process msiexec.exe -ArgumentList $arguments -Wait
|
||||
Remove-Item $msiInstaller
|
||||
|
||||
$suffix = "\\Microsoft\\Edge\\Application\\msedge.exe"
|
||||
if (Test-Path "${env:ProgramFiles(x86)}$suffix") {
|
||||
(Get-Item "${env:ProgramFiles(x86)}$suffix").VersionInfo
|
||||
} elseif (Test-Path "${env:ProgramFiles}$suffix") {
|
||||
(Get-Item "${env:ProgramFiles}$suffix").VersionInfo
|
||||
} else {
|
||||
write-host "ERROR: failed to install Microsoft Edge"
|
||||
exit 1
|
||||
}
|
@ -39,10 +39,34 @@ import * as utils from '../utils/utils';
|
||||
|
||||
const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');
|
||||
|
||||
type BrowserChannel = 'chrome-beta'|'chrome';
|
||||
const allBrowserChannels: Set<BrowserChannel> = new Set(['chrome-beta', 'chrome']);
|
||||
|
||||
type BrowserChannel = 'chrome-beta'|'chrome'|'msedge';
|
||||
const allBrowserChannels: Set<BrowserChannel> = new Set(['chrome-beta', 'chrome', 'msedge']);
|
||||
const packageJSON = require('../../package.json');
|
||||
|
||||
const ChannelName = {
|
||||
'chrome-beta': 'Google Chrome Beta',
|
||||
'chrome': 'Google Chrome',
|
||||
'msedge': 'Microsoft Edge',
|
||||
};
|
||||
|
||||
const InstallationScriptName = {
|
||||
'chrome-beta': {
|
||||
'linux': 'reinstall_chrome_beta_linux.sh',
|
||||
'darwin': 'reinstall_chrome_beta_mac.sh',
|
||||
'win32': 'reinstall_chrome_beta_win.ps1',
|
||||
},
|
||||
'chrome': {
|
||||
'linux': 'reinstall_chrome_stable_linux.sh',
|
||||
'darwin': 'reinstall_chrome_stable_mac.sh',
|
||||
'win32': 'reinstall_chrome_stable_win.ps1',
|
||||
},
|
||||
'msedge': {
|
||||
'darwin': 'reinstall_msedge_stable_mac.sh',
|
||||
'win32': 'reinstall_msedge_stable_win.ps1',
|
||||
},
|
||||
};
|
||||
|
||||
program
|
||||
.version('Version ' + packageJSON.version)
|
||||
.name(process.env.PW_CLI_NAME || 'npx playwright');
|
||||
@ -107,47 +131,46 @@ program
|
||||
console.log(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${[...allBrowserNames, ...allBrowserChannels].map(name => `'${name}'`).join(', ')}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (browserNames.has('chromium') || browserChannels.has('chrome-beta') || browserChannels.has('chrome'))
|
||||
if (browserNames.has('chromium') || browserChannels.has('chrome-beta') || browserChannels.has('chrome') || browserChannels.has('msedge'))
|
||||
browserNames.add('ffmpeg');
|
||||
if (browserNames.size)
|
||||
await installBrowsers([...browserNames]);
|
||||
for (const browserChannel of browserChannels) {
|
||||
if (browserChannel === 'chrome-beta' || browserChannel === 'chrome')
|
||||
await installChromeChannel(browserChannel);
|
||||
else
|
||||
throw new Error(`ERROR: no installation instructions for '${browserChannel}' channel.`);
|
||||
}
|
||||
for (const browserChannel of browserChannels)
|
||||
await installBrowserChannel(browserChannel);
|
||||
} catch (e) {
|
||||
console.log(`Failed to install browsers\n${e}`);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
async function installChromeChannel(channel: string) {
|
||||
const platform: string = os.platform();
|
||||
const shell: (string|undefined) = {
|
||||
'linux': 'bash',
|
||||
'darwin': 'bash',
|
||||
'win32': 'powershell.exe',
|
||||
}[platform];
|
||||
const scriptName: (string|undefined) = ({
|
||||
'chrome-beta': {
|
||||
'linux': 'reinstall_chrome_beta_linux.sh',
|
||||
'darwin': 'reinstall_chrome_beta_mac.sh',
|
||||
'win32': 'reinstall_chrome_beta_win.ps1',
|
||||
},
|
||||
'chrome': {
|
||||
'linux': 'reinstall_chrome_stable_linux.sh',
|
||||
'darwin': 'reinstall_chrome_stable_mac.sh',
|
||||
'win32': 'reinstall_chrome_stable_win.ps1',
|
||||
},
|
||||
}[channel] as any)[platform];
|
||||
if (!shell || !scriptName)
|
||||
throw new Error(`Cannot install chrome-beta on ${platform}`);
|
||||
async function installBrowserChannel(channel: BrowserChannel) {
|
||||
const platform = os.platform();
|
||||
const scriptName: (string|undefined) = (InstallationScriptName[channel] as any)[platform];
|
||||
if (!scriptName)
|
||||
throw new Error(`Cannot install ${ChannelName[channel]} on ${platform}`);
|
||||
|
||||
const {code} = await utils.spawnAsync(shell, [path.join(SCRIPTS_DIRECTORY, scriptName)], { cwd: SCRIPTS_DIRECTORY, stdio: 'inherit' });
|
||||
const scriptArgs = [];
|
||||
if (channel === 'msedge') {
|
||||
const products = JSON.parse(await utils.fetchData('https://edgeupdates.microsoft.com/api/products'));
|
||||
const stable = products.find((product: any) => product.Product === 'Stable');
|
||||
if (platform === 'win32') {
|
||||
const arch = os.arch() === 'x64' ? 'x64' : 'x86';
|
||||
const release = stable.Releases.find((release: any) => release.Platform === 'Windows' && release.Architecture === arch);
|
||||
const artifact = release.Artifacts.find((artifact: any) => artifact.ArtifactName === 'msi');
|
||||
scriptArgs.push(artifact.Location /* url */);
|
||||
} else if (platform === 'darwin') {
|
||||
const release = stable.Releases.find((release: any) => release.Platform === 'MacOS' && release.Architecture === 'universal');
|
||||
const artifact = release.Artifacts.find((artifact: any) => artifact.ArtifactName === 'pkg');
|
||||
scriptArgs.push(artifact.Location /* url */);
|
||||
} else {
|
||||
throw new Error(`Cannot install ${ChannelName[channel]} on ${platform}`);
|
||||
}
|
||||
}
|
||||
|
||||
const shell = scriptName.endsWith('.ps1') ? 'powershell.exe' : 'bash';
|
||||
const {code} = await utils.spawnAsync(shell, [path.join(SCRIPTS_DIRECTORY, scriptName), ...scriptArgs], { cwd: SCRIPTS_DIRECTORY, stdio: 'inherit' });
|
||||
if (code !== 0)
|
||||
throw new Error('Failed to install chrome-beta');
|
||||
throw new Error(`Failed to install ${ChannelName[channel]}`);
|
||||
}
|
||||
|
||||
program
|
||||
|
@ -20,24 +20,10 @@ import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import ProgressBar from 'progress';
|
||||
import { getProxyForUrl } from 'proxy-from-env';
|
||||
import * as URL from 'url';
|
||||
import { BrowserName, Registry, hostPlatform } from '../utils/registry';
|
||||
import { downloadFile, existsAsync } from '../utils/utils';
|
||||
import { debugLogger } from '../utils/debugLogger';
|
||||
|
||||
// `https-proxy-agent` v5 is written in TypeScript and exposes generated types.
|
||||
// However, as of June 2020, its types are generated with tsconfig that enables
|
||||
// `esModuleInterop` option.
|
||||
//
|
||||
// As a result, we can't depend on the package unless we enable the option
|
||||
// for our codebase. Instead of doing this, we abuse "require" to import module
|
||||
// without types.
|
||||
const ProxyAgent = require('https-proxy-agent');
|
||||
|
||||
const existsAsync = (path: string): Promise<boolean> => new Promise(resolve => fs.stat(path, err => resolve(!err)));
|
||||
|
||||
export type OnProgressCallback = (downloadedBytes: number, totalBytes: number) => void;
|
||||
|
||||
export async function downloadBrowserWithProgressBar(registry: Registry, browserName: BrowserName): Promise<boolean> {
|
||||
const browserDirectory = registry.browserDirectory(browserName);
|
||||
const progressBarName = `${browserName} v${registry.revision(browserName)}`;
|
||||
@ -71,7 +57,7 @@ export async function downloadBrowserWithProgressBar(registry: Registry, browser
|
||||
try {
|
||||
for (let attempt = 1, N = 3; attempt <= N; ++attempt) {
|
||||
debugLogger.log('install', `downloading ${progressBarName} - attempt #${attempt}`);
|
||||
const {error} = await downloadFile(url, zipPath, progress);
|
||||
const {error} = await downloadFile(url, zipPath, {progressCallback: progress, log: debugLogger.log.bind(debugLogger, 'install')});
|
||||
if (!error) {
|
||||
debugLogger.log('install', `SUCCESS downloading ${progressBarName}`);
|
||||
break;
|
||||
@ -111,77 +97,6 @@ function toMegabytes(bytes: number) {
|
||||
return `${Math.round(mb * 10) / 10} Mb`;
|
||||
}
|
||||
|
||||
function downloadFile(url: string, destinationPath: string, progressCallback: OnProgressCallback | undefined): Promise<{error: any}> {
|
||||
debugLogger.log('install', `running download:`);
|
||||
debugLogger.log('install', `-- from url: ${url}`);
|
||||
debugLogger.log('install', `-- to location: ${destinationPath}`);
|
||||
let fulfill: ({error}: {error: any}) => void = ({error}) => {};
|
||||
let downloadedBytes = 0;
|
||||
let totalBytes = 0;
|
||||
|
||||
const promise: Promise<{error: any}> = new Promise(x => { fulfill = x; });
|
||||
|
||||
const request = httpRequest(url, 'GET', response => {
|
||||
if (response.statusCode !== 200) {
|
||||
const error = new Error(`Download failed: server returned code ${response.statusCode}. URL: ${url}`);
|
||||
// consume response data to free up memory
|
||||
response.resume();
|
||||
fulfill({error});
|
||||
return;
|
||||
}
|
||||
const file = fs.createWriteStream(destinationPath);
|
||||
file.on('finish', () => fulfill({error: null}));
|
||||
file.on('error', error => fulfill({error}));
|
||||
response.pipe(file);
|
||||
totalBytes = parseInt(response.headers['content-length'], 10);
|
||||
debugLogger.log('install', `-- total bytes: ${totalBytes}`);
|
||||
if (progressCallback)
|
||||
response.on('data', onData);
|
||||
});
|
||||
request.on('error', (error: any) => fulfill({error}));
|
||||
return promise;
|
||||
|
||||
function onData(chunk: string) {
|
||||
downloadedBytes += chunk.length;
|
||||
progressCallback!(downloadedBytes, totalBytes);
|
||||
}
|
||||
}
|
||||
|
||||
function httpRequest(url: string, method: string, response: (r: any) => void) {
|
||||
let options: any = URL.parse(url);
|
||||
options.method = method;
|
||||
|
||||
const proxyURL = getProxyForUrl(url);
|
||||
if (proxyURL) {
|
||||
if (url.startsWith('http:')) {
|
||||
const proxy = URL.parse(proxyURL);
|
||||
options = {
|
||||
path: options.href,
|
||||
host: proxy.hostname,
|
||||
port: proxy.port,
|
||||
};
|
||||
} else {
|
||||
const parsedProxyURL: any = URL.parse(proxyURL);
|
||||
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:';
|
||||
|
||||
options.agent = new ProxyAgent(parsedProxyURL);
|
||||
options.rejectUnauthorized = false;
|
||||
}
|
||||
}
|
||||
|
||||
const requestCallback = (res: any) => {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location)
|
||||
httpRequest(res.headers.location, method, response);
|
||||
else
|
||||
response(res);
|
||||
};
|
||||
const request = options.protocol === 'https:' ?
|
||||
require('https').request(options, requestCallback) :
|
||||
require('http').request(options, requestCallback);
|
||||
request.end();
|
||||
return request;
|
||||
}
|
||||
|
||||
export function logPolitely(toBeLogged: string) {
|
||||
const logLevel = process.env.npm_config_loglevel;
|
||||
const logLevelDisplay = ['silent', 'error', 'warn'].indexOf(logLevel || '') > -1;
|
||||
|
@ -27,12 +27,11 @@ import { Progress, ProgressController } from './progress';
|
||||
import * as types from './types';
|
||||
import { DEFAULT_TIMEOUT, TimeoutSettings } from '../utils/timeoutSettings';
|
||||
import { validateHostRequirements } from './validateDependencies';
|
||||
import { debugMode } from '../utils/utils';
|
||||
import { debugMode, existsAsync } from '../utils/utils';
|
||||
import { helper } from './helper';
|
||||
import { RecentLogsCollector } from '../utils/debugLogger';
|
||||
import { CallMetadata, SdkObject } from './instrumentation';
|
||||
|
||||
const existsAsync = (path: string): Promise<boolean> => new Promise(resolve => fs.stat(path, err => resolve(!err)));
|
||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||
|
||||
export abstract class BrowserType extends SdkObject {
|
||||
|
@ -23,9 +23,7 @@ import { EventEmitter } from 'events';
|
||||
import { internalCallMetadata } from '../../instrumentation';
|
||||
import type { CallLog, EventData, Mode, Source } from './recorderTypes';
|
||||
import { BrowserContext } from '../../browserContext';
|
||||
import { isUnderTest } from '../../../utils/utils';
|
||||
|
||||
const existsAsync = (path: string): Promise<boolean> => new Promise(resolve => fs.stat(path, err => resolve(!err)));
|
||||
import { existsAsync, isUnderTest } from '../../../utils/utils';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -20,6 +20,113 @@ import removeFolder from 'rimraf';
|
||||
import * as crypto from 'crypto';
|
||||
import os from 'os';
|
||||
import { spawn } from 'child_process';
|
||||
import { getProxyForUrl } from 'proxy-from-env';
|
||||
import * as URL from 'url';
|
||||
|
||||
// `https-proxy-agent` v5 is written in TypeScript and exposes generated types.
|
||||
// However, as of June 2020, its types are generated with tsconfig that enables
|
||||
// `esModuleInterop` option.
|
||||
//
|
||||
// As a result, we can't depend on the package unless we enable the option
|
||||
// for our codebase. Instead of doing this, we abuse "require" to import module
|
||||
// without types.
|
||||
const ProxyAgent = require('https-proxy-agent');
|
||||
|
||||
export const existsAsync = (path: string): Promise<boolean> => new Promise(resolve => fs.stat(path, err => resolve(!err)));
|
||||
|
||||
function httpRequest(url: string, method: string, response: (r: any) => void) {
|
||||
let options: any = URL.parse(url);
|
||||
options.method = method;
|
||||
|
||||
const proxyURL = getProxyForUrl(url);
|
||||
if (proxyURL) {
|
||||
if (url.startsWith('http:')) {
|
||||
const proxy = URL.parse(proxyURL);
|
||||
options = {
|
||||
path: options.href,
|
||||
host: proxy.hostname,
|
||||
port: proxy.port,
|
||||
};
|
||||
} else {
|
||||
const parsedProxyURL: any = URL.parse(proxyURL);
|
||||
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:';
|
||||
|
||||
options.agent = new ProxyAgent(parsedProxyURL);
|
||||
options.rejectUnauthorized = false;
|
||||
}
|
||||
}
|
||||
|
||||
const requestCallback = (res: any) => {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location)
|
||||
httpRequest(res.headers.location, method, response);
|
||||
else
|
||||
response(res);
|
||||
};
|
||||
const request = options.protocol === 'https:' ?
|
||||
require('https').request(options, requestCallback) :
|
||||
require('http').request(options, requestCallback);
|
||||
request.end();
|
||||
return request;
|
||||
}
|
||||
|
||||
export function fetchData(url: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
httpRequest(url, 'GET', function(response){
|
||||
if (response.statusCode !== 200) {
|
||||
reject(new Error(`fetch failed: server returned code ${response.statusCode}. URL: ${url}`));
|
||||
return;
|
||||
}
|
||||
let body = '';
|
||||
response.on('data', (chunk: string) => body += chunk);
|
||||
response.on('error', (error: any) => reject(error));
|
||||
response.on('end', () => resolve(body));
|
||||
}).on('error', (error: any) => reject(error));
|
||||
});
|
||||
}
|
||||
|
||||
type OnProgressCallback = (downloadedBytes: number, totalBytes: number) => void;
|
||||
type DownloadFileLogger = (message: string) => void;
|
||||
|
||||
export function downloadFile(url: string, destinationPath: string, options : {progressCallback?: OnProgressCallback, log?: DownloadFileLogger} = {}): Promise<{error: any}> {
|
||||
const {
|
||||
progressCallback,
|
||||
log = () => {},
|
||||
} = options;
|
||||
log(`running download:`);
|
||||
log(`-- from url: ${url}`);
|
||||
log(`-- to location: ${destinationPath}`);
|
||||
let fulfill: ({error}: {error: any}) => void = ({error}) => {};
|
||||
let downloadedBytes = 0;
|
||||
let totalBytes = 0;
|
||||
|
||||
const promise: Promise<{error: any}> = new Promise(x => { fulfill = x; });
|
||||
|
||||
const request = httpRequest(url, 'GET', response => {
|
||||
log(`-- response status code: ${response.statusCode}`);
|
||||
if (response.statusCode !== 200) {
|
||||
const error = new Error(`Download failed: server returned code ${response.statusCode}. URL: ${url}`);
|
||||
// consume response data to free up memory
|
||||
response.resume();
|
||||
fulfill({error});
|
||||
return;
|
||||
}
|
||||
const file = fs.createWriteStream(destinationPath);
|
||||
file.on('finish', () => fulfill({error: null}));
|
||||
file.on('error', error => fulfill({error}));
|
||||
response.pipe(file);
|
||||
totalBytes = parseInt(response.headers['content-length'], 10);
|
||||
log(`-- total bytes: ${totalBytes}`);
|
||||
if (progressCallback)
|
||||
response.on('data', onData);
|
||||
});
|
||||
request.on('error', (error: any) => fulfill({error}));
|
||||
return promise;
|
||||
|
||||
function onData(chunk: string) {
|
||||
downloadedBytes += chunk.length;
|
||||
progressCallback!(downloadedBytes, totalBytes);
|
||||
}
|
||||
}
|
||||
|
||||
export function spawnAsync(cmd: string, args: string[], options: any): Promise<{stdout: string, stderr: string, code: number, error?: Error}> {
|
||||
const process = spawn(cmd, args, options);
|
||||
|
@ -148,6 +148,7 @@ it('Page.bringToFront should work', async ({browserType, browserOptions}) => {
|
||||
});
|
||||
|
||||
it('focused input should produce the same screenshot', async ({browserType, browserOptions, browserName, platform, channel}, testInfo) => {
|
||||
it.fail(channel === 'msedge' && platform === 'darwin', 'focus ring is black on MSEdge');
|
||||
it.fail(browserName === 'firefox' && platform === 'darwin', 'headless has thinner outline');
|
||||
it.fail(browserName === 'firefox' && platform === 'linux', 'headless has no outline');
|
||||
it.skip(browserName === 'webkit' && platform === 'linux', 'gtk vs wpe');
|
||||
|
Loading…
Reference in New Issue
Block a user