mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-12 10:10:32 -06:00
@@ -1,13 +1,17 @@
|
||||
import {log} from './log'
|
||||
import {find, map} from 'lodash'
|
||||
import cp = require('child_process')
|
||||
import {Browser, FoundBrowser, BrowserNotFoundError} from './types'
|
||||
import { log } from './log'
|
||||
import { find, map } from 'lodash'
|
||||
import * as cp from 'child_process'
|
||||
import { Browser, FoundBrowser, BrowserNotFoundError } from './types'
|
||||
|
||||
const browserNotFoundErr = (browsers: FoundBrowser[], name: string): BrowserNotFoundError => {
|
||||
const browserNotFoundErr = (
|
||||
browsers: FoundBrowser[],
|
||||
name: string
|
||||
): BrowserNotFoundError => {
|
||||
const available = map(browsers, 'name').join(', ')
|
||||
|
||||
const err: BrowserNotFoundError
|
||||
= new Error(`Browser: '${name}' not found. Available browsers are: [${available}]`) as BrowserNotFoundError
|
||||
const err: BrowserNotFoundError = new Error(
|
||||
`Browser: '${name}' not found. Available browsers are: [${available}]`
|
||||
) as BrowserNotFoundError
|
||||
err.specificBrowserNotFound = true
|
||||
return err
|
||||
}
|
||||
@@ -34,13 +38,15 @@ export const browsers: Browser[] = [
|
||||
versionRegex: /Google Chrome (\S+)/,
|
||||
profile: true,
|
||||
binary: 'google-chrome'
|
||||
},{
|
||||
},
|
||||
{
|
||||
name: 'chromium',
|
||||
displayName: 'Chromium',
|
||||
versionRegex: /Chromium (\S+)/,
|
||||
profile: true,
|
||||
binary: 'chromium-browser'
|
||||
},{
|
||||
},
|
||||
{
|
||||
name: 'canary',
|
||||
displayName: 'Canary',
|
||||
versionRegex: /Google Chrome Canary (\S+)/,
|
||||
@@ -53,10 +59,14 @@ export const browsers: Browser[] = [
|
||||
]
|
||||
|
||||
/** starts a browser by name and opens URL if given one */
|
||||
export function launch (browsers: FoundBrowser[],
|
||||
name: string, url?: string, args: string[] = []) {
|
||||
export function launch(
|
||||
browsers: FoundBrowser[],
|
||||
name: string,
|
||||
url?: string,
|
||||
args: string[] = []
|
||||
) {
|
||||
log('launching browser %s to open %s', name, url)
|
||||
const browser = find(browsers, {name})
|
||||
const browser = find(browsers, { name })
|
||||
|
||||
if (!browser) {
|
||||
throw browserNotFoundErr(browsers, name)
|
||||
@@ -71,5 +81,5 @@ export function launch (browsers: FoundBrowser[],
|
||||
}
|
||||
|
||||
log('spawning browser %s with args %s', browser.path, args.join(' '))
|
||||
return cp.spawn(browser.path, args, {stdio: 'ignore'})
|
||||
return cp.spawn(browser.path, args, { stdio: 'ignore' })
|
||||
}
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
import {findApp} from './util'
|
||||
import {Browser} from '../types'
|
||||
import {detectBrowserLinux} from '../linux'
|
||||
import {log} from '../log'
|
||||
import {merge, partial} from 'ramda'
|
||||
import { findApp } from './util'
|
||||
import { Browser } from '../types'
|
||||
import { detectBrowserLinux } from '../linux'
|
||||
import { log } from '../log'
|
||||
import { merge, partial } from 'ramda'
|
||||
|
||||
const detectCanary = partial(findApp,
|
||||
['Contents/MacOS/Google Chrome Canary', 'com.google.Chrome.canary', 'KSVersion'])
|
||||
const detectChrome = partial(findApp,
|
||||
['Contents/MacOS/Google Chrome', 'com.google.Chrome', 'KSVersion'])
|
||||
const detectChromium = partial(findApp,
|
||||
['Contents/MacOS/Chromium', 'org.chromium.Chromium', 'CFBundleShortVersionString'])
|
||||
const detectCanary = partial(findApp, [
|
||||
'Contents/MacOS/Google Chrome Canary',
|
||||
'com.google.Chrome.canary',
|
||||
'KSVersion'
|
||||
])
|
||||
const detectChrome = partial(findApp, [
|
||||
'Contents/MacOS/Google Chrome',
|
||||
'com.google.Chrome',
|
||||
'KSVersion'
|
||||
])
|
||||
const detectChromium = partial(findApp, [
|
||||
'Contents/MacOS/Chromium',
|
||||
'org.chromium.Chromium',
|
||||
'CFBundleShortVersionString'
|
||||
])
|
||||
|
||||
type Detectors = {
|
||||
[index: string]: Function
|
||||
@@ -21,7 +30,7 @@ const browsers: Detectors = {
|
||||
chromium: detectChromium
|
||||
}
|
||||
|
||||
export function detectBrowserDarwin (browser: Browser) {
|
||||
export function detectBrowserDarwin(browser: Browser) {
|
||||
let fn = browsers[browser.name]
|
||||
|
||||
if (!fn) {
|
||||
@@ -30,11 +39,9 @@ export function detectBrowserDarwin (browser: Browser) {
|
||||
return detectBrowserLinux(browser)
|
||||
}
|
||||
|
||||
return fn()
|
||||
.then(merge({name: browser.name}))
|
||||
.catch(() => {
|
||||
log('could not detect %s using traditional Mac methods', browser.name)
|
||||
log('trying linux search')
|
||||
return detectBrowserLinux(browser)
|
||||
})
|
||||
return fn().then(merge({ name: browser.name })).catch(() => {
|
||||
log('could not detect %s using traditional Mac methods', browser.name)
|
||||
log('trying linux search')
|
||||
return detectBrowserLinux(browser)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import {log} from '../log'
|
||||
import {NotInstalledError} from '../types'
|
||||
import {prop, tap} from 'ramda'
|
||||
import execa = require('execa')
|
||||
|
||||
import fs = require('fs-extra')
|
||||
import path = require('path')
|
||||
import plist = require('plist')
|
||||
import { log } from '../log'
|
||||
import { NotInstalledError } from '../types'
|
||||
import { prop, tap } from 'ramda'
|
||||
import * as execa from 'execa'
|
||||
import * as fs from 'fs-extra'
|
||||
import * as path from 'path'
|
||||
import * as plist from 'plist'
|
||||
|
||||
/** parses Info.plist file from given application and returns a property */
|
||||
export function parse (p: string, property: string): Promise<string> {
|
||||
export function parse(p: string, property: string): Promise<string> {
|
||||
const pl = path.join(p, 'Contents', 'Info.plist')
|
||||
log('reading property file "%s"', pl)
|
||||
|
||||
@@ -21,14 +20,15 @@ export function parse (p: string, property: string): Promise<string> {
|
||||
throw err
|
||||
}
|
||||
|
||||
return fs.readFile(pl, 'utf8')
|
||||
return fs
|
||||
.readFile(pl, 'utf8')
|
||||
.then(plist.parse)
|
||||
.then(prop(property))
|
||||
.catch(failed)
|
||||
}
|
||||
|
||||
/** uses mdfind to find app using Ma app id like 'com.google.Chrome.canary' */
|
||||
export function mdfind (id: string): Promise<string> {
|
||||
export function mdfind(id: string): Promise<string> {
|
||||
const cmd = `mdfind 'kMDItemCFBundleIdentifier=="${id}"' | head -1`
|
||||
log('looking for bundle id %s using command: %s', id, cmd)
|
||||
|
||||
@@ -44,18 +44,19 @@ export function mdfind (id: string): Promise<string> {
|
||||
throw err
|
||||
}
|
||||
|
||||
return execa.shell(cmd)
|
||||
return execa
|
||||
.shell(cmd)
|
||||
.then(prop('stdout'))
|
||||
.then(tap(logFound))
|
||||
.catch(failedToFind)
|
||||
}
|
||||
|
||||
export type AppInfo = {
|
||||
path: string,
|
||||
path: string
|
||||
version: string
|
||||
}
|
||||
|
||||
function formApplicationPath (executable: string) {
|
||||
function formApplicationPath(executable: string) {
|
||||
const parts = executable.split('/')
|
||||
const name = parts[parts.length - 1]
|
||||
const appName = `${name}.app`
|
||||
@@ -63,21 +64,23 @@ function formApplicationPath (executable: string) {
|
||||
}
|
||||
|
||||
/** finds an application and its version */
|
||||
export function findApp (executable: string, appId: string, versionProperty: string): Promise<AppInfo> {
|
||||
export function findApp(
|
||||
executable: string,
|
||||
appId: string,
|
||||
versionProperty: string
|
||||
): Promise<AppInfo> {
|
||||
log('looking for app %s id %s', executable, appId)
|
||||
|
||||
const findVersion = (foundPath: string) =>
|
||||
parse(foundPath, versionProperty)
|
||||
.then((version) => {
|
||||
return {
|
||||
path: path.join(foundPath, executable),
|
||||
version
|
||||
}
|
||||
})
|
||||
parse(foundPath, versionProperty).then(version => {
|
||||
return {
|
||||
path: path.join(foundPath, executable),
|
||||
version
|
||||
}
|
||||
})
|
||||
|
||||
const tryMdFind = () => {
|
||||
return mdfind(appId)
|
||||
.then(findVersion)
|
||||
return mdfind(appId).then(findVersion)
|
||||
}
|
||||
|
||||
const tryFullApplicationFind = () => {
|
||||
@@ -86,6 +89,5 @@ export function findApp (executable: string, appId: string, versionProperty: str
|
||||
return findVersion(applicationPath)
|
||||
}
|
||||
|
||||
return tryMdFind()
|
||||
.catch(tryFullApplicationFind)
|
||||
return tryMdFind().catch(tryFullApplicationFind)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import {detectBrowserLinux} from './linux'
|
||||
import {detectBrowserDarwin} from './darwin'
|
||||
import {log} from './log'
|
||||
import {Browser, NotInstalledError} from './types'
|
||||
import {browsers} from './browsers'
|
||||
import { detectBrowserLinux } from './linux'
|
||||
import { detectBrowserDarwin } from './darwin'
|
||||
import { log } from './log'
|
||||
import { Browser, NotInstalledError } from './types'
|
||||
import { browsers } from './browsers'
|
||||
import * as Bluebird from 'bluebird'
|
||||
import {merge, pick, tap, uniqBy, prop} from 'ramda'
|
||||
|
||||
import _ = require('lodash')
|
||||
import os = require('os')
|
||||
import { merge, pick, tap, uniqBy, prop } from 'ramda'
|
||||
import * as _ from 'lodash'
|
||||
import * as os from 'os'
|
||||
|
||||
const setMajorVersion = (obj: Browser) => {
|
||||
if (obj.version) {
|
||||
obj.majorVersion = obj.version.split('.')[0]
|
||||
log('browser %s version %s major version %s',
|
||||
obj.name, obj.version, obj.majorVersion)
|
||||
log(
|
||||
'browser %s version %s major version %s',
|
||||
obj.name,
|
||||
obj.version,
|
||||
obj.majorVersion
|
||||
)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
@@ -27,7 +30,7 @@ const detectors: Detectors = {
|
||||
linux: detectBrowserLinux
|
||||
}
|
||||
|
||||
function lookup (platform: NodeJS.Platform, obj: Browser): Promise<Object> {
|
||||
function lookup(platform: NodeJS.Platform, obj: Browser): Promise<Object> {
|
||||
log('looking up %s on %s platform', obj.name, platform)
|
||||
const detector = detectors[platform]
|
||||
if (!detector) {
|
||||
@@ -36,9 +39,15 @@ function lookup (platform: NodeJS.Platform, obj: Browser): Promise<Object> {
|
||||
return detector(obj)
|
||||
}
|
||||
|
||||
function checkOneBrowser (browser: Browser) {
|
||||
function checkOneBrowser(browser: Browser) {
|
||||
const platform = os.platform()
|
||||
const pickBrowserProps = pick(['name', 'displayName', 'type', 'version', 'path'])
|
||||
const pickBrowserProps = pick([
|
||||
'name',
|
||||
'displayName',
|
||||
'type',
|
||||
'version',
|
||||
'path'
|
||||
])
|
||||
|
||||
const logBrowser = (props: any) => {
|
||||
log('setting major version for %j', props)
|
||||
@@ -61,7 +70,7 @@ function checkOneBrowser (browser: Browser) {
|
||||
}
|
||||
|
||||
/** returns list of detected browsers */
|
||||
function detectBrowsers (): Bluebird<Browser[]> {
|
||||
function detectBrowsers(): Bluebird<Browser[]> {
|
||||
// we can detect same browser under different aliases
|
||||
// tell them apart by the full version property
|
||||
const removeDuplicates = uniqBy(prop('version'))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {writeJson} from 'fs-extra'
|
||||
import {launch} from './browsers'
|
||||
import { writeJson } from 'fs-extra'
|
||||
import { launch } from './browsers'
|
||||
import detect from './detect'
|
||||
import {Browser, LauncherApi} from './types'
|
||||
import { Browser, LauncherApi } from './types'
|
||||
|
||||
const Promise = require('bluebird')
|
||||
|
||||
@@ -9,14 +9,13 @@ const missingConfig = () =>
|
||||
Promise.reject(new Error('You must provide a path to a config file.'))
|
||||
|
||||
const wrap = (all: Browser[]) => ({
|
||||
launch: (name: string, url: string, args = []) =>
|
||||
launch(all, name, url, args)
|
||||
launch: (name: string, url: string, args = []) => launch(all, name, url, args)
|
||||
})
|
||||
|
||||
const init = (browsers: Browser[]) =>
|
||||
browsers ? wrap(browsers) : detect().then(wrap)
|
||||
|
||||
const api: LauncherApi = init as any as LauncherApi
|
||||
const api: LauncherApi = (init as any) as LauncherApi
|
||||
|
||||
const update = (pathToConfig?: string) => {
|
||||
if (!pathToConfig) {
|
||||
@@ -25,10 +24,9 @@ const update = (pathToConfig?: string) => {
|
||||
|
||||
// detect the browsers and set the config
|
||||
const saveBrowsers = (browers: Browser[]) =>
|
||||
writeJson(pathToConfig, browers, {spaces: 2})
|
||||
writeJson(pathToConfig, browers, { spaces: 2 })
|
||||
|
||||
return detect()
|
||||
.then(saveBrowsers)
|
||||
return detect().then(saveBrowsers)
|
||||
}
|
||||
|
||||
// extend "api" with a few utility methods for convenience
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
import {log} from '../log'
|
||||
import {prop, trim, tap} from 'ramda'
|
||||
import {FoundBrowser, Browser, NotInstalledError} from '../types'
|
||||
import execa = require('execa')
|
||||
import { log } from '../log'
|
||||
import { prop, trim, tap } from 'ramda'
|
||||
import { FoundBrowser, Browser, NotInstalledError } from '../types'
|
||||
import * as execa from 'execa'
|
||||
|
||||
const notInstalledErr = (name: string) => {
|
||||
const err: NotInstalledError =
|
||||
new Error(`Browser not installed: ${name}`) as NotInstalledError
|
||||
const err: NotInstalledError = new Error(
|
||||
`Browser not installed: ${name}`
|
||||
) as NotInstalledError
|
||||
err.notInstalled = true
|
||||
throw err
|
||||
}
|
||||
|
||||
function getLinuxBrowser (name: string, binary: string, versionRegex: RegExp): Promise<FoundBrowser> {
|
||||
function getLinuxBrowser(
|
||||
name: string,
|
||||
binary: string,
|
||||
versionRegex: RegExp
|
||||
): Promise<FoundBrowser> {
|
||||
const getVersion = (stdout: string) => {
|
||||
const m = versionRegex.exec(stdout)
|
||||
if (m) {
|
||||
return m[1]
|
||||
}
|
||||
log('Could not extract version from %s using regex %s', stdout, versionRegex)
|
||||
log(
|
||||
'Could not extract version from %s using regex %s',
|
||||
stdout,
|
||||
versionRegex
|
||||
)
|
||||
return notInstalledErr(binary)
|
||||
}
|
||||
|
||||
@@ -27,12 +36,13 @@ function getLinuxBrowser (name: string, binary: string, versionRegex: RegExp): P
|
||||
|
||||
const cmd = `${binary} --version`
|
||||
log('looking using command "%s"', cmd)
|
||||
return execa.shell(cmd)
|
||||
return execa
|
||||
.shell(cmd)
|
||||
.then(prop('stdout'))
|
||||
.then(trim)
|
||||
.then(tap(log))
|
||||
.then(getVersion)
|
||||
.then((version) => {
|
||||
.then(version => {
|
||||
return {
|
||||
name,
|
||||
version,
|
||||
@@ -42,6 +52,6 @@ function getLinuxBrowser (name: string, binary: string, versionRegex: RegExp): P
|
||||
.catch(returnError)
|
||||
}
|
||||
|
||||
export function detectBrowserLinux (browser: Browser) {
|
||||
export function detectBrowserLinux(browser: Browser) {
|
||||
return getLinuxBrowser(browser.name, browser.binary, browser.versionRegex)
|
||||
}
|
||||
|
||||
@@ -5,25 +5,25 @@ export type PlatformName = 'darwin' | 'linux'
|
||||
|
||||
export type Browser = {
|
||||
/** short browser name */
|
||||
name: MacBrowserName,
|
||||
name: MacBrowserName
|
||||
/** Optional display name */
|
||||
displayName?: string,
|
||||
displayName?: string
|
||||
/** RegExp to use to extract version from something like "Google Chrome 58.0.3029.110" */
|
||||
versionRegex: RegExp,
|
||||
profile: boolean,
|
||||
binary: string,
|
||||
version?: string,
|
||||
majorVersion?: string,
|
||||
versionRegex: RegExp
|
||||
profile: boolean
|
||||
binary: string
|
||||
version?: string
|
||||
majorVersion?: string
|
||||
page?: string
|
||||
}
|
||||
|
||||
export type FoundBrowser = {
|
||||
name: string,
|
||||
name: string
|
||||
path?: string
|
||||
}
|
||||
|
||||
interface ExtraLauncherMethods {
|
||||
update: Function,
|
||||
update: Function
|
||||
detect: Function
|
||||
}
|
||||
|
||||
@@ -33,6 +33,6 @@ export type LauncherApi = LauncherLaunch & ExtraLauncherMethods
|
||||
|
||||
// all common type definition for this module
|
||||
|
||||
export type NotInstalledError = Error & {notInstalled: boolean}
|
||||
export type NotInstalledError = Error & { notInstalled: boolean }
|
||||
|
||||
export type BrowserNotFoundError = Error & {specificBrowserNotFound: boolean}
|
||||
export type BrowserNotFoundError = Error & { specificBrowserNotFound: boolean }
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
"test": "mocha",
|
||||
"clean-deps": "rm -rf node_modules",
|
||||
"clean": "rm lib/*.js lib/**/*.js || true",
|
||||
"lint": "npm run lint-ts && npm run lint-coffee",
|
||||
"lint": "npm run format-ts && npm run lint-ts && npm run lint-coffee",
|
||||
"lint-ts": "tslint --type-check --project . --fix --format stylish lib/*.ts lib/**/*.ts",
|
||||
"lint-coffee": "../coffee/node_modules/.bin/coffeelint test/*.coffee test/**/*.coffee"
|
||||
"lint-coffee": "../coffee/node_modules/.bin/coffeelint test/*.coffee test/**/*.coffee",
|
||||
"format-ts": "prettier --no-semi --single-quote --write lib/*.ts lib/**/*.ts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -34,9 +35,10 @@
|
||||
"@types/node": "^7.0.18",
|
||||
"chai": "^3.5.0",
|
||||
"mocha": "^2.4.5",
|
||||
"prettier": "^1.4.2",
|
||||
"sinon": "^1.17.3",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"tslint": "5.3.2",
|
||||
"tslint": "5.4.3",
|
||||
"tslint-config-standard": "5.0.2",
|
||||
"typescript": "2.3.2"
|
||||
},
|
||||
@@ -47,7 +49,7 @@
|
||||
"execa": "^0.6.3",
|
||||
"fs-extra": "^3.0.0",
|
||||
"lodash": "^4.11.1",
|
||||
"plist": "^1.2.0",
|
||||
"plist": "^2.1.0",
|
||||
"ramda": "^0.23.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('linux browser detection', () => {
|
||||
execa.shell.restore()
|
||||
})
|
||||
|
||||
it('is detects browser by running --version', () => {
|
||||
it('detects browser by running --version', () => {
|
||||
const goal = {
|
||||
name: 'test-browser-name',
|
||||
versionRegex: /v(\S+)$/,
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
{
|
||||
"extends": "tslint-config-standard"
|
||||
"extends": "tslint-config-standard",
|
||||
"rules": {
|
||||
"space-before-function-paren": false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user