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

[WIP] Update configuration change behavior #3211

Closed
wants to merge 45 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
deccabe
Add initial UI for config changes in desktop GUI
lilaconlee Jan 24, 2019
15f1807
WIP: update events for config/plugins changes
lilaconlee Jan 24, 2019
fe0d282
Add file paths to configuration and background change events
lilaconlee Jan 25, 2019
74f60e8
Add handling for config:changed event from the server to the runner
lilaconlee Jan 28, 2019
35b2efb
Add config change events to reporter
lilaconlee Jan 28, 2019
66b9ef8
WIP: Start reporter UI
lilaconlee Jan 28, 2019
57f5cdd
Update desktop-gui tests
lilaconlee Jan 29, 2019
f9ccfbd
First pass on reporter UI
lilaconlee Jan 29, 2019
5ec5b8f
Add onRequest back into server.coffee
lilaconlee Jan 29, 2019
09026d0
wip: cleaning up UI and adding reload configuration events
lilaconlee Jan 29, 2019
342d4b8
Unify desktop gui and reporter message and design
lilaconlee Jan 31, 2019
cd6a8e7
wip: partial browser reloading
lilaconlee Jan 31, 2019
1a7bfca
Update reporter warning to only appear when config changes
lilaconlee Feb 1, 2019
b9e98f8
WIP: rework configuration reloading logic
lilaconlee Feb 4, 2019
71dc7a6
Update reopen project logic
lilaconlee Feb 5, 2019
2941df1
Update desktop gui tests
lilaconlee Feb 5, 2019
baa49ba
Use reload configuration hook in desktop gui
lilaconlee Feb 5, 2019
93548ef
Rename reloadConfigurationRequested to onReloadConfigurationRequested
lilaconlee Feb 5, 2019
95960fc
Remove plugins:changed event
lilaconlee Feb 6, 2019
110d139
Update banner code styles
lilaconlee Feb 6, 2019
bb37f3a
Reload configuration directly in desktop gui
lilaconlee Feb 6, 2019
c865ca0
Correct desktop gui configuration reload function
lilaconlee Feb 6, 2019
b2120fa
Fix typo in server.coffee
lilaconlee Feb 11, 2019
6fb4be6
Update gui event specs in server
lilaconlee Feb 11, 2019
77c5b18
Add config changes e2e tests including simulateOpenMode flag
lilaconlee Feb 11, 2019
42564d6
Update comment style in decaffinated code
lilaconlee Feb 12, 2019
a480cfe
Merge branch 'develop' into issue-2869-config-changes
chrisbreiding Apr 4, 2019
85875b9
fix server unit tests
chrisbreiding Apr 4, 2019
aaaa1d5
Merge branch 'develop' into issue-2869-config-changes
jennifer-shehane Jul 3, 2019
756ed6d
Merge branch develop into issue-2869-config-changes
jennifer-shehane Dec 31, 2019
00a6b85
remove duplicate files (coffee already in js file)
jennifer-shehane Dec 31, 2019
dc684dc
fix lint errors
jennifer-shehane Dec 31, 2019
70be9c0
update options to correct 'args'
jennifer-shehane Dec 31, 2019
62a9ad3
Change 'setWarning' to proper 'addWarning'
jennifer-shehane Dec 31, 2019
6089158
Fix env tests that naively did not take into account restarting config.
jennifer-shehane Jan 2, 2020
88d7695
fix orphaned cypress command outside of test.
jennifer-shehane Jan 2, 2020
49a03b7
Update snapshot to have newer whitespacing.
jennifer-shehane Jan 2, 2020
7b68197
Fix incorrectly decaffed server test + remove irrelevant tests due to…
jennifer-shehane Jan 2, 2020
8cc47d3
remove duplicate sinon.stub that are present in beforeEach already
jennifer-shehane Jan 2, 2020
0d6ba54
Update tests - move warning message into MarkdownRendered component.
jennifer-shehane Jan 3, 2020
1f719fd
rewrite tests for banner configuration changes in Cypress
jennifer-shehane Jan 6, 2020
a2e33ce
Merge branch 'develop' into issue-2869-config-changes
jennifer-shehane Jan 6, 2020
9f35d17
renamed events + wrote failing test for config not reloading on reloa…
jennifer-shehane Jan 6, 2020
4584e3c
Fixed issue where reload:config was not being called when rerunning t…
jennifer-shehane Jan 6, 2020
0e7a595
reset 'configurationFilePathChanged' to default of 'null' when restar…
jennifer-shehane Jan 6, 2020
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
6 changes: 2 additions & 4 deletions packages/desktop-gui/cypress/integration/project_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,9 @@ describe('Project', function () {

it('re-opens project if config changes', function () {
cy.shouldBeOnProjectSpecs().then(() => {
this.ipc.onConfigChanged.yield()
expect(this.ipc.closeProject).to.be.called
expect(this.ipc.openProject).to.be.called
this.ipc.onConfigChanged.yield({}, '/Users/Jane/Dev/my-application/file.ext')

cy.shouldBeOnProjectSpecs()
cy.contains('file.ext was modified. Restart Cypress for changes to take effect.')
})
})
})
Expand Down
134 changes: 51 additions & 83 deletions packages/desktop-gui/cypress/integration/settings_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,33 +183,6 @@ describe('Settings', () => {
})
})

it('displays null when env settings are empty or not defined', function () {
this.ipc.openProject.resolves(setConfigEnv(this.config, undefined))
this.ipc.onConfigChanged.yield()

cy.contains('.line', 'env:null').then(() => {
this.ipc.openProject.resolves(this.config)
this.ipc.onConfigChanged.yield()

cy.contains('.line', 'env:fileServerFolder')
.then(() => {
this.ipc.openProject.resolves(setConfigEnv(this.config, null))
this.ipc.onConfigChanged.yield()
cy.contains('.line', 'env:null').then(() => {
this.ipc.openProject.resolves(this.config)
this.ipc.onConfigChanged.yield()

cy.contains('.line', 'env:fileServerFolder')
.then(() => {
this.ipc.openProject.resolves(setConfigEnv(this.config, {}))
this.ipc.onConfigChanged.yield()
cy.contains('.line', 'env:null')
})
})
})
})
})

it('displays env settings', () => {
cy.get('@config').then(({ resolved }) => {
const getEnvKeys = flow([
Expand Down Expand Up @@ -422,33 +395,6 @@ describe('Settings', () => {
})
})

context('on config changes', () => {
beforeEach(function () {
this.projectStatuses[0].id = this.config.projectId
this.getProjectStatus.resolve(this.projectStatuses[0])
const newConfig = this.util.deepClone(this.config)

newConfig.clientUrl = 'http://localhost:8888'
newConfig.clientUrlDisplay = 'http://localhost:8888'
newConfig.browsers = this.browsers
this.openProject.resolve(newConfig)

this.goToSettings()

cy.contains('Configuration').click()
})

it('displays updated config', function () {
const newConfig = this.util.deepClone(this.config)

newConfig.resolved.baseUrl.value = 'http://localhost:7777'
this.ipc.openProject.onCall(1).resolves(newConfig)
this.ipc.onConfigChanged.yield()

cy.contains('http://localhost:7777')
})
})

describe('when node version panel is opened', () => {
const bundledNodeVersion = '1.2.3'
const systemNodePath = '/foo/bar/node'
Expand Down Expand Up @@ -488,44 +434,20 @@ describe('Settings', () => {
})

describe('errors', () => {
beforeEach(function () {
this.err = {
message: 'Port \'2020\' is already in use.',
name: 'Error',
port: 2020,
portInUse: true,
stack: '[object Object]↵ at Object.API.get (/Users/jennifer/Dev/Projects/cypress-app/lib/errors.coffee:55:15)↵ at Object.wrapper [as get] (/Users/jennifer/Dev/Projects/cypress-app/node_modules/lodash/lodash.js:4414:19)↵ at Server.portInUseErr (/Users/jennifer/Dev/Projects/cypress-app/lib/server.coffee:58:16)↵ at Server.onError (/Users/jennifer/Dev/Projects/cypress-app/lib/server.coffee:86:19)↵ at Server.g (events.js:273:16)↵ at emitOne (events.js:90:13)↵ at Server.emit (events.js:182:7)↵ at emitErrorNT (net.js:1253:8)↵ at _combinedTickCallback (internal/process/next_tick.js:74:11)↵ at process._tickDomainCallback (internal/process/next_tick.js:122:9)↵From previous event:↵ at fn (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:57919:14)↵ at Object.appIpc [as ipc] (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:57939:10)↵ at openProject (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:59135:24)↵ at new Project (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:58848:34)↵ at ReactCompositeComponentMixin._constructComponentWithoutOwner (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:44052:27)↵ at ReactCompositeComponentMixin._constructComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:44034:21)↵ at ReactCompositeComponentMixin.mountComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:43953:21)↵ at Object.ReactReconciler.mountComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:51315:35)↵ at ReactCompositeComponentMixin.performInitialMount (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:44129:34)↵ at ReactCompositeComponentMixin.mountComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:44016:21)↵ at Object.ReactReconciler.mountComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:51315:35)↵ at ReactDOMComponent.ReactMultiChild.Mixin._mountChildAtIndex (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:50247:40)↵ at ReactDOMComponent.ReactMultiChild.Mixin._updateChildren (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:50163:43)↵ at ReactDOMComponent.ReactMultiChild.Mixin.updateChildren (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:50123:12)↵ at ReactDOMComponent.Mixin._updateDOMChildren (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:45742:12)↵ at ReactDOMComponent.Mixin.updateComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:45571:10)↵ at ReactDOMComponent.Mixin.receiveComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:45527:10)↵ at Object.ReactReconciler.receiveComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:51396:22)↵ at ReactCompositeComponentMixin._updateRenderedComponent (file:///Users/jennifer/Dev/Projects/cypress-core-desktop-gui/dist/app.js:44547:23)',
type: 'PORT_IN_USE_SHORT',
}

it('displays configuration change warning', function () {
this.config.resolved.baseUrl.value = 'http://localhost:7777'

this.projectStatuses[0].id = this.config.projectId
this.getProjectStatus.resolve(this.projectStatuses[0])
this.openProject.resolve(this.config)
this.goToSettings()
cy.contains('Configuration').click()

cy.contains('http://localhost:7777').then(() => {
this.ipc.openProject.onCall(1).rejects(this.err)

this.ipc.onConfigChanged.yield()
cy.contains('Restart').should('not.exist')
cy.contains('http://localhost:7777').then(function () {
this.ipc.onConfigChanged.yield({}, '/Users/Jane/Dev/my-application/file.ext')
cy.contains('file.ext was modified. Restart Cypress for changes to take effect.')
})
})

it('displays errors', () => {
cy.contains('Can\'t start server')
})

it('displays config after error is fixed', function () {
cy.contains('Can\'t start server').then(() => {
this.ipc.openProject.onCall(1).resolves(this.config)

this.ipc.onConfigChanged.yield()
})

cy.contains('Configuration')
})
})

context('when project is not set up for CI', () => {
Expand Down Expand Up @@ -595,6 +517,52 @@ describe('Settings', () => {
cy.contains('set from custom config file special-cypress.json')
})
})

context('when env settings are set', function () {
it('displays value of env', function () {
this.openProject.resolve(this.config)
this.projectStatuses[0].id = this.config.projectId
this.getProjectStatus.resolve(this.projectStatuses[0])

this.goToSettings()

cy.contains('Configuration').click()
cy.contains('.line', 'env:fileServerFolder')
})

it('displays null when undefined', function () {
this.openProject.resolve(setConfigEnv(this.config, undefined))
this.projectStatuses[0].id = this.config.projectId
this.getProjectStatus.resolve(this.projectStatuses[0])

this.goToSettings()

cy.contains('Configuration').click()
cy.contains('.line', 'env:null')
})

it('displays null when null', function () {
this.openProject.resolve(setConfigEnv(this.config, null))
this.projectStatuses[0].id = this.config.projectId
this.getProjectStatus.resolve(this.projectStatuses[0])

this.goToSettings()

cy.contains('Configuration').click()
cy.contains('.line', 'env:null')
})

it('displays null when empty', function () {
this.openProject.resolve(setConfigEnv(this.config, {}))
this.projectStatuses[0].id = this.config.projectId
this.getProjectStatus.resolve(this.projectStatuses[0])

this.goToSettings()

cy.contains('Configuration').click()
cy.contains('.line', 'env:null')
})
})
})

// --
Expand Down
31 changes: 31 additions & 0 deletions packages/desktop-gui/cypress/integration/warning_message_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,35 @@ describe('Warning Message', function () {
.should('not.contain', 'Other message')
})
})

describe('for error type CONFIGURATION_CHANGED', function () {
beforeEach(function () {
this.configWarningObj = {
type: 'CONFIGURATION_CHANGED',
name: 'Configuration changed',
message: '`cypress.json` was modified. Restart Cypress for changes to take effect.',
}

cy.shouldBeOnProjectSpecs().then(function () {
this.ipc.onProjectWarning.yield(null, this.configWarningObj)
})
})

it('renders configuration change message with the correct file name', function () {
cy.contains('.alert-warning', 'cypress.json was modified. Restart Cypress for changes to take effect.')
})

it('is not dismissable', function () {
cy.get('.alert-warning .close').should('not.exist')
})

it('can reload the project', function () {
cy.contains('.alert-warning button', 'Restart')
.click()
.should(function () {
expect(this.ipc.closeProject).to.be.called
expect(this.ipc.openProject).to.be.called
})
})
})
})
4 changes: 4 additions & 0 deletions packages/desktop-gui/src/lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ const errors = {
isUnknown (err) {
return _.get(err, 'type') === 'UNKNOWN'
},

isConfigurationChanged (err) {
return _.get(err, 'type') === 'CONFIGURATION_CHANGED'
},
}

export default errors
1 change: 1 addition & 0 deletions packages/desktop-gui/src/lib/ipc.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ register('on:spec:changed', false)
register('on:project:error', false)
register('on:project:warning', false)
register('ping:api:server')
register('on:reload:configuration:requested', false)
register('remove:project')
register('request:access')
register('setup:dashboard:project')
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-gui/src/project/project.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class Project extends Component {
const { warnings } = this.props.project

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

_removeWarning = (warning) => {
Expand Down
18 changes: 17 additions & 1 deletion packages/desktop-gui/src/project/warning-message.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import React, { Component } from 'react'
import { observer } from 'mobx-react'
import errors from '../lib/errors'
import projectsApi from '../projects/projects-api'
import MarkdownRenderer from '../lib/markdown-renderer'

@observer
class WarningMessage extends Component {
render () {
const warningText = this.props.warning.message.split('\n').join('<br />')
const warning = this.props.warning
const warningText = warning.message.split('\n').join('<br />')
const reloadConfiguration = () => () => projectsApi.reloadConfiguration(this.props.project)

if (errors.isConfigurationChanged(warning)) {
return (
<div className='alert alert-warning centered'>
<MarkdownRenderer markdown={warningText} />
<button className='restart' onClick={reloadConfiguration()}>
<i className='fas fa-sync-alt'></i>
Restart
</button>
</div>
)
}

return (
<div className='alert alert-warning'>
Expand Down
21 changes: 19 additions & 2 deletions packages/desktop-gui/src/projects/projects-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,12 @@ const openProject = (project) => {
specsStore.setChosenSpecByRelativePath(relativeSpecPath)
})

ipc.onConfigChanged(() => {
reopenProject(project)
ipc.onConfigChanged((__, filePath) => {
project.addWarning({
isCypressErr: true,
type: 'CONFIGURATION_CHANGED',
message: `\`${filePath}\` was modified. Restart Cypress for changes to take effect.`,
})
})

ipc.onProjectError((__, error) => {
Expand All @@ -177,6 +181,10 @@ const openProject = (project) => {
project.addWarning(warning)
})

ipc.onReloadConfigurationRequested(() => {
reloadConfiguration(project)
})

return ipc.openProject(project.path)
.then((config = {}) => {
updateConfig(config)
Expand Down Expand Up @@ -214,6 +222,14 @@ const updateProject = (project, projectDetails) => {
saveToLocalStorage()
}

const reloadConfiguration = (project) => {
const chosenSpec = specsStore.chosenSpec

reopenProject(project).then(() => {
return runSpec(project, chosenSpec, project.chosenBrowser)
})
}

const getRecordKeys = () => {
return ipc.getRecordKeys()
.catch(ipc.isUnauthed, ipc.handleUnauthed)
Expand All @@ -233,5 +249,6 @@ export default {
updateProject,
runSpec,
closeBrowser,
reloadConfiguration,
getRecordKeys,
}
2 changes: 2 additions & 0 deletions packages/desktop-gui/src/specs/specs-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const pathsEqual = (path1, path2) => {
export class SpecsStore {
@observable _files = []
@observable chosenSpecPath
@observable chosenSpec
@observable error
@observable isLoading = false
@observable filter
Expand All @@ -52,6 +53,7 @@ export class SpecsStore {

@action setChosenSpec (spec) {
this.chosenSpecPath = spec ? formRelativePath(spec) : null
this.chosenSpec = spec
}

@action setChosenSpecByRelativePath (relativePath) {
Expand Down
26 changes: 25 additions & 1 deletion packages/desktop-gui/src/styles/components/_alerts.scss
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,32 @@
position: relative;

code, pre {
border: none;
color: #8a6d3b;
border: 1px solid #ddd;
}

&.centered {
align-items: center;
display: flex;
flex-direction: column;

p {
margin: 0;
}
}

.restart {
position: relative;
background: none;
text-decoration: underline;
padding: none;
font-weight: 500;
border: none;
cursor: pointer;

i {
margin-right: 0.2rem;
}
}
}

Expand Down
Loading