Skip to content

Commit

Permalink
Merge pull request #722 from oskarhane/multi-statements
Browse files Browse the repository at this point in the history
Add support for multi-statement execution
  • Loading branch information
pe4cey authored Jul 2, 2018
2 parents d160a4b + a20c9d4 commit e3db5e2
Show file tree
Hide file tree
Showing 42 changed files with 1,671 additions and 385 deletions.
53 changes: 28 additions & 25 deletions e2e_tests/integration/0.index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

/* global Cypress, cy, test, expect */

const Editor = '.ReactCodeMirror textarea'
const Carousel = '[data-test-id="carousel"]'
const SubmitQueryButton = '[data-test-id="submitQuery"]'
const Editor = '.ReactCodeMirror textarea'
const ClearEditorButton = '[data-test-id="clearEditorContent"]'

describe('Neo4j Browser', () => {
Expand All @@ -38,64 +38,68 @@ describe('Neo4j Browser', () => {
})
it('can connect', () => {
const password = Cypress.env('browser-password') || 'newpassword'
cy.connect('neo4j', password)
cy.connect(
'neo4j',
password
)
})
it('can empty the db', () => {
cy.executeCommand(':clear')
const query = 'MATCH (n) DETACH DELETE n'
cy.executeCommand(query)
cy.waitForCommandResult()
cy
.get('[data-test-id="frameCommand"]', { timeout: 10000 })
cy.get('[data-test-id="frameCommand"]', { timeout: 10000 })
.first()
.should('contain', query)
cy
.get('[data-test-id="frameStatusbar"]', { timeout: 100000 })
cy.get('[data-test-id="frameStatusbar"]', { timeout: 100000 })
.first()
.contains(/completed/i)
})
it('can run cypher statement', () => {
cy.executeCommand(':clear')
const query = 'return 1'
const query = 'RETURN 1'
cy.executeCommand(query)
cy.waitForCommandResult()
cy
.get('[data-test-id="frameCommand"]', { timeout: 10000 })
cy.get('[data-test-id="frameCommand"]', { timeout: 10000 })
.first()
.should('contain', query)
cy
.get('[data-test-id="frameStatusbar"]', { timeout: 10000 })
cy.get('[data-test-id="frameStatusbar"]', { timeout: 10000 })
.first()
.should('contain', 'Started streaming')
})
it('shows error frame for unknown command', () => {
cy.executeCommand(':clear')
const query = ':unknown'
cy.executeCommand(query)
cy.get('[data-test-id="frameCommand"]', { timeout: 10000 })
.first()
.should('contain', query)
cy.get('[data-test-id="frame"]', { timeout: 10000 })
.first()
.should('contain', 'Error')
})
it('can exec cypher from `:play movies`', () => {
cy.executeCommand(':clear')
const query = ':play movies'
cy.executeCommand(query)
cy
.get('[data-test-id="frameCommand"]')
cy.get('[data-test-id="frameCommand"]')
.first()
.should('contain', query)
cy
.get(Carousel)
cy.get(Carousel)
.find('[data-test-id="nextSlide"]')
.click()
cy
.get(Carousel)
cy.get(Carousel)
.find('[data-test-id="nextSlide"]')
.click()
cy
.get(Carousel)
cy.get(Carousel)
.find('[data-test-id="previousSlide"]')
.click()
cy
.get(Carousel)
cy.get(Carousel)
.find('.code')
.click()
cy.get(SubmitQueryButton).click()
cy.waitForCommandResult()
cy
.get('[data-test-id="frameCommand"]', { timeout: 10000 })
cy.get('[data-test-id="frameCommand"]', { timeout: 10000 })
.first()
.should('contain', 'Emil Eifrem')
})
Expand All @@ -112,8 +116,7 @@ describe('Neo4j Browser', () => {
cy.get('[data-test-id="editorFavorite"]').click()

cy.get('[data-test-id="drawerFavorites"]').click()
cy
.get('[data-test-id="sidebarFavoriteItem"]')
cy.get('[data-test-id="sidebarFavoriteItem"]')
.first()
.should('be', scriptName)

Expand Down
90 changes: 90 additions & 0 deletions e2e_tests/integration/multistatements.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2002-2018 "Neo4j, Inc"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/* global Cypress, cy, test, expect */

describe('Multi statements', () => {
it('can connect', () => {
const password = Cypress.env('browser-password') || 'newpassword'
cy.connect(
'neo4j',
password
)
})
it('can run multiple statements (non open by default)', () => {
cy.executeCommand(':clear')
const query = 'RETURN 1; :config; RETURN 2;'
cy.executeCommand(query)
cy.get('[data-test-id="frame"]', { timeout: 10000 }).should(
'have.length',
1
)
const frame = cy.get('[data-test-id="frame"]', { timeout: 10000 }).first()
frame.get('[data-test-id="multi-statement-list"]').should('have.length', 1)
frame
.get('[data-test-id="multi-statement-list-title"]')
.should('have.length', 3)
frame
.get('[data-test-id="multi-statement-list-content"]')
.should('have.length', 0)
})
it('can run multiple statements with error open', () => {
cy.executeCommand(':clear')
const query = 'RETURN 1; RETURN $nonsetparam; RETURN 2;'
cy.executeCommand(query)
cy.get('[data-test-id="frame"]', { timeout: 10000 }).should(
'have.length',
1
)
const frame = cy.get('[data-test-id="frame"]', { timeout: 10000 }).first()
frame.find('[data-test-id="multi-statement-list"]').should('have.length', 1)
frame
.get('[data-test-id="multi-statement-list-title"]')
.should('have.length', 3)
frame
.get('[data-test-id="multi-statement-list-content"]', { timeout: 10000 })
.should('have.length', 1)
frame
.get('[data-test-id="multi-statement-list-content"]', { timeout: 10000 })
.first()
.should('contain', 'ERROR')
})
it('Takes any statements (not just valid cypher and client commands)', () => {
cy.executeCommand(':clear')
const query = 'RETURN 1; hello1; RETURN 2; hello2;'
cy.executeCommand(query)
cy.get('[data-test-id="frame"]', { timeout: 10000 }).should(
'have.length',
1
)
const frame = cy.get('[data-test-id="frame"]', { timeout: 10000 }).first()
frame.find('[data-test-id="multi-statement-list"]').should('have.length', 1)
frame
.get('[data-test-id="multi-statement-list-title"]')
.should('have.length', 4)
frame
.get('[data-test-id="multi-statement-list-content"]', { timeout: 10000 })
.should('have.length', 1)
frame
.get('[data-test-id="multi-statement-list-content"]', { timeout: 10000 })
.first()
.should('contain', 'ERROR')
})
})
24 changes: 20 additions & 4 deletions e2e_tests/integration/params.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,38 @@ function runTests () {
let getParamQ
// it('can connect', () => {
const password = Cypress.env('browser-password') || 'newpassword'
cy.connect('neo4j', password)
cy.connect(
'neo4j',
password
)
// })
// it(':param x => 1+1', () => {
// Set param
cy.executeCommand(':clear')
setParamQ = ':param x => 1+1'
cy.executeCommand(setParamQ)
cy.resultContains('"x": 2')

// return param
cy.executeCommand(':clear')
getParamQ = 'RETURN $x'
cy.executeCommand(getParamQ)
cy.waitForCommandResult()
cy.resultContains('2')

// it(':param x => {prop: 1} multi line', () => {
// Set param
cy.executeCommand(':clear')
setParamQ = `:param x => {
prop: 1
}`
cy.executeCommand(setParamQ)
cy.resultContains('"prop": 1')
// return param
cy.executeCommand(':clear')
getParamQ = 'RETURN $x'
cy.executeCommand(getParamQ)
cy.waitForCommandResult()
cy.resultContains('"prop": 1')
// })

// it(':param x => 1.0', () => {
Expand Down Expand Up @@ -94,8 +111,7 @@ function runTests () {
":param x => point({{}crs: 'wgs-84', latitude: 57.7346, longitude: 12.9082})"
cy.executeCommand(query)

cy
.get('[data-test-id="rawParamData"]', { timeout: 20000 })
cy.get('[data-test-id="rawParamData"]', { timeout: 20000 })
.first()
.should('contain', '"x": point({srid:4326, x:12.9082, y:57.7346})')
getParamQ = 'RETURN $x'
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"raf/polyfill.js"
],
"testPathIgnorePatterns": [
".jsx$",
"/e2e_tests/"
],
"moduleNameMapper": {
Expand Down Expand Up @@ -130,13 +131,12 @@
"ascii-data-table": "^2.1.1",
"classnames": "^2.2.5",
"codemirror": "^5.29.0",
"cypher-codemirror": "^1.0.5",
"cypher-codemirror": "1.1.2",
"dnd-core": "^2.5.1",
"file-saver": "^1.3.8",
"firebase": "^4.3.0",
"isomorphic-fetch": "^2.2.1",
"jsonic": "^0.3.0",
"lodash.debounce": "^4.0.8",
"neo4j-driver": "^1.6.1",
"react": "^16.4.0",
"react-addons-pure-render-mixin": "^15.0.2",
Expand Down
81 changes: 81 additions & 0 deletions src/browser/components/Accordion/Accordion.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2002-2018 "Neo4j, Inc"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React, { Component } from 'react'
import { BorderedWrapper, TitleBar, ContentArea } from './styled'

class Accordion extends Component {
state = {
activeIndex: -1,
initialLoad: true
}
titleClick = index => {
const newIndex = this.state.activeIndex === index ? -1 : index
this.setState({ activeIndex: newIndex, initialLoad: false })
}
getChildProps = ({ index, defaultActive = false, forceActive = false }) => {
const props = {
titleProps: {
onClick: () => this.titleClick(index)
},
contentProps: {}
}
if (forceActive) {
props.titleProps.onClick = () => {}
}
if (defaultActive && this.state.initialLoad) {
props.titleProps.onClick = () => this.titleClick(-1)
}
if (
index === this.state.activeIndex ||
(this.state.initialLoad && defaultActive) ||
forceActive
) {
props.titleProps.active = true
props.contentProps.active = true
return props
}
props.titleProps.active = false
props.contentProps.active = false
return props
}
render () {
const { getChildProps } = this
const { render: renderProp, ...rest } = this.props
return (
<BorderedWrapper {...rest}>
{renderProp({ getChildProps })}
</BorderedWrapper>
)
}
}

const Title = ({ children, ...rest }) => {
return <TitleBar {...rest}>{children}</TitleBar>
}
Accordion.Title = Title

const Content = ({ children, active, ...rest }) => {
if (!active) return null
return <ContentArea {...rest}>{children}</ContentArea>
}
Accordion.Content = Content

export default Accordion
Loading

0 comments on commit e3db5e2

Please sign in to comment.