UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

235 lines (192 loc) 5.47 kB
import fse from 'fs-extra' import os from 'os' import { join, normalize, win32 } from 'path' import { tap, trim, prop } from 'ramda' import { get } from 'lodash' import { notInstalledErr } from '../errors' import { log } from '../log' import { Browser, FoundBrowser, PathData } from '../types' import { utils } from '../utils' function formFullAppPath (name: string) { return [ `C:/Program Files (x86)/Google/Chrome/Application/${name}.exe`, `C:/Program Files/Google/Chrome/Application/${name}.exe`, ].map(normalize) } function formChromiumAppPath () { const exe = 'C:/Program Files (x86)/Google/chrome-win32/chrome.exe' return [normalize(exe)] } function formChromeCanaryAppPath () { const home = os.homedir() const exe = join( home, 'AppData', 'Local', 'Google', 'Chrome SxS', 'Application', 'chrome.exe', ) return [normalize(exe)] } function getFirefoxPaths (editionFolder) { return () => { return (['Program Files', 'Program Files (x86)']) .map((programFiles) => { return normalize(`C:/${programFiles}/${editionFolder}/firefox.exe`) }) .concat(normalize(join( os.homedir(), 'AppData', 'Local', editionFolder, 'firefox.exe', ))) } } function formEdgeCanaryAppPath () { const home = os.homedir() const exe = join( home, 'AppData', 'Local', 'Microsoft', 'Edge SxS', 'Application', 'msedge.exe', ) return [normalize(exe)] } type NameToPath = (name: string) => string[] type WindowsBrowserPaths = { [name: string]: { [channel: string]: NameToPath } } const formPaths: WindowsBrowserPaths = { chrome: { stable: formFullAppPath, canary: formChromeCanaryAppPath, }, chromium: { stable: formChromiumAppPath, }, firefox: { stable: getFirefoxPaths('Mozilla Firefox'), dev: getFirefoxPaths('Firefox Developer Edition'), nightly: getFirefoxPaths('Firefox Nightly'), }, edge: { stable: () => { return [normalize('C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe')] }, beta: () => { return [normalize('C:/Program Files (x86)/Microsoft/Edge Beta/Application/msedge.exe')] }, dev: () => { return [normalize('C:/Program Files (x86)/Microsoft/Edge Dev/Application/msedge.exe')] }, canary: formEdgeCanaryAppPath, }, } function getWindowsBrowser (browser: Browser): Promise<FoundBrowser> { const getVersion = (stdout: string): string => { // result from wmic datafile // "Version=61.0.3163.100" const wmicVersion = /^Version=(\S+)$/ const m = wmicVersion.exec(stdout) if (m) { return m[1] } log('Could not extract version from %s using regex %s', stdout, wmicVersion) throw notInstalledErr(browser.name) } const formFullAppPathFn: NameToPath = get(formPaths, [browser.name, browser.channel], formFullAppPath) const exePaths = formFullAppPathFn(browser.name) log('looking at possible paths... %o', { browser, exePaths }) // shift and try paths 1-by-1 until we find one that works const tryNextExePath = async () => { const exePath = exePaths.shift() if (!exePath) { // exhausted available paths throw notInstalledErr(browser.name) } let path = doubleEscape(exePath) return fse.pathExists(path) .then((exists) => { log('found %s ?', path, exists) if (!exists) { return tryNextExePath() } return getVersionString(path) .then(tap(log)) .then(getVersion) .then((version: string) => { log('browser %s at \'%s\' version %s', browser.name, exePath, version) return { name: browser.name, version, path: exePath, } as FoundBrowser }) }) .catch((err) => { log('error while looking up exe, trying next exePath %o', { exePath, exePaths, err }) return tryNextExePath() }) } return tryNextExePath() } export function doubleEscape (s: string) { // Converts all types of paths into windows supported double backslash path // Handles any number of \\ in the given path return win32.join(...s.split(win32.sep)).replace(/\\/g, '\\\\') } export function getVersionString (path: string) { // on Windows using "--version" seems to always start the full // browser, no matter what one does. const args = [ 'datafile', 'where', `name="${path}"`, 'get', 'Version', '/value', ] return utils.execa('wmic', args) .then(prop('stdout')) .then(trim) } export function getVersionNumber (version: string) { if (version.indexOf('Version=') > -1) { return version.split('=')[1] } return version } export function getPathData (pathStr: string): PathData { const test = new RegExp(/^.+\.exe:(.+)$/) const res = test.exec(pathStr) let browserKey = '' let path = pathStr if (res) { const pathParts = path.split(':') browserKey = pathParts.pop() || '' path = doubleEscape(pathParts.join(':')) return { path, browserKey } } path = doubleEscape(path) if (pathStr.indexOf('chrome.exe') > -1) { return { path, browserKey: 'chrome' } } if (pathStr.indexOf('edge.exe') > -1) { return { path, browserKey: 'edge' } } if (pathStr.indexOf('firefox.exe') > -1) { return { path, browserKey: 'firefox' } } return { path } } export function detect (browser: Browser) { return getWindowsBrowser(browser) }