diff --git a/README.md b/README.md index a652beabe9f..663334cf3b3 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,18 @@ server=3.2|3.3|3.4|3.5 (default 3.4) browser-password= (default 'newpassword') include-import-tests=true|false (default false) bolt-url= (default localhost:7687) -E2E_TEST_ENV=local|null (if the initial set of pw should run or not) (default undefined) -BROWSER_URL= (default http://localhost:8080) ``` +Test environment options (cannot be set using the `--env` flag as the ones above). +These needs to be set before the test command is run. + +``` +CYPRESS_E2E_TEST_ENV=local|null (if the initial set of pw should run or not) (default undefined) +CYPRESS_BASE_URL= (default http://localhost:8080) +``` + +Example: `CYPRESS_E2E_TEST_ENV="local" CYPRESS_BASE_URL=http://localhost:8081 cypress open --env server=3.4` + ## Devtools Download these two chrome extensions: diff --git a/cypress.json b/cypress.json index de5366efb68..549b87e788e 100644 --- a/cypress.json +++ b/cypress.json @@ -1,6 +1,6 @@ { "animationDistanceThreshold": 5, - "baseUrl": null, + "baseUrl": "http://localhost:8080", "chromeWebSecurity": true, "defaultCommandTimeout": 4000, "environmentVariables": {}, diff --git a/e2e_tests/support/defaults.js b/e2e_tests/support/defaults.js index cc88c7e2c3e..5449914f72f 100644 --- a/e2e_tests/support/defaults.js +++ b/e2e_tests/support/defaults.js @@ -2,7 +2,7 @@ Cypress.config.serverVersion = parseFloat(Cypress.env('server')) || 3.4 Cypress.config.includeImportTests = Cypress.env('include-import-tests') || false -Cypress.config.url = Cypress.env('BROWSER_URL') || 'http://localhost:8080' +Cypress.config.url = '/' Cypress.config.password = Cypress.env('browser-password') || 'newpassword' Cypress.config.boltHost = Cypress.env('bolt-url') ? Cypress.env('bolt-url').split(':')[0] diff --git a/src/shared/modules/commands/commandsDuck.js b/src/shared/modules/commands/commandsDuck.js index 33989562ecd..2397d6f3222 100644 --- a/src/shared/modules/commands/commandsDuck.js +++ b/src/shared/modules/commands/commandsDuck.js @@ -30,7 +30,8 @@ import { extractWhitelistFromConfigString, addProtocolsToUrlList, firstSuccessPromise, - serialExecution + serialExecution, + resolveWhitelistWildcard } from 'services/utils' import helper from 'services/commandInterpreterHelper' import { addHistory } from '../history/historyDuck' @@ -45,7 +46,8 @@ import { UPDATE_SETTINGS, getAvailableSettings, fetchMetaData, - getRemoteContentHostnameWhitelist + getRemoteContentHostnameWhitelist, + getDefaultRemoteContentHostnameWhitelist } from '../dbMeta/dbMetaDuck' import { APP_START, USER_CLEAR } from 'shared/modules/app/appDuck' import { add as addFrame } from 'shared/modules/stream/streamDuck' @@ -256,7 +258,14 @@ export const fetchGuideFromWhitelistEpic = (some$, store) => } const whitelistStr = getRemoteContentHostnameWhitelist(store.getState()) const whitelist = extractWhitelistFromConfigString(whitelistStr) - const urlWhitelist = addProtocolsToUrlList(whitelist) + const defaultWhitelist = extractWhitelistFromConfigString( + getDefaultRemoteContentHostnameWhitelist(store.getState()) + ) + const resolvedWildcardWhitelist = resolveWhitelistWildcard( + whitelist, + defaultWhitelist + ) + const urlWhitelist = addProtocolsToUrlList(resolvedWildcardWhitelist) const guidesUrls = urlWhitelist.map(url => url + '/' + action.url) return firstSuccessPromise(guidesUrls, url => { // Get first successful fetch diff --git a/src/shared/modules/commands/remoteGuides.test.js b/src/shared/modules/commands/remoteGuides.test.js new file mode 100644 index 00000000000..357e35ce1b4 --- /dev/null +++ b/src/shared/modules/commands/remoteGuides.test.js @@ -0,0 +1,128 @@ +/* + * 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 . + */ + +/* global jest, describe, afterEach, test, expect */ +import { createEpicMiddleware } from 'redux-observable' +import { createBus } from 'suber' +import { + fetchGuideFromWhitelistAction, + fetchGuideFromWhitelistEpic +} from './commandsDuck' + +jest.mock('services/remote', () => { + const orig = require.requireActual('services/remote') + return { + ...orig, + get: jest.fn() + } +}) +const remote = require.requireMock('services/remote') + +jest.mock('shared/modules/dbMeta/dbMetaDuck', () => { + const orig = require.requireActual('shared/modules/dbMeta/dbMetaDuck') + return { + ...orig, + getRemoteContentHostnameWhitelist: jest.fn(), + getDefaultRemoteContentHostnameWhitelist: jest.fn() + } +}) +const dbMeta = require.requireMock('shared/modules/dbMeta/dbMetaDuck') + +describe('fetchGuideFromWhitelistEpic', () => { + afterEach(() => { + remote.get.mockReset() + dbMeta.getRemoteContentHostnameWhitelist.mockReset() + dbMeta.getDefaultRemoteContentHostnameWhitelist.mockReset() + }) + + it('resolves * to default whitelist when looking for a guide', done => { + // Given + const bus = createBus() + bus.applyReduxMiddleware(createEpicMiddleware(fetchGuideFromWhitelistEpic)) + remote.get.mockImplementation(() => Promise.reject(new Error('test'))) + dbMeta.getRemoteContentHostnameWhitelist.mockImplementation(() => '*') + dbMeta.getDefaultRemoteContentHostnameWhitelist.mockImplementation( + () => 'testurl1.test, testurl2.test' + ) + const $$responseChannel = 'test-channel' + const action = fetchGuideFromWhitelistAction('reco') + action.$$responseChannel = $$responseChannel + bus.one($$responseChannel, res => { + // Then + expect(dbMeta.getRemoteContentHostnameWhitelist).toHaveBeenCalledTimes(1) + expect( + dbMeta.getDefaultRemoteContentHostnameWhitelist + ).toHaveBeenCalledTimes(1) + expect(remote.get).toHaveBeenCalledTimes(4) // 2 times per hostname + expect(remote.get).toHaveBeenCalledWith('http://testurl1.test/reco', { + 'cache-control': 'no-cache', + pragma: 'no-cache' + }) + expect(remote.get).toHaveBeenCalledWith('https://testurl1.test/reco', { + 'cache-control': 'no-cache', + pragma: 'no-cache' + }) + expect(remote.get).toHaveBeenCalledWith('http://testurl2.test/reco', { + 'cache-control': 'no-cache', + pragma: 'no-cache' + }) + expect(remote.get).toHaveBeenCalledWith('https://testurl2.test/reco', { + 'cache-control': 'no-cache', + pragma: 'no-cache' + }) + done() + }) + bus.send(action.type, action) + }) + it('does not change behavior when * isnt involved', done => { + // Given + const bus = createBus() + bus.applyReduxMiddleware(createEpicMiddleware(fetchGuideFromWhitelistEpic)) + remote.get.mockImplementation(() => Promise.reject(new Error('test'))) + dbMeta.getRemoteContentHostnameWhitelist.mockImplementation( + () => 'configurl1.test' + ) + + dbMeta.getDefaultRemoteContentHostnameWhitelist.mockImplementation( + () => 'test1.test, test2.test' + ) + const $$responseChannel = 'test-channel' + const action = fetchGuideFromWhitelistAction('reco') + action.$$responseChannel = $$responseChannel + bus.one($$responseChannel, res => { + // Then + expect(dbMeta.getRemoteContentHostnameWhitelist).toHaveBeenCalledTimes(1) + expect( + dbMeta.getDefaultRemoteContentHostnameWhitelist + ).toHaveBeenCalledTimes(1) + expect(remote.get).toHaveBeenCalledTimes(2) + expect(remote.get).toHaveBeenCalledWith('http://configurl1.test/reco', { + 'cache-control': 'no-cache', + pragma: 'no-cache' + }) + expect(remote.get).toHaveBeenCalledWith('https://configurl1.test/reco', { + 'cache-control': 'no-cache', + pragma: 'no-cache' + }) + done() + }) + bus.send(action.type, action) + }) +}) diff --git a/src/shared/modules/dbMeta/dbMetaDuck.js b/src/shared/modules/dbMeta/dbMetaDuck.js index 5fb708c5e67..9f565f40f39 100644 --- a/src/shared/modules/dbMeta/dbMetaDuck.js +++ b/src/shared/modules/dbMeta/dbMetaDuck.js @@ -86,6 +86,8 @@ export const credentialsTimeout = state => export const getRemoteContentHostnameWhitelist = state => getAvailableSettings(state)['browser.remote_content_hostname_whitelist'] || initialState.settings['browser.remote_content_hostname_whitelist'] +export const getDefaultRemoteContentHostnameWhitelist = () => + initialState.settings['browser.remote_content_hostname_whitelist'] export const shouldRetainConnectionCredentials = state => { const settings = getAvailableSettings(state) const conf = settings['browser.retain_connection_credentials'] diff --git a/src/shared/services/utils.js b/src/shared/services/utils.js index 7b989cb39b1..319f1a62237 100644 --- a/src/shared/services/utils.js +++ b/src/shared/services/utils.js @@ -181,6 +181,15 @@ export const addProtocolsToUrlList = list => { }, []) } +export const resolveWhitelistWildcard = (list, resolveTo = []) => { + return list.reduce((all, entry) => { + if (entry && entry.trim() === '*') { + entry = resolveTo + } + return all.concat(entry) + }, []) +} + export const getUrlInfo = url => { let protocolMissing = false diff --git a/src/shared/services/utils.test.js b/src/shared/services/utils.test.js index 6f01f71d91b..8b252466ab9 100644 --- a/src/shared/services/utils.test.js +++ b/src/shared/services/utils.test.js @@ -369,6 +369,43 @@ describe('utils', () => { ]) }) }) + describe('resolveWhitelistWildcard', () => { + test('Resolves * to given urls', () => { + // Given + const input = ['*'] + const resolveTo = ['guides.neo4j.com', 'localhost'] + + // When + const res = utils.resolveWhitelistWildcard(input, resolveTo) + + // Then + expect(res).toEqual(['guides.neo4j.com', 'localhost']) + }) + test('Resolves * to given urls when in a list', () => { + // Given + const input = [ + 'http://test.com', + 'oskarhane.com', + '*', + null, + 'https://mysite.com/guides' + ] + const resolveTo = ['guides.neo4j.com', 'localhost'] + + // When + const res = utils.resolveWhitelistWildcard(input, resolveTo) + + // Then + expect(res).toEqual([ + 'http://test.com', + 'oskarhane.com', + 'guides.neo4j.com', + 'localhost', + null, + 'https://mysite.com/guides' + ]) + }) + }) describe('hostIsAllowed', () => { test('should respect host whitelist', () => { // Given