Skip to content
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

Represent browsers as objects internally #3225

Merged
merged 35 commits into from
Feb 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
eceef1e
adding multiple possible binary names for linux
flotwig Jan 24, 2019
be231b8
windows launcher doesn't consider "binary", so don't pass it
flotwig Jan 24, 2019
66427dd
adding test for multiple binary names
flotwig Jan 24, 2019
61ad49e
Stronger typing, clearer variable names
flotwig Jan 24, 2019
04e3e5e
cleanup
flotwig Jan 24, 2019
a8ea637
clean up type- why isn't this being linted?
flotwig Jan 24, 2019
d27b8e1
Add more aliases (#3217)
flotwig Jan 24, 2019
db5b47c
launcher changes to use Browser throughout, also clarifying FoundBrow…
flotwig Jan 25, 2019
96c215c
wip
flotwig Jan 28, 2019
0048772
Stronger typing, clearer variable names
flotwig Jan 24, 2019
3043d4c
cleanup
flotwig Jan 24, 2019
be883dc
wip
flotwig Jan 28, 2019
20cc650
update tests to expect objects
flotwig Jan 28, 2019
481fd9b
removing errant debugger calls
flotwig Jan 28, 2019
680f717
Fixing tests
flotwig Jan 28, 2019
a27b31a
desktop-gui: use displayName for display
flotwig Jan 28, 2019
e4a9434
' -> "
flotwig Jan 28, 2019
a173be7
launcher: add definitions for google chrome beta and unstable
flotwig Jan 28, 2019
e31ae0f
server: fallthrough to using chrome helper
flotwig Jan 28, 2019
0db40d9
server: changes for run mode to pick correct version
flotwig Jan 28, 2019
7f58bd2
desktop-gui: add displayName to fixtures
flotwig Jan 28, 2019
1525c1a
server: isolating bug with runmode
flotwig Jan 28, 2019
6b65adc
browser was a string all along
flotwig Jan 28, 2019
7e1b9c0
server: re-promisify browser detection
flotwig Jan 28, 2019
6570ab3
launcher: remove chrome-beta for now, needs some more tweaking for th…
flotwig Jan 28, 2019
af46f07
launcher: cleaning up types
flotwig Jan 30, 2019
8807186
launcher: fix type comflict when filtering browsers (#3258)
flotwig Feb 4, 2019
38cd2de
launcher: cast Windows foundbrowsers
flotwig Feb 5, 2019
c29c205
launcher: mapSeries -> map
flotwig Feb 5, 2019
eaf7a4d
launcher: clean up launcher, change 1 call in server to match
flotwig Feb 5, 2019
8bb8915
launcher: test that browsers contains what we like it to
flotwig Feb 5, 2019
cf48a5a
whoops
flotwig Feb 6, 2019
89a1a96
launcher, server: PR review changes
flotwig Feb 11, 2019
d6507f7
server: add unit test for non-existing browser family
flotwig Feb 11, 2019
3276ef4
server: add family to integration tests
flotwig Feb 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/desktop-gui/cypress/fixtures/browsers.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
[
{
"name": "chrome",
"displayName": "Chrome",
"version": "50.0.2661.86",
"path": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"majorVersion": "50"
},
{
"name": "chromium",
"displayName": "Chromium",
"version": "49.0.2609.0",
"path": "/Users/bmann/Downloads/chrome-mac/Chromium.app/Contents/MacOS/Chromium",
"majorVersion": "49"
},
{
"name": "canary",
"displayName": "Canary",
"version": "48.0",
"path": "/Users/bmann/Downloads/chrome-mac/Canary.app/Contents/MacOS/Canary",
"majorVersion": "48"
}
]
]
5 changes: 4 additions & 1 deletion packages/desktop-gui/cypress/fixtures/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,26 @@
"browsers": [
{
"name": "chrome",
"displayName": "Chrome",
"version": "50.0.2661.86",
"path": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"majorVersion": "50"
},
{
"name": "chromium",
"displayName": "Chromium",
"version": "49.0.2609.0",
"path": "/Users/bmann/Downloads/chrome-mac/Chromium.app/Contents/MacOS/Chromium",
"majorVersion": "49"
},
{
"name": "canary",
"displayName": "Canary",
"version": "48.0",
"path": "/Users/bmann/Downloads/chrome-mac/Canary.app/Contents/MacOS/Canary",
"majorVersion": "48"
}
],
],
"clientRoute": "/__/",
"clientUrl": "http://localhost:2020/__/",
"clientUrlDisplay": "http://localhost:2020",
Expand Down
7 changes: 2 additions & 5 deletions packages/desktop-gui/src/lib/browser-model.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _ from 'lodash'
import { computed, observable } from 'mobx'

export default class Browser {
@observable displayName
@observable name
@observable version
@observable path
Expand All @@ -10,17 +10,14 @@ export default class Browser {
@observable isChosen = false

constructor (browser) {
this.displayName = browser.displayName
this.name = browser.name
this.version = browser.version
this.path = browser.path
this.majorVersion = browser.majorVersion
this.info = browser.info
}

@computed get displayName () {
return _.capitalize(this.name)
}

@computed get icon () {
return 'chrome'
}
Expand Down
33 changes: 33 additions & 0 deletions packages/launcher/__snapshots__/browsers_spec.ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
exports['browsers returns the expected list of browsers 1'] = [
{
"name": "chrome",
"family": "chrome",
"displayName": "Chrome",
"versionRegex": {},
"profile": true,
"binary": [
"google-chrome",
"chrome",
"google-chrome-stable"
]
},
{
"name": "chromium",
"family": "chrome",
"displayName": "Chromium",
"versionRegex": {},
"profile": true,
"binary": [
"chromium-browser",
"chromium"
]
},
{
"name": "canary",
"family": "chrome",
"displayName": "Canary",
"versionRegex": {},
"profile": true,
"binary": "google-chrome-canary"
}
]
39 changes: 11 additions & 28 deletions packages/launcher/lib/browsers.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,51 @@
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 available = map(browsers, 'name').join(', ')

const err: BrowserNotFoundError = new Error(
`Browser: '${name}' not found. Available browsers are: [${available}]`
) as BrowserNotFoundError
err.specificBrowserNotFound = true
return err
}
import { Browser, FoundBrowser } from './types'

/** list of the browsers we can detect and use by default */
export const browsers: Browser[] = [
{
name: 'chrome',
family: 'chrome',
displayName: 'Chrome',
versionRegex: /Google Chrome (\S+)/,
profile: true,
binary: 'google-chrome'
binary: ['google-chrome', 'chrome', 'google-chrome-stable']
},
{
name: 'chromium',
family: 'chrome',
displayName: 'Chromium',
versionRegex: /Chromium (\S+)/,
profile: true,
binary: 'chromium-browser'
binary: ['chromium-browser', 'chromium']
},
{
name: 'canary',
family: 'chrome',
displayName: 'Canary',
versionRegex: /Google Chrome Canary (\S+)/,
profile: true,
binary: 'google-chrome-canary'
}
]

/** starts a browser by name and opens URL if given one */
/** starts a found browser and opens URL if given one */
export function launch(
browsers: FoundBrowser[],
name: string,
browser: FoundBrowser,
url?: string,
args: string[] = []
) {
log('launching browser %s to open %s', name, url)
const browser = find(browsers, { name })

if (!browser) {
throw browserNotFoundErr(browsers, name)
}
log('launching browser %o to open %s', browser, url)

if (!browser.path) {
throw new Error(`Found browser ${name} is missing path`)
throw new Error(`Browser ${browser.name} is missing path`)
}

if (url) {
args = [url].concat(args)
}

log('spawning browser %s with args %s', browser.path, args.join(' '))
log('spawning browser %o with args %s', browser, args.join(' '))
return cp.spawn(browser.path, args, { stdio: 'ignore' })
}
4 changes: 2 additions & 2 deletions packages/launcher/lib/darwin/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { findApp } from './util'
import { Browser } from '../types'
import { FoundBrowser, Browser } from '../types'
import { detectBrowserLinux } from '../linux'
import { log } from '../log'
import { merge, partial } from 'ramda'
Expand Down Expand Up @@ -30,7 +30,7 @@ const browsers: Detectors = {
chromium: detectChromium
}

export function detectBrowserDarwin(browser: Browser) {
export function detectBrowserDarwin(browser: Browser): Promise<FoundBrowser> {
let fn = browsers[browser.name]

if (!fn) {
Expand Down
72 changes: 44 additions & 28 deletions packages/launcher/lib/detect.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import * as Bluebird from 'bluebird'
import * as _ from 'lodash'
import { extend, compact } from 'lodash'
import * as os from 'os'
import { merge, pick, props, tap, uniqBy } from 'ramda'
import { merge, pick, props, tap, uniqBy, flatten } from 'ramda'
import { browsers } from './browsers'
import { detectBrowserDarwin } from './darwin'
import { detectBrowserLinux } from './linux'
import { log } from './log'
import { Browser, NotInstalledError } from './types'
import { FoundBrowser, Browser, NotInstalledError } from './types'
import { detectBrowserWindows } from './windows'

const setMajorVersion = (obj: Browser) => {
if (obj.version) {
obj.majorVersion = obj.version.split('.')[0]
const setMajorVersion = (browser: FoundBrowser) => {
if (browser.version) {
browser.majorVersion = browser.version.split('.')[0]
log(
'browser %s version %s major version %s',
obj.name,
obj.version,
obj.majorVersion
browser.name,
browser.version,
browser.majorVersion
)
}
return obj
return browser
}

type BrowserDetector = (browser: Browser) => Promise<Object>
type BrowserDetector = (browser: Browser) => Promise<FoundBrowser>
type Detectors = {
[index: string]: BrowserDetector
}
Expand All @@ -32,19 +32,37 @@ const detectors: Detectors = {
win32: detectBrowserWindows
}

function lookup(platform: NodeJS.Platform, obj: Browser): Promise<Object> {
log('looking up %s on %s platform', obj.name, platform)
function lookup(
platform: NodeJS.Platform,
browser: Browser
): Promise<FoundBrowser> {
log('looking up %s on %s platform', browser.name, platform)
const detector = detectors[platform]
if (!detector) {
throw new Error(`Cannot lookup browser ${obj.name} on ${platform}`)
throw new Error(`Cannot lookup browser ${browser.name} on ${platform}`)
}
return detector(obj)
return detector(browser)
}

function checkOneBrowser(browser: Browser) {
/**
* Try to detect a single browser definition, which may dispatch multiple `checkOneBrowser` calls,
* one for each binary. If Windows is detected, only one `checkOneBrowser` will be called, because
* we don't use the `binary` field on Windows.
*/
function checkBrowser(browser: Browser): Promise<(boolean | FoundBrowser)[]> {
if (Array.isArray(browser.binary) && os.platform() !== 'win32') {
return Bluebird.map(browser.binary, (binary: string) => {
return checkOneBrowser(extend({}, browser, { binary }))
})
}
return Bluebird.map([browser], checkOneBrowser)
}

function checkOneBrowser(browser: Browser): Promise<boolean | FoundBrowser> {
const platform = os.platform()
const pickBrowserProps = pick([
'name',
'family',
'displayName',
'type',
'version',
Expand Down Expand Up @@ -73,22 +91,20 @@ function checkOneBrowser(browser: Browser) {
}

/** returns list of detected browsers */
function detectBrowsers(goalBrowsers?: Browser[]): Bluebird<Browser[]> {
export const detect = (goalBrowsers?: Browser[]): Bluebird<FoundBrowser[]> => {
// we can detect same browser under different aliases
// tell them apart by the name and the version property
// @ts-ignore
if (!goalBrowsers) {
goalBrowsers = browsers
}

// for some reason the type system does not understand that after _.compact
// the remaining list only contains valid Browser objects
// and we can pick "name" and "version" fields from each object
// @ts-ignore
const removeDuplicates = uniqBy(props(['name', 'version']))
return Bluebird.mapSeries(goalBrowsers, checkOneBrowser)
.then(_.compact)
.then(removeDuplicates) as Bluebird<Browser[]>
}
const removeDuplicates = uniqBy((browser: FoundBrowser) =>
props(['name', 'version'], browser)
)
const compactFalse = (browsers: any[]) => compact(browsers) as FoundBrowser[]

export default detectBrowsers
return Bluebird.mapSeries(goalBrowsers, checkBrowser)
.then(flatten)
.then(compactFalse)
.then(removeDuplicates)
}
37 changes: 4 additions & 33 deletions packages/launcher/lib/launcher.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,7 @@
import { writeJson } from 'fs-extra'
import { launch } from './browsers'
import detect from './detect'
import { Browser, LauncherApi } from './types'
import { detect } from './detect'

const Promise = require('bluebird')

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)
})

const init = (browsers: Browser[]) =>
browsers ? wrap(browsers) : detect().then(wrap)

const api: LauncherApi = (init as any) as LauncherApi

const update = (pathToConfig?: string) => {
if (!pathToConfig) {
return missingConfig()
}

// detect the browsers and set the config
const saveBrowsers = (browers: Browser[]) =>
writeJson(pathToConfig, browers, { spaces: 2 })

return detect().then(saveBrowsers)
module.exports = {
detect,
launch
}

// extend "api" with a few utility methods for convenience
api.update = update
api.detect = detect

module.exports = api
Loading