Skip to content

Commit

Permalink
Merge pull request #664 from oskarhane/3.0-desktop-integration
Browse files Browse the repository at this point in the history
Integrate with desktop API
  • Loading branch information
pe4cey authored Oct 17, 2017
2 parents 1d1f802 + 476c344 commit 6ed2f11
Show file tree
Hide file tree
Showing 20 changed files with 1,144 additions and 104 deletions.
29 changes: 12 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
"homepage": "https://neo4j.com",
"main": "dist/index.html",
"neo4jDesktop": {
"apiVersion": "1.0.0"
"apiVersion": "^1.2.0"
},
"scripts": {
"start": "webpack-dashboard -t 'Neo4j Browser' -- webpack-dev-server --colors --no-info",
"starts": "webpack-dashboard -t 'Neo4j Browser' -- webpack-dev-server --https --colors --no-info",
"start":
"webpack-dashboard -t 'Neo4j Browser' -- webpack-dev-server --colors --no-info",
"starts":
"webpack-dashboard -t 'Neo4j Browser' -- webpack-dev-server --https --colors --no-info",
"precommit": "lint-staged",
"format": "prettier-eslint 'src/**/!(*.min).js' 'src/**/*.jsx' --write",
"lint": "eslint --fix --ext .js --ext .jsx ./",
Expand All @@ -26,24 +28,20 @@
"build": "rm -rf ./dist && NODE_ENV=\"production\" webpack",
"prepare-jar": "node ./scripts/prepare-mvn-package.js",
"jar": "yarn build && mvn package",
"version-pom": "node ./scripts/set-pom-version.js -f ./pom.xml -v $npm_package_version",
"version-pom":
"node ./scripts/set-pom-version.js -f ./pom.xml -v $npm_package_version",
"version": "npm run version-pom && git add ./pom.xml"
},
"lint-staged": {
"linters": {
"*.{js,jsx}": [
"prettier-eslint --write",
"git add"
]
"*.{js,jsx}": ["prettier-eslint --write", "git add"]
}
},
"jest": {
"testPathIgnorePatterns": [
".jsx$",
"/e2e_tests/"
],
"testPathIgnorePatterns": [".jsx$", "/e2e_tests/"],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|html)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|html)$":
"<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
"neo4j": "<rootDir>/__mocks__/neo4j.js",
"^react-dom/server$": "preact-render-to-string",
Expand All @@ -55,10 +53,7 @@
"^browser-components(.*)$": "<rootDir>/src/browser/components$1",
"worker-loader": "<rootDir>/__mocks__/workerLoaderMock.js"
},
"modulePaths": [
"<rootDir>/src",
"<rootDir>/src/shared"
]
"modulePaths": ["<rootDir>/src", "<rootDir>/src/shared"]
},
"devDependencies": {
"autoprefixer": "^7.1.4",
Expand Down
90 changes: 90 additions & 0 deletions src/browser/components/DesktopIntegration/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2002-2017 "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/>.
*/

export const getActiveGraph = (context = {}) => {
if (!context) return null
const { projects } = context
if (!Array.isArray(projects)) return null
const activeProject = projects.find(project => {
if (!project) return false
if (!(project.graphs && Array.isArray(project.graphs))) return false
return project.graphs.find(({ status }) => status === 'ACTIVE')
})
if (!activeProject) return null
return activeProject.graphs.find(({ status }) => status === 'ACTIVE')
}

export const getCredentials = (type, connection) => {
if (!connection) return null
const { configuration = null } = connection
if (
!(
configuration &&
configuration.constructor &&
configuration.constructor === Object
)
) {
return null
}
if (
!(
configuration.protocols &&
configuration.protocols.constructor &&
configuration.protocols.constructor === Object
)
) {
return null
}
if (typeof configuration.protocols[type] === 'undefined') {
return null
}
return configuration.protocols[type]
}

// XXX_YYY -> onXxxYyy
export const eventToHandler = type => {
if (typeof type !== 'string') return null
return (
'on' +
splitOnUnderscore(type)
.filter(notEmpty)
.map(toLower)
.map(upperFirst)
.join('')
)
}
const notEmpty = str => str.length > 0
const splitOnUnderscore = str => str.split('_')
const toLower = str => str.toLowerCase()
const upperFirst = str => str[0].toUpperCase() + str.substring(1)

export const didChangeActiveGraph = (newContext, oldContext) => {
const oldActive = getActiveGraph(oldContext)
const newActive = getActiveGraph(newContext)
if (!oldActive && !newActive) return false // If no active before and after = nu change
return !(oldActive && newActive && newActive.id === oldActive.id)
}

export const getActiveCredentials = (type, context) => {
const activeGraph = getActiveGraph(context)
if (!activeGraph || typeof activeGraph.connection === 'undefined') return null
const creds = getCredentials('bolt', activeGraph.connection)
return creds || null
}
245 changes: 245 additions & 0 deletions src/browser/components/DesktopIntegration/helpers.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
/*
* Copyright (c) 2002-2017 "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 test, expect */
import {
getCredentials,
getActiveGraph,
eventToHandler,
didChangeActiveGraph,
getActiveCredentials
} from './helpers'

test('getActiveGraph handles non objects and non-active projects', () => {
// Given
const graphs = [
null,
'string',
undefined,
[1],
{ project: null },
{ projects: { x: 1 } },
{ projects: [{ x: 1 }] },
{ projects: [{ graphs: [{ status: 'NOPE' }] }] }
]

// When && Then
graphs.forEach(graph => {
expect(getActiveGraph(graph)).toEqual(null)
})
})
test('getActiveGraph handles expected objects', () => {
// Given
const graph = {
status: 'ACTIVE'
}
const graph2 = {
status: 'INACTIVE'
}
const apiResponse = {
projects: [
{
graphs: [graph, graph2]
}
]
}

// When
const activeGraph = getActiveGraph(apiResponse)

// Then
expect(activeGraph).toEqual(graph)
})

test('getCredentials handles non objects', () => {
// Given
const configs = [null, 'string', undefined, [1]]

// When && Then
configs.forEach(config => {
expect(getCredentials('xxx', config)).toBe(null)
})
})

test('getCredentials finds credentials on expected format', () => {
// Given

const config = {
bolt: {
username: 'molly',
password: 'stella'
},
http: {
username: 'oskar',
password: 'picachu'
}
}
const connection = {
configuration: { protocols: config }
}

// When
const boltRes = getCredentials('bolt', connection)
const httpRes = getCredentials('http', connection)
const notFoundRes = getCredentials('https', connection)

// Then
expect(boltRes).toEqual(config.bolt)
expect(httpRes).toEqual(config.http)
expect(notFoundRes).toBe(null)
})

test('XXX_YYY -> onXxxYyy', () => {
// Given
const tests = [
{ type: undefined, expect: null },
{ type: true, expect: null },
{ type: 'XXX', expect: 'onXxx' },
{ type: '_XXX', expect: 'onXxx' },
{ type: 'XXX_YYY', expect: 'onXxxYyy' },
{ type: 'XXX_YYY_ZZZ', expect: 'onXxxYyyZzz' },
{ type: 'xxx', expect: 'onXxx' },
{ type: 'xxx_yyy', expect: 'onXxxYyy' },
{ type: 'XXX_123', expect: 'onXxx123' },
{ type: '0', expect: 'on0' },
{ type: '1', expect: 'on1' },
{ type: 1, expect: null }
]

// When && Then
tests.forEach(test => {
expect(eventToHandler(test.type)).toEqual(test.expect)
})
})

test('didChangeActiveGraph detects if the active graph changed', () => {
// Given
const createApiResponse = graphs => ({
projects: [{ graphs }]
})
const id1Active = createApiResponse([
{ id: 1, status: 'ACTIVE' },
{ id: 2, status: 'INACTIVE' }
])
const id2Active = createApiResponse([
{ id: 1, status: 'INACTIVE' },
{ id: 2, status: 'ACTIVE' }
])
const noActive = createApiResponse([
{ id: 1, status: 'INACTIVE' },
{ id: 2, status: 'INACTIVE' }
])

// When
const noChange = didChangeActiveGraph(id1Active, id1Active)
const didChange = didChangeActiveGraph(id2Active, id1Active)
const didChange2 = didChangeActiveGraph(noActive, id1Active)
const noChange2 = didChangeActiveGraph(noActive, noActive)

// Then
expect(noChange).toBe(false)
expect(didChange).toBe(true)
expect(didChange2).toBe(true)
expect(noChange2).toBe(false)
})

test('getActiveCredentials finds the active connection from a context object and returns the creds', () => {
// Given
const bolt1 = {
username: 'one',
password: 'one1'
}
const bolt2 = {
username: 'two',
password: 'two2'
}
const createApiResponse = graphs => ({
projects: [{ graphs }]
})
const id1Active = createApiResponse([
{
id: 1,
status: 'ACTIVE',
connection: {
configuration: {
protocols: { bolt: bolt1 }
}
}
},
{
id: 2,
status: 'INACTIVE',
connection: {
configuration: {
protocols: { bolt: bolt2 }
}
}
}
])
const id2Active = createApiResponse([
{
id: 1,
status: 'INACTIVE',
connection: {
configuration: {
protocols: { bolt: bolt1 }
}
}
},
{
id: 2,
status: 'ACTIVE',
connection: {
configuration: {
protocols: { bolt: bolt2 }
}
}
}
])
const noActive = createApiResponse([
{
id: 1,
status: 'INACTIVE',
connection: {
configuration: {
protocols: { bolt: bolt1 }
}
}
},
{
id: 2,
status: 'INACTIVE',
connection: {
configuration: {
protocols: { bolt: bolt2 }
}
}
}
])

// When
const firstActive = getActiveCredentials('bolt', id1Active)
const secondActive = getActiveCredentials('bolt', id2Active)
const zeroActive = getActiveCredentials('bolt', noActive)

// Then
expect(firstActive).toEqual(bolt1)
expect(secondActive).toEqual(bolt2)
expect(zeroActive).toEqual(null)
})
Loading

0 comments on commit 6ed2f11

Please sign in to comment.