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

Warn when Cypress detects policies that may interfere with automating Chrome #4405

Merged
merged 19 commits into from Jul 3, 2019
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 27 additions & 1 deletion packages/desktop-gui/cypress/integration/project_nav_spec.coffee
Expand Up @@ -151,7 +151,7 @@ describe "Project Nav", ->
it "sends the required parameters to launch a browser", ->
browserArg = @ipc.launchBrowser.getCall(0).args[0].browser
expect(browserArg).to.have.keys([
"family", "name", "path", "version", "majorVersion", "displayName", "info", "isChosen", "custom"
"family", "name", "path", "version", "majorVersion", "displayName", "info", "isChosen", "custom", "warning"
])
expect(browserArg.path).to.include('/')
expect(browserArg.family).to.equal('chrome')
Expand Down Expand Up @@ -232,6 +232,32 @@ describe "Project Nav", ->
cy.get(".browsers-list")
.find(".dropdown-toggle").should("not.be.visible")

describe "browser has a warning attached", ->
beforeEach ->
@browsers = [{
"name": "chromium",
"displayName": "Chromium",
"family": "chrome",
"version": "49.0.2609.0",
"path": "/Users/bmann/Downloads/chrome-mac/Chromium.app/Contents/MacOS/Chromium",
"majorVersion": "49",
"warning": "Cypress detected policy settings on your computer that may cause issues with using this browser. For more information, see https://on.cypress.io/bad-browser-policy"
}]

@config.browsers = @browsers
@openProject.resolve(@config)

it "shows warning icon with linkified tooltip", ->
cy.get(".browsers .fa-exclamation-triangle")
.then ($el) ->
$el[0].dispatchEvent(new Event("mouseover", {bubbles: true}))
brian-mann marked this conversation as resolved.
Show resolved Hide resolved
cy.get(".cy-tooltip")
.should("contain", "Cypress detected policy settings on your computer that may cause issues with using this browser. For more information, see")
.get(".cy-tooltip a")
.click()
.then () ->
expect(@ipc.externalOpen).to.be.calledWith("https://on.cypress.io/bad-browser-policy")

describe "custom browser available", ->
beforeEach ->
@config.browsers.push({
Expand Down
Expand Up @@ -80,3 +80,41 @@ describe "WarningMessage", ->
.click()
.then ->
expect(@ipc.externalOpen).not.to.be.called

context "with multiple warnings", ->
beforeEach ->
@warningObj2 = {type: "GOOD_BUT_NOT_TOO_GOOD", name: "Fairly good warning", message: "Other message"}

it "shows multiple warnings", ->
cy.shouldBeOnProjectSpecs().then =>
@ipc.onProjectWarning.yield(null, @warningObj)
@ipc.onProjectWarning.yield(null, @warningObj2)

cy.get(".alert-warning")
.should("have.length", 2)
.should("be.visible")
.first()
.should("contain", "Some warning")
cy.get(".alert-warning")
.its('1')
.should("contain", "Other message")

it "can dismiss the warnings", ->
cy.shouldBeOnProjectSpecs().then =>
@ipc.onProjectWarning.yield(null, @warningObj)
@ipc.onProjectWarning.yield(null, @warningObj2)

cy.get(".alert-warning")
.should("contain", "Some warning")
.should("contain", "Other message")
.get(".alert-warning button")
.first()
.click()
cy.get(".alert-warning")
.should("not.contain", "Some warning")
.should("contain", "Other message")
.get(".alert-warning button")
.click()
cy.get(".alert-warning")
.should("not.contain", "Some warning")
.should("not.contain", "Other message")
2 changes: 1 addition & 1 deletion packages/desktop-gui/package.json
Expand Up @@ -26,7 +26,7 @@
"devDependencies": {
"@babel/plugin-proposal-object-rest-spread": "7.4.4",
"@cypress/icons": "0.7.0",
"@cypress/json-schemas": "5.32.1",
"@cypress/json-schemas": "5.31.3",
"@cypress/react-tooltip": "0.5.0",
"bin-up": "1.2.0",
"bluebird": "3.5.3",
Expand Down
6 changes: 6 additions & 0 deletions packages/desktop-gui/src/app/nav.scss
Expand Up @@ -135,6 +135,12 @@
margin-right: 4px;
}

.nav .browser-warning {
color: $red-primary;
margin-left: 6px;
margin-right: 4px;
}

.browser-info-tooltip {
background: #ececec;
border-color: #c7c7c7;
Expand Down
2 changes: 2 additions & 0 deletions packages/desktop-gui/src/lib/browser-model.js
Expand Up @@ -9,6 +9,7 @@ export default class Browser {
@observable majorVersion
@observable info
@observable custom
@observable warning
@observable isChosen = false

constructor (browser) {
Expand All @@ -20,6 +21,7 @@ export default class Browser {
this.majorVersion = browser.majorVersion
this.info = browser.info
this.custom = browser.custom
this.warning = browser.warning
}

@computed get icon () {
Expand Down
37 changes: 37 additions & 0 deletions packages/desktop-gui/src/lib/markdown-renderer.jsx
@@ -0,0 +1,37 @@
import React from 'react'
import Markdown from 'markdown-it'

import ipc from '../lib/ipc'

const md = new Markdown({
html: true,
linkify: true,
})

export default class MarkdownRenderer extends React.PureComponent {
componentDidMount () {
this.node.addEventListener('click', this._clickHandler)
}

componentWillUnmount () {
this.node.removeEventListener('click', this._clickHandler)
}

_clickHandler (e) {
if (e.target.href) {
e.preventDefault()

return ipc.externalOpen(e.target.href)
}
}

render () {
return (
<span ref={(node) => this.node = node}
dangerouslySetInnerHTML={{
__html: md.render(this.props.markdown),
}}>
</span>
)
}
}
18 changes: 18 additions & 0 deletions packages/desktop-gui/src/project-nav/browsers.jsx
Expand Up @@ -2,6 +2,7 @@ import React, { Component } from 'react'
import { observer } from 'mobx-react'
import Tooltip from '@cypress/react-tooltip'
import Dropdown from '../dropdown/dropdown'
import MarkdownRenderer from '../lib/markdown-renderer'

import projectsApi from '../projects/projects-api'

Expand Down Expand Up @@ -73,11 +74,28 @@ export default class Browsers extends Component {
{prefixText}{' '}
{browser.displayName}{' '}
{browser.majorVersion}
{this._warn(browser)}
{this._info(browser)}
</span>
)
}

_warn (browser) {
if (!browser.warning) return null

return (
<span className='browser-warning'>
<Tooltip
title={<MarkdownRenderer markdown={browser.warning}/>}
placement='bottom'
className='browser-info-tooltip cy-tooltip'
>
<i className='fa fa-exclamation-triangle' />
</Tooltip>
</span>
)
}

_info (browser) {
if (!browser.info) return null

Expand Down
19 changes: 12 additions & 7 deletions packages/desktop-gui/src/project/project-model.js
Expand Up @@ -53,7 +53,7 @@ export default class Project {
@observable browserState = 'closed'
@observable resolvedConfig
@observable error
@observable warning
@observable warnings = []
@observable apiError
@observable parentTestsFolderDisplay
@observable integrationExampleName
Expand Down Expand Up @@ -209,18 +209,23 @@ export default class Project {
this.error = null
}

@action setWarning (warning) {
@action addWarning (warning) {
if (!this.dismissedWarnings[this._serializeWarning(warning)]) {
this.warning = warning
this.warnings.push(warning)
}
}

@action clearWarning () {
if (this.warning) {
this.dismissedWarnings[this._serializeWarning(this.warning)] = true
@action clearWarning (warning) {
if (!warning) {
// calling with no warning clears all warnings
return this.warnings.map((warning) => {
return this.clearWarning(warning)
})
}

this.warning = null
this.dismissedWarnings[this._serializeWarning(warning)] = true

this.warnings = _.without(this.warnings, warning)
}

_serializeWarning (warning) {
Expand Down
18 changes: 11 additions & 7 deletions packages/desktop-gui/src/project/project.jsx
Expand Up @@ -39,15 +39,11 @@ class Project extends Component {

if (this.props.project.error) return <ErrorMessage error={this.props.project.error} onTryAgain={this._reopenProject}/>

const { warning } = this.props.project

return (
<div>
<ProjectNav project={this.props.project}/>
<div className='project-content'>
{warning &&
<WarningMessage warning={warning} onClearWarning={this._removeWarning}/>
}
{this._renderWarnings()}
{this._currentView()}
</div>
<OnBoarding project={this.props.project}/>
Expand All @@ -72,8 +68,16 @@ class Project extends Component {
}
}

_removeWarning = () => {
this.props.project.clearWarning()
_renderWarnings = () => {
const { warnings } = this.props.project

return warnings.map((warning, i) =>
(<WarningMessage key={i} warning={warning} onClearWarning={() => this._removeWarning(warning)}/>)
)
}

_removeWarning = (warning) => {
this.props.project.clearWarning(warning)
}

_reopenProject = () => {
Expand Down
31 changes: 4 additions & 27 deletions packages/desktop-gui/src/project/warning-message.jsx
@@ -1,32 +1,9 @@
import React, { Component } from 'react'
import { observer } from 'mobx-react'
import Markdown from 'markdown-it'

import ipc from '../lib/ipc'

const md = new Markdown({
html: true,
linkify: true,
})
import MarkdownRenderer from '../lib/markdown-renderer'

@observer
class WarningMessage extends Component {
componentDidMount () {
this.warningMessageNode.addEventListener('click', this._clickHandler)
}

componentWillUnmount () {
this.warningMessageNode.removeEventListener('click', this._clickHandler)
}

_clickHandler (e) {
if (e.target.href) {
e.preventDefault()

return ipc.externalOpen(e.target.href)
}
}

render () {
const warningText = this.props.warning.message.split('\n').join('<br />')

Expand All @@ -36,9 +13,9 @@ class WarningMessage extends Component {
<i className='fa fa-warning'></i>{' '}
<strong>Warning</strong>
</p>
<div ref={(node) => this.warningMessageNode = node} dangerouslySetInnerHTML={{
__html: md.render(warningText),
}}></div>
<div>
<MarkdownRenderer markdown={warningText}/>
</div>
<button className='btn btn-link close' onClick={this.props.onClearWarning}>
<i className='fa fa-remove' />
</button>
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-gui/src/projects/projects-api.js
Expand Up @@ -168,7 +168,7 @@ const openProject = (project) => {
})

ipc.onProjectWarning((__, warning) => {
project.setWarning(warning)
project.addWarning(warning)
})

return ipc.openProject(project.path)
Expand Down
2 changes: 2 additions & 0 deletions packages/launcher/lib/types.ts
Expand Up @@ -35,6 +35,8 @@ export type FoundBrowser = Browser & {
custom?: boolean
/** optional info that will be shown in the GUI */
info?: string
/** optional warning that will be shown in the GUI */
warning?: string
}

// all common type definition for this module
Expand Down
14 changes: 14 additions & 0 deletions packages/server/lib/errors.coffee
Expand Up @@ -788,6 +788,20 @@ getMsgByType = (type, arg1 = {}, arg2) ->

Provide a path to an existing fixture file.
"""
when "BAD_POLICY_WARNING"
"""
Cypress detected policy settings on your computer that may cause issues.

The following policies were detected that may prevent Cypress from automating Chrome:

> #{arg1.join('\n > ')}

For more information, see https://on.cypress.io/bad-browser-policy
"""
when "BAD_POLICY_WARNING_TOOLTIP"
"""
Cypress detected policy settings on your computer that may cause issues with using this browser. For more information, see https://on.cypress.io/bad-browser-policy
"""

get = (type, arg1, arg2) ->
msg = getMsgByType(type, arg1, arg2)
Expand Down
6 changes: 6 additions & 0 deletions packages/server/lib/gui/events.coffee
Expand Up @@ -14,6 +14,7 @@ Updater = require("../updater")
Project = require("../project")
openProject = require("../open_project")
ensureUrl = require("../util/ensure-url")
chromePolicyCheck = require("../util/chrome_policy_check")
browsers = require("../browsers")
konfig = require("../konfig")

Expand Down Expand Up @@ -204,6 +205,11 @@ handleEvent = (options, bus, event, id, type, arg) ->
.then (browsers = []) ->
options.config = _.assign(options.config, { browsers })
.then ->
chromePolicyCheck.run (err) ->
options.config.browsers.forEach (browser) ->
if browser.family == 'chrome'
browser.warning = errors.getMsgByType('BAD_POLICY_WARNING_TOOLTIP')

openProject.create(arg, options, {
onFocusTests: onFocusTests
onSpecChanged: onSpecChanged
Expand Down