* Update to React 16 * Add missing promise catch * Fix jest tests * extract react-dom mock * remove empty snapshots * Fix modalstags/7.0-RC1
@@ -0,0 +1,23 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser 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 | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import Enzyme from 'enzyme'; | |||
import Adapter from 'enzyme-adapter-react-16'; | |||
Enzyme.configure({ adapter: new Adapter() }); |
@@ -22,3 +22,9 @@ window.t = window.tp = function() { | |||
const args = Array.prototype.slice.call(arguments, 0); | |||
return args.join('.'); | |||
}; | |||
// Fix for https://github.com/facebook/jest/issues/4545 | |||
// Try to remove when jest 21.3.0 is out | |||
window.requestAnimationFrame = function(callback) { | |||
setTimeout(callback, 0); | |||
}; |
@@ -26,14 +26,14 @@ | |||
"lodash": "4.17.4", | |||
"prop-types": "15.6.0", | |||
"rc-tooltip": "3.5.0", | |||
"react": "15.6.2", | |||
"react-dom": "15.6.2", | |||
"react": "16.0.0", | |||
"react-dom": "16.0.0", | |||
"react-draggable": "3.0.3", | |||
"react-helmet": "5.2.0", | |||
"react-intl": "2.4.0", | |||
"react-modal": "3.0.4", | |||
"react-redux": "5.0.6", | |||
"react-router": "3.0.5", | |||
"react-router": "3.2.0", | |||
"react-select": "1.0.0-rc.10", | |||
"react-virtualized": "9.12.0", | |||
"redux": "3.7.2", | |||
@@ -46,20 +46,19 @@ | |||
"@types/classnames": "2.2.3", | |||
"@types/d3-array": "1.2.1", | |||
"@types/d3-scale": "1.0.10", | |||
"@types/date-fns": "2.6.0", | |||
"@types/enzyme": "2.8.6", | |||
"@types/enzyme": "3.1.1", | |||
"@types/escape-html": "0.0.20", | |||
"@types/jest": "21.1.5", | |||
"@types/jquery": "3.2.11", | |||
"@types/lodash": "4.14.79", | |||
"@types/lodash": "4.14.80", | |||
"@types/prop-types": "15.5.2", | |||
"@types/react": "16.0.2", | |||
"@types/react-dom": "15.5.2", | |||
"@types/react": "16.0.19", | |||
"@types/react-dom": "16.0.2", | |||
"@types/react-helmet": "5.0.3", | |||
"@types/react-intl": "2.3.2", | |||
"@types/react-modal": "2.2.2", | |||
"@types/react-redux": "5.0.10", | |||
"@types/react-router": "3.0.5", | |||
"@types/react-redux": "5.0.12", | |||
"@types/react-router": "3.0.13", | |||
"@types/react-select": "1.0.59", | |||
"autoprefixer": "7.1.6", | |||
"awesome-typescript-loader": "3.2.3", | |||
@@ -77,8 +76,9 @@ | |||
"babel-preset-react": "^6.22.0", | |||
"chalk": "2.3.0", | |||
"css-loader": "0.28.7", | |||
"enzyme": "2.9.1", | |||
"enzyme-to-json": "2.0.1", | |||
"enzyme": "3.1.0", | |||
"enzyme-adapter-react-16": "1.0.2", | |||
"enzyme-to-json": "3.1.4", | |||
"eslint": "4.9.0", | |||
"eslint-plugin-import": "2.8.0", | |||
"eslint-plugin-jsx-a11y": "6.0.2", | |||
@@ -96,10 +96,10 @@ | |||
"postcss-loader": "2.0.8", | |||
"prettier": "1.7.4", | |||
"react-error-overlay": "1.0.7", | |||
"react-test-renderer": "15.6.2", | |||
"react-test-renderer": "16.0.0", | |||
"rimraf": "2.6.2", | |||
"style-loader": "0.19.0", | |||
"ts-jest": "21.1.3", | |||
"ts-jest": "21.1.4", | |||
"typescript": "2.5.3", | |||
"typescript-eslint-parser": "8.0.1", | |||
"webpack": "3.8.1", | |||
@@ -141,7 +141,8 @@ | |||
}, | |||
"setupFiles": [ | |||
"<rootDir>/config/polyfills.js", | |||
"<rootDir>/config/jest/SetupTestEnvironment.js" | |||
"<rootDir>/config/jest/SetupTestEnvironment.js", | |||
"<rootDir>/config/jest/SetupEnzyme.js" | |||
], | |||
"snapshotSerializers": ["enzyme-to-json/serializer"], | |||
"testPathIgnorePatterns": [ |
@@ -0,0 +1,26 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser 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 | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
const ReactDOM = require.requireActual('react-dom'); | |||
//FIXME To be dropped when https://github.com/airbnb/enzyme/issues/1150 is resolved | |||
module.exports = { | |||
...ReactDOM, | |||
createPortal: (children: React.ReactNode) => children | |||
}; |
@@ -17,23 +17,29 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first */ | |||
jest.mock('../../../api/branches', () => ({ getBranches: jest.fn() })); | |||
jest.mock('../../../api/components', () => ({ getComponentData: jest.fn() })); | |||
jest.mock('../../../api/nav', () => ({ getComponentNavigation: jest.fn() })); | |||
// mock this, because some of its children are using redux store | |||
jest.mock('../nav/component/ComponentNav', () => ({ | |||
default: () => null | |||
})); | |||
import * as React from 'react'; | |||
import { shallow, mount } from 'enzyme'; | |||
import { ComponentContainer } from '../ComponentContainer'; | |||
import { getBranches } from '../../../api/branches'; | |||
import { getComponentData } from '../../../api/components'; | |||
import { getComponentNavigation } from '../../../api/nav'; | |||
import { doAsync } from '../../../helpers/testUtils'; | |||
jest.mock('../../../api/branches', () => ({ getBranches: jest.fn(() => Promise.resolve([])) })); | |||
jest.mock('../../../api/components', () => ({ | |||
getComponentData: jest.fn(() => Promise.resolve({})) | |||
})); | |||
jest.mock('../../../api/nav', () => ({ | |||
getComponentNavigation: jest.fn(() => | |||
Promise.resolve({ | |||
breadcrumbs: [{ key: 'portfolioKey', name: 'portfolio', qualifier: 'VW' }] | |||
}) | |||
) | |||
})); | |||
// mock this, because some of its children are using redux store | |||
jest.mock('../nav/component/ComponentNav', () => ({ | |||
default: () => null | |||
})); | |||
const Inner = () => <div />; | |||
@@ -60,10 +66,8 @@ it('changes component', () => { | |||
expect(wrapper.state().component).toEqual({ qualifier: 'TRK', visibility: 'private' }); | |||
}); | |||
it("loads branches for module's project", () => { | |||
(getBranches as jest.Mock<any>).mockImplementation(() => Promise.resolve([])); | |||
(getComponentData as jest.Mock<any>).mockImplementation(() => Promise.resolve({})); | |||
(getComponentNavigation as jest.Mock<any>).mockImplementation(() => | |||
it("loads branches for module's project", async () => { | |||
(getComponentNavigation as jest.Mock<any>).mockImplementationOnce(() => | |||
Promise.resolve({ | |||
breadcrumbs: [ | |||
{ key: 'projectKey', name: 'project', qualifier: 'TRK' }, | |||
@@ -78,38 +82,28 @@ it("loads branches for module's project", () => { | |||
</ComponentContainer> | |||
); | |||
return doAsync().then(() => { | |||
expect(getBranches).toBeCalledWith('projectKey'); | |||
expect(getComponentData).toBeCalledWith('moduleKey', undefined); | |||
expect(getComponentNavigation).toBeCalledWith('moduleKey', undefined); | |||
}); | |||
await new Promise(setImmediate); | |||
expect(getBranches).toBeCalledWith('projectKey'); | |||
expect(getComponentData).toBeCalledWith('moduleKey', undefined); | |||
expect(getComponentNavigation).toBeCalledWith('moduleKey', undefined); | |||
}); | |||
it("doesn't load branches portfolio", () => { | |||
(getBranches as jest.Mock<any>).mockImplementation(() => Promise.resolve([])); | |||
(getComponentData as jest.Mock<any>).mockImplementation(() => Promise.resolve({})); | |||
(getComponentNavigation as jest.Mock<any>).mockImplementation(() => | |||
Promise.resolve({ | |||
breadcrumbs: [{ key: 'portfolioKey', name: 'portfolio', qualifier: 'VW' }] | |||
}) | |||
); | |||
it("doesn't load branches portfolio", async () => { | |||
const wrapper = mount( | |||
<ComponentContainer fetchOrganizations={jest.fn()} location={{ query: { id: 'portfolioKey' } }}> | |||
<Inner /> | |||
</ComponentContainer> | |||
); | |||
return doAsync().then(() => { | |||
expect(getBranches).not.toBeCalled(); | |||
expect(getComponentData).toBeCalledWith('portfolioKey', undefined); | |||
expect(getComponentNavigation).toBeCalledWith('portfolioKey', undefined); | |||
expect(wrapper.find(Inner).exists()).toBeTruthy(); | |||
}); | |||
await new Promise(setImmediate); | |||
expect(getBranches).not.toBeCalled(); | |||
expect(getComponentData).toBeCalledWith('portfolioKey', undefined); | |||
expect(getComponentNavigation).toBeCalledWith('portfolioKey', undefined); | |||
wrapper.update(); | |||
expect(wrapper.find(Inner).exists()).toBeTruthy(); | |||
}); | |||
it('updates branches on change', () => { | |||
(getBranches as jest.Mock<any>).mockImplementation(() => Promise.resolve([])); | |||
const wrapper = shallow( | |||
<ComponentContainer fetchOrganizations={jest.fn()} location={{ query: { id: 'portfolioKey' } }}> | |||
<Inner /> | |||
@@ -125,8 +119,8 @@ it('updates branches on change', () => { | |||
expect(getBranches).toBeCalledWith('projectKey'); | |||
}); | |||
it('loads organization', () => { | |||
(getComponentData as jest.Mock<any>).mockImplementation(() => | |||
it('loads organization', async () => { | |||
(getComponentData as jest.Mock<any>).mockImplementationOnce(() => | |||
Promise.resolve({ organization: 'org' }) | |||
); | |||
@@ -140,7 +134,6 @@ it('loads organization', () => { | |||
</ComponentContainer> | |||
); | |||
return doAsync().then(() => { | |||
expect(fetchOrganizations).toBeCalledWith(['org']); | |||
}); | |||
await new Promise(setImmediate); | |||
expect(fetchOrganizations).toBeCalledWith(['org']); | |||
}); |
@@ -17,7 +17,11 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first, import/order */ | |||
/* eslint-disable import/order */ | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import ComponentNav from '../ComponentNav'; | |||
jest.mock('../ComponentNavFavorite', () => ({ | |||
// eslint-disable-next-line | |||
default: function ComponentNavFavorite() { | |||
@@ -47,10 +51,6 @@ jest.mock('../../../../../api/ce', () => ({ | |||
getTasksForComponent: jest.fn(() => Promise.resolve({ queue: [] })) | |||
})); | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import ComponentNav from '../ComponentNav'; | |||
const getTasksForComponent = require('../../../../../api/ce').getTasksForComponent as jest.Mock< | |||
any | |||
>; |
@@ -21,6 +21,7 @@ exports[`renders 1`] = ` | |||
"qualifier": "TRK", | |||
} | |||
} | |||
currentTask={undefined} | |||
isInProgress={true} | |||
isPending={true} | |||
/> |
@@ -64,7 +64,7 @@ export default class SettingsEditionsNotif extends React.PureComponent<Props, St | |||
</button> | |||
)} | |||
{!preventRestart && | |||
this.state.openRestart && <RestartForm onClose={this.hanleCloseRestart} />} | |||
this.state.openRestart && <RestartForm onClose={this.hanleCloseRestart} />} | |||
</NavBarNotif> | |||
); | |||
} | |||
@@ -73,14 +73,12 @@ export default class SettingsEditionsNotif extends React.PureComponent<Props, St | |||
const { editionStatus } = this.props; | |||
return ( | |||
<NavBarNotif className="alert alert-danger"> | |||
{edition ? ( | |||
translateWithParameters( | |||
'marketplace.status_x.' + editionStatus.installationStatus, | |||
edition.name | |||
) | |||
) : ( | |||
translate('marketplace.status', editionStatus.installationStatus) | |||
)} | |||
{edition | |||
? translateWithParameters( | |||
'marketplace.status_x.' + editionStatus.installationStatus, | |||
edition.name | |||
) | |||
: translate('marketplace.status', editionStatus.installationStatus)} | |||
{edition && ( | |||
<a | |||
className="button spacer-left" |
@@ -118,6 +118,7 @@ it('shows tooltip after delay', () => { | |||
expect(wrapper.find('Tooltip').prop('visible')).toBe(false); | |||
jest.runAllTimers(); | |||
wrapper.update(); | |||
expect(wrapper.find('Tooltip').prop('visible')).toBe(true); | |||
wrapper.setProps({ selected: false }); |
@@ -30,8 +30,8 @@ export default class UserExternalIdentity extends React.PureComponent { | |||
this.fetchIdentityProviders(); | |||
} | |||
componentDidUpdate(nextProps) { | |||
if (nextProps.user !== this.props.user) { | |||
componentDidUpdate(prevProps) { | |||
if (prevProps.user !== this.props.user) { | |||
this.this.fetchIdentityProviders(); | |||
} | |||
} |
@@ -47,11 +47,18 @@ export default class Stacktrace extends React.PureComponent<Props, State> { | |||
} | |||
loadStacktrace() { | |||
getTask(this.props.task.id, ['stacktrace']).then(task => { | |||
if (this.mounted) { | |||
this.setState({ loading: false, stacktrace: task.errorStacktrace }); | |||
getTask(this.props.task.id, ['stacktrace']).then( | |||
task => { | |||
if (this.mounted) { | |||
this.setState({ loading: false, stacktrace: task.errorStacktrace }); | |||
} | |||
}, | |||
() => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
} | |||
}); | |||
); | |||
} | |||
handleCloseClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => { |
@@ -56,15 +56,22 @@ export default class Workers extends React.PureComponent<{}, State> { | |||
loadWorkers = () => { | |||
this.setState({ loading: true }); | |||
getWorkers().then(({ canSetWorkerCount, value }) => { | |||
if (this.mounted) { | |||
this.setState({ | |||
canSetWorkerCount, | |||
loading: false, | |||
workerCount: value | |||
}); | |||
getWorkers().then( | |||
({ canSetWorkerCount, value }) => { | |||
if (this.mounted) { | |||
this.setState({ | |||
canSetWorkerCount, | |||
loading: false, | |||
workerCount: value | |||
}); | |||
} | |||
}, | |||
() => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
} | |||
}); | |||
); | |||
}; | |||
closeForm = (newWorkerCount?: number) => |
@@ -17,15 +17,17 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first, import/order */ | |||
jest.mock('../../../../api/ce', () => ({ | |||
getTask: jest.fn() | |||
})); | |||
/* eslint-disable import/order */ | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import ScannerContext from '../ScannerContext'; | |||
import { click, doAsync } from '../../../../helpers/testUtils'; | |||
import { click } from '../../../../helpers/testUtils'; | |||
jest.mock('react-dom'); | |||
jest.mock('../../../../api/ce', () => ({ | |||
getTask: jest.fn(() => Promise.resolve({ scannerContext: 'context' })) | |||
})); | |||
const getTask = require('../../../../api/ce').getTask as jest.Mock<any>; | |||
@@ -37,6 +39,10 @@ const task = { | |||
type: 'REPORT' | |||
}; | |||
beforeEach(() => { | |||
getTask.mockClear(); | |||
}); | |||
it('renders', () => { | |||
const wrapper = shallow(<ScannerContext onClose={jest.fn()} task={task} />); | |||
wrapper.setState({ scannerContext: 'context' }); | |||
@@ -50,12 +56,10 @@ it('closes', () => { | |||
expect(onClose).toBeCalled(); | |||
}); | |||
it('fetches scanner context on mount', () => { | |||
getTask.mockImplementation(() => Promise.resolve({ scannerContext: 'context' })); | |||
it('fetches scanner context on mount', async () => { | |||
const wrapper = mount(<ScannerContext onClose={jest.fn()} task={task} />); | |||
expect(wrapper.state()).toEqual({}); | |||
expect(getTask).toBeCalledWith('123', ['scannerContext']); | |||
return doAsync().then(() => { | |||
expect(wrapper.state()).toEqual({ scannerContext: 'context' }); | |||
}); | |||
await new Promise(setImmediate); | |||
expect(wrapper.state()).toEqual({ scannerContext: 'context' }); | |||
}); |
@@ -17,15 +17,17 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first, import/order */ | |||
jest.mock('../../../../api/ce', () => ({ | |||
getTask: jest.fn() | |||
})); | |||
/* eslint-disable import/order */ | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import Stacktrace from '../Stacktrace'; | |||
import { click, doAsync } from '../../../../helpers/testUtils'; | |||
import { click } from '../../../../helpers/testUtils'; | |||
jest.mock('react-dom'); | |||
jest.mock('../../../../api/ce', () => ({ | |||
getTask: jest.fn(() => Promise.resolve({ errorStacktrace: 'stacktrace' })) | |||
})); | |||
const getTask = require('../../../../api/ce').getTask as jest.Mock<any>; | |||
@@ -37,6 +39,10 @@ const task = { | |||
type: 'REPORT' | |||
}; | |||
beforeEach(() => { | |||
getTask.mockClear(); | |||
}); | |||
it('renders', () => { | |||
const wrapper = shallow(<Stacktrace onClose={jest.fn()} task={task} />); | |||
wrapper.setState({ loading: false, stacktrace: 'stacktrace' }); | |||
@@ -50,12 +56,10 @@ it('closes', () => { | |||
expect(onClose).toBeCalled(); | |||
}); | |||
it('fetches scanner context on mount', () => { | |||
getTask.mockImplementation(() => Promise.resolve({ errorStacktrace: 'stacktrace' })); | |||
it('fetches scanner context on mount', async () => { | |||
const wrapper = mount(<Stacktrace onClose={jest.fn()} task={task} />); | |||
expect(wrapper.state()).toEqual({ loading: true }); | |||
expect(getTask).toBeCalledWith('123', ['stacktrace']); | |||
return doAsync().then(() => { | |||
expect(wrapper.state()).toEqual({ loading: false, stacktrace: 'stacktrace' }); | |||
}); | |||
await new Promise(setImmediate); | |||
expect(wrapper.state()).toEqual({ loading: false, stacktrace: 'stacktrace' }); | |||
}); |
@@ -35,6 +35,7 @@ it('shows stack trace', () => { | |||
click(wrapper.find('.js-task-show-stacktrace')); | |||
expect(wrapper.find('Stacktrace')).toMatchSnapshot(); | |||
wrapper.find('Stacktrace').prop<Function>('onClose')(); | |||
wrapper.update(); | |||
expect(wrapper.find('Stacktrace').exists()).toBeFalsy(); | |||
}); | |||
@@ -43,6 +44,7 @@ it('shows scanner context', () => { | |||
click(wrapper.find('.js-task-show-scanner-context')); | |||
expect(wrapper.find('ScannerContext')).toMatchSnapshot(); | |||
wrapper.find('ScannerContext').prop<Function>('onClose')(); | |||
wrapper.update(); | |||
expect(wrapper.find('ScannerContext').exists()).toBeFalsy(); | |||
}); | |||
@@ -94,7 +94,9 @@ export default class App extends React.PureComponent<Props, State> { | |||
retrieveComponentChildren(component.key, isPortfolio, branch && getBranchName(branch)) | |||
.then(() => { | |||
addComponent(component); | |||
this.handleUpdate(); | |||
if (this.mounted) { | |||
this.handleUpdate(); | |||
} | |||
}) | |||
.catch(e => { | |||
if (this.mounted) { |
@@ -117,7 +117,11 @@ export default class App extends React.PureComponent { | |||
}); | |||
} | |||
}, | |||
() => this.setState({ loading: false }) | |||
() => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
} | |||
); | |||
}; | |||
@@ -42,7 +42,7 @@ const PROPS = { | |||
branch: { isMain: true, name: 'master' }, | |||
component: { key: 'foo' }, | |||
location: { pathname: '/component_measures', query: { metric: 'coverage' } }, | |||
fetchMeasures: () => {}, | |||
fetchMeasures: () => Promise.resolve({ measures: [] }), | |||
fetchMetrics: () => {}, | |||
metrics: METRICS, | |||
metricsKey: ['lines_to_cover', 'coverage', 'duplicated_lines_density', 'new_bugs'], |
@@ -14,6 +14,7 @@ exports[`should render 1`] = ` | |||
active={false} | |||
disabled={false} | |||
halfWidth={false} | |||
key="" | |||
name="unassigned" | |||
onClick={[Function]} | |||
stat="5" | |||
@@ -100,6 +101,7 @@ exports[`should select unassigned 1`] = ` | |||
active={true} | |||
disabled={false} | |||
halfWidth={false} | |||
key="" | |||
name="unassigned" | |||
onClick={[Function]} | |||
stat="5" | |||
@@ -162,6 +164,7 @@ exports[`should select user 1`] = ` | |||
active={false} | |||
disabled={false} | |||
halfWidth={false} | |||
key="" | |||
name="unassigned" | |||
onClick={[Function]} | |||
stat="5" |
@@ -62,6 +62,7 @@ it('should display an error message', () => { | |||
it('should open the license form', () => { | |||
const wrapper = getWrapper({ editions: DEFAULT_EDITIONS }); | |||
(wrapper.instance() as EditionBoxes).handleOpenLicenseForm(DEFAULT_EDITIONS[0]); | |||
wrapper.update(); | |||
expect(wrapper.find('LicenseEditionForm').exists()).toBeTruthy(); | |||
}); | |||
@@ -38,7 +38,7 @@ it('should display pending actions', () => { | |||
}); | |||
it('should not display anything', () => { | |||
expect(getWrapper({ pending: { installing: [], updating: [], removing: [] } })).toMatchSnapshot(); | |||
expect(getWrapper({ pending: { installing: [], updating: [], removing: [] } }).type()).toBeNull(); | |||
}); | |||
it('should open the restart form', () => { |
@@ -59,5 +59,3 @@ exports[`should display pending actions 1`] = ` | |||
</div> | |||
</div> | |||
`; | |||
exports[`should not display anything 1`] = `null`; |
@@ -43,11 +43,9 @@ export default class EditionBox extends React.PureComponent<Props> { | |||
if (canInstall && !isInstalled) { | |||
return ( | |||
<button disabled={installInProgress || uninstallInProgress} onClick={this.handleInstall}> | |||
{this.props.isDowngrade ? ( | |||
translate('marketplace.downgrade') | |||
) : ( | |||
translate('marketplace.upgrade') | |||
)} | |||
{this.props.isDowngrade | |||
? translate('marketplace.downgrade') | |||
: translate('marketplace.upgrade')} | |||
</button> | |||
); | |||
} |
@@ -31,7 +31,7 @@ const DEFAULT_STATUS: EditionStatus = { | |||
it('should display installed badge', () => { | |||
expect( | |||
getWrapper({ | |||
editionStatus: { | |||
status: { | |||
currentEditionKey: 'foo', | |||
nextEditionKey: '', | |||
installationStatus: 'NONE' | |||
@@ -43,7 +43,7 @@ it('should display installed badge', () => { | |||
it('should display installing badge', () => { | |||
expect( | |||
getWrapper({ | |||
editionStatus: { | |||
status: { | |||
currentEditionKey: 'foo', | |||
nextEditionKey: 'foo', | |||
installationStatus: 'AUTOMATIC_IN_PROGRESS' | |||
@@ -55,7 +55,7 @@ it('should display installing badge', () => { | |||
it('should display pending badge', () => { | |||
expect( | |||
getWrapper({ | |||
editionStatus: { | |||
status: { | |||
currentEditionKey: '', | |||
nextEditionKey: 'foo', | |||
installationStatus: 'AUTOMATIC_READY' | |||
@@ -67,13 +67,13 @@ it('should display pending badge', () => { | |||
it('should not display a badge', () => { | |||
expect( | |||
getWrapper({ | |||
editionStatus: { | |||
status: { | |||
currentEditionKey: '', | |||
nextEditionKey: 'bar', | |||
installationStatus: 'AUTOMATIC_READY' | |||
} | |||
}) | |||
).toMatchSnapshot(); | |||
}).type() | |||
).toBeNull(); | |||
}); | |||
function getWrapper(props = {}) { |
@@ -63,8 +63,8 @@ it('should update the edition status after install', async () => { | |||
const updateEditionStatus = jest.fn(); | |||
const wrapper = getWrapper({ updateEditionStatus }); | |||
const form = wrapper.instance() as LicenseEditionForm; | |||
form.mounted = true; | |||
form.handleLicenseChange('mylicense', 'AUTOMATIC_INSTALL'); | |||
wrapper.update(); | |||
click(wrapper.find('button')); | |||
expect(applyLicense).toHaveBeenCalledWith({ license: 'mylicense' }); | |||
await new Promise(setImmediate); |
@@ -26,7 +26,8 @@ import LicenseEditionSet from '../LicenseEditionSet'; | |||
jest.mock('../../../../api/marketplace', () => ({ | |||
getLicensePreview: jest.fn(() => | |||
Promise.resolve({ nextEditionKey: 'foo', previewStatus: 'NO_INSTALL' }) | |||
) | |||
), | |||
getFormData: jest.fn(() => Promise.resolve({ serverId: 'foo', ncloc: 1000 })) | |||
})); | |||
jest.mock('lodash', () => { | |||
@@ -56,6 +57,13 @@ it('should display correctly', () => { | |||
expect(getWrapper()).toMatchSnapshot(); | |||
}); | |||
it('should display the get license link with parameters', async () => { | |||
const wrapper = getWrapper(); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper.find('a')).toMatchSnapshot(); | |||
}); | |||
it('should correctly display status message after checking license', async () => { | |||
await testLicenseStatus('NO_INSTALL'); | |||
await testLicenseStatus('AUTOMATIC_INSTALL'); | |||
@@ -79,10 +87,10 @@ async function testLicenseStatus(status: string) { | |||
); | |||
const updateLicense = jest.fn(); | |||
const wrapper = getWrapper({ updateLicense }); | |||
(wrapper.instance() as LicenseEditionSet).mounted = true; | |||
change(wrapper.find('textarea'), 'mylicense'); | |||
expect(getLicensePreview).toHaveBeenCalled(); | |||
await new Promise(setImmediate); | |||
expect(updateLicense).toHaveBeenCalled(); | |||
wrapper.update(); | |||
expect(wrapper.find('p.alert')).toMatchSnapshot(); | |||
} |
@@ -26,5 +26,5 @@ it('should display the license field', () => { | |||
}); | |||
it('should not display anything', () => { | |||
expect(shallow(<PluginLicense />)).toMatchSnapshot(); | |||
expect(shallow(<PluginLicense />).type()).toBeNull(); | |||
}); |
@@ -30,7 +30,7 @@ it('should display only one url', () => { | |||
}); | |||
it('should not display anything', () => { | |||
expect(getWrapper({ homepageUrl: undefined, issueTrackerUrl: undefined })).toMatchSnapshot(); | |||
expect(getWrapper({ homepageUrl: undefined, issueTrackerUrl: undefined }).type()).toBeNull(); | |||
}); | |||
function getWrapper(plugin = {}) { |
@@ -1,9 +1,29 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should display installed badge 1`] = `null`; | |||
exports[`should display installed badge 1`] = ` | |||
<span | |||
className="marketplace-edition-badge badge badge-normal-size" | |||
> | |||
<CheckIcon | |||
className="little-spacer-right text-bottom" | |||
size={14} | |||
/> | |||
marketplace.installed | |||
</span> | |||
`; | |||
exports[`should display installing badge 1`] = `null`; | |||
exports[`should display installing badge 1`] = ` | |||
<span | |||
className="marketplace-edition-badge badge badge-normal-size" | |||
> | |||
marketplace.installing | |||
</span> | |||
`; | |||
exports[`should display pending badge 1`] = `null`; | |||
exports[`should not display a badge 1`] = `null`; | |||
exports[`should display pending badge 1`] = ` | |||
<span | |||
className="marketplace-edition-badge badge badge-normal-size" | |||
> | |||
marketplace.pending | |||
</span> | |||
`; |
@@ -75,3 +75,13 @@ exports[`should display correctly 1`] = ` | |||
</a> | |||
</div> | |||
`; | |||
exports[`should display the get license link with parameters 1`] = ` | |||
<a | |||
className="display-inline-block spacer-top" | |||
href="license_url?serverId=foo&ncloc=1000" | |||
target="_blank" | |||
> | |||
marketplace.i_need_a_license | |||
</a> | |||
`; |
@@ -24,5 +24,3 @@ exports[`should display the license field 1`] = ` | |||
</li> | |||
</Tooltip> | |||
`; | |||
exports[`should not display anything 1`] = `null`; |
@@ -48,5 +48,3 @@ exports[`should display the urls 1`] = ` | |||
</ul> | |||
</li> | |||
`; | |||
exports[`should not display anything 1`] = `null`; |
@@ -23,12 +23,12 @@ import { connect } from 'react-redux'; | |||
import { getOrganizationByKey } from '../../../store/rootReducer'; | |||
import handleRequiredAuthorization from '../../../app/utils/handleRequiredAuthorization'; | |||
class OrganizationAdmin extends React.PureComponent { | |||
export class OrganizationAdmin extends React.PureComponent { | |||
/*:: props: { | |||
children?: React.Element<*>, | |||
organization: { canAdmin: boolean } | |||
}; | |||
*/ | |||
*/ | |||
componentDidMount() { | |||
this.checkPermissions(); | |||
@@ -62,5 +62,3 @@ const mapStateToProps = (state, ownProps) => ({ | |||
}); | |||
export default connect(mapStateToProps)(OrganizationAdmin); | |||
export const UnconnectedOrganizationAdmin = OrganizationAdmin; |
@@ -49,7 +49,7 @@ type State = { | |||
}; | |||
*/ | |||
class OrganizationPage extends React.PureComponent { | |||
export class OrganizationPage extends React.PureComponent { | |||
/*:: mounted: boolean; */ | |||
/*:: props: Props; */ | |||
state /*: State */ = { loading: true }; | |||
@@ -108,5 +108,3 @@ const mapStateToProps = (state, ownProps /*: OwnProps */) => ({ | |||
const mapDispatchToProps = { fetchOrganization }; | |||
export default connect(mapStateToProps, mapDispatchToProps)(OrganizationPage); | |||
export const UnconnectedOrganizationPage = OrganizationPage; |
@@ -19,15 +19,17 @@ | |||
*/ | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import { UnconnectedOrganizationAdmin } from '../OrganizationAdmin'; | |||
import { OrganizationAdmin } from '../OrganizationAdmin'; | |||
jest.mock('../../../../app/utils/handleRequiredAuthorization', () => jest.fn()); | |||
it('should render children', () => { | |||
const organization = { canAdmin: true }; | |||
expect( | |||
shallow( | |||
<UnconnectedOrganizationAdmin organization={organization}> | |||
<OrganizationAdmin organization={organization}> | |||
<div>hello</div> | |||
</UnconnectedOrganizationAdmin> | |||
</OrganizationAdmin> | |||
) | |||
).toMatchSnapshot(); | |||
}); | |||
@@ -36,9 +38,9 @@ it('should not render anything', () => { | |||
const organization = { canAdmin: false }; | |||
expect( | |||
shallow( | |||
<UnconnectedOrganizationAdmin organization={organization}> | |||
<OrganizationAdmin organization={organization}> | |||
<div>hello</div> | |||
</UnconnectedOrganizationAdmin> | |||
) | |||
).toMatchSnapshot(); | |||
</OrganizationAdmin> | |||
).type() | |||
).toBeNull(); | |||
}); |
@@ -35,6 +35,7 @@ it('should not render actions for non admin', () => { | |||
members={members} | |||
status={status} | |||
fetchOrganizationMembers={jest.fn()} | |||
fetchOrganizationGroups={jest.fn()} | |||
fetchMoreOrganizationMembers={jest.fn()} | |||
/> | |||
); | |||
@@ -48,6 +49,7 @@ it('should render actions for admin', () => { | |||
members={members} | |||
status={{ ...status, loading: true }} | |||
fetchOrganizationMembers={jest.fn()} | |||
fetchOrganizationGroups={jest.fn()} | |||
fetchMoreOrganizationMembers={jest.fn()} | |||
/> | |||
); |
@@ -19,15 +19,17 @@ | |||
*/ | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import { UnconnectedOrganizationPage } from '../OrganizationPage'; | |||
import { OrganizationPage } from '../OrganizationPage'; | |||
const fetchOrganization = () => Promise.resolve(); | |||
it('smoke test', () => { | |||
const wrapper = shallow( | |||
<UnconnectedOrganizationPage params={{ organizationKey: 'foo' }}> | |||
<OrganizationPage fetchOrganization={fetchOrganization} params={{ organizationKey: 'foo' }}> | |||
<div>hello</div> | |||
</UnconnectedOrganizationPage> | |||
</OrganizationPage> | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(wrapper.type()).toBeNull(); | |||
const organization = { key: 'foo', name: 'Foo', isDefault: false, canAdmin: false }; | |||
wrapper.setProps({ organization }); | |||
@@ -36,9 +38,9 @@ it('smoke test', () => { | |||
it('not found', () => { | |||
const wrapper = shallow( | |||
<UnconnectedOrganizationPage params={{ organizationKey: 'foo' }}> | |||
<OrganizationPage fetchOrganization={fetchOrganization} params={{ organizationKey: 'foo' }}> | |||
<div>hello</div> | |||
</UnconnectedOrganizationPage> | |||
</OrganizationPage> | |||
); | |||
wrapper.setState({ loading: false }); | |||
expect(wrapper).toMatchSnapshot(); | |||
@@ -47,12 +49,11 @@ it('not found', () => { | |||
it('should correctly update when the organization changes', () => { | |||
const fetchOrganization = jest.fn(() => Promise.resolve()); | |||
const wrapper = shallow( | |||
<UnconnectedOrganizationPage | |||
params={{ organizationKey: 'foo' }} | |||
fetchOrganization={fetchOrganization}> | |||
<OrganizationPage params={{ organizationKey: 'foo' }} fetchOrganization={fetchOrganization}> | |||
<div>hello</div> | |||
</UnconnectedOrganizationPage> | |||
</OrganizationPage> | |||
); | |||
wrapper.setProps({ params: { organizationKey: 'bar' } }); | |||
expect(fetchOrganization).toHaveBeenCalledTimes(2); | |||
expect(fetchOrganization.mock.calls).toMatchSnapshot(); | |||
}); |
@@ -1,7 +1,5 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should not render anything 1`] = `null`; | |||
exports[`should render children 1`] = ` | |||
<div> | |||
hello |
@@ -4,15 +4,16 @@ exports[`not found 1`] = `<NotFound />`; | |||
exports[`should correctly update when the organization changes 1`] = ` | |||
Array [ | |||
Array [ | |||
"foo", | |||
], | |||
Array [ | |||
"bar", | |||
], | |||
] | |||
`; | |||
exports[`smoke test 1`] = `null`; | |||
exports[`smoke test 2`] = ` | |||
exports[`smoke test 1`] = ` | |||
<div> | |||
<HelmetWrapper | |||
defaultTitle="Foo" |
@@ -77,10 +77,11 @@ export default class AddMemberForm extends React.PureComponent { | |||
}; | |||
renderModal() { | |||
const header = translate('users.add'); | |||
return ( | |||
<Modal contentLabel="modal form" onRequestClose={this.closeForm}> | |||
<Modal key="add-member-modal" contentLabel={header} onRequestClose={this.closeForm}> | |||
<header className="modal-head"> | |||
<h2>{translate('users.add')}</h2> | |||
<h2>{header}</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> | |||
<div className="modal-body"> | |||
@@ -111,11 +112,14 @@ export default class AddMemberForm extends React.PureComponent { | |||
} | |||
render() { | |||
return ( | |||
<button onClick={this.openForm}> | |||
const buttonComponent = ( | |||
<button key="add-member-button" onClick={this.openForm}> | |||
{translate('organization.members.add')} | |||
{this.state.open && this.renderModal()} | |||
</button> | |||
); | |||
if (this.state.open) { | |||
return [buttonComponent, this.renderModal()]; | |||
} | |||
return buttonComponent; | |||
} | |||
} |
@@ -105,10 +105,11 @@ export default class ManageMemberGroupsForm extends React.PureComponent { | |||
}; | |||
renderModal() { | |||
const header = translate('organization.members.manage_groups'); | |||
return ( | |||
<Modal contentLabel="modal form" onRequestClose={this.closeForm}> | |||
<Modal key="manage-member-modal" contentLabel={header} onRequestClose={this.closeForm}> | |||
<header className="modal-head"> | |||
<h2>{translate('organization.members.manage_groups')}</h2> | |||
<h2>{header}</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> | |||
<div className="modal-body"> | |||
@@ -146,11 +147,14 @@ export default class ManageMemberGroupsForm extends React.PureComponent { | |||
} | |||
render() { | |||
return ( | |||
<a onClick={this.openForm} href="#"> | |||
const buttonComponent = ( | |||
<a key="manage-member-button" onClick={this.openForm} href="#"> | |||
{translate('organization.members.manage_groups')} | |||
{this.state.open && this.renderModal()} | |||
</a> | |||
); | |||
if (this.state.open) { | |||
return [buttonComponent, this.renderModal()]; | |||
} | |||
return buttonComponent; | |||
} | |||
} |
@@ -61,10 +61,11 @@ export default class RemoveMemberForm extends React.PureComponent { | |||
}; | |||
renderModal() { | |||
const header = translate('users.remove'); | |||
return ( | |||
<Modal contentLabel="modal form" onRequestClose={this.closeForm}> | |||
<Modal key="remove-member-modal" contentLabel={header} onRequestClose={this.closeForm}> | |||
<header className="modal-head"> | |||
<h2>{translate('users.remove')}</h2> | |||
<h2>{header}</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> | |||
<div className="modal-body markdown"> | |||
@@ -92,11 +93,14 @@ export default class RemoveMemberForm extends React.PureComponent { | |||
} | |||
render() { | |||
return ( | |||
<a onClick={this.openForm} href="#"> | |||
const buttonComponent = ( | |||
<a key="remove-member-button" onClick={this.openForm} href="#"> | |||
{translate('organization.members.remove')} | |||
{this.state.open && this.renderModal()} | |||
</a> | |||
); | |||
if (this.state.open) { | |||
return [buttonComponent, this.renderModal()]; | |||
} | |||
return buttonComponent; | |||
} | |||
} |
@@ -18,21 +18,25 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import React from 'react'; | |||
import { shallow, mount } from 'enzyme'; | |||
import { shallow } from 'enzyme'; | |||
import { click } from '../../../../../helpers/testUtils'; | |||
import AddMemberForm from '../AddMemberForm'; | |||
jest.mock('react-dom'); | |||
const memberLogins = ['admin']; | |||
it('should render and open the modal', () => { | |||
const wrapper = shallow(<AddMemberForm memberLogins={memberLogins} addMember={jest.fn()} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.setState({ open: true }); | |||
expect(wrapper).toMatchSnapshot(); | |||
// FIXME Can probably be removed when https://github.com/airbnb/enzyme/issues/1149 is resolved | |||
expect(wrapper.first().getElements()).toMatchSnapshot(); | |||
}); | |||
it('should correctly handle user interactions', () => { | |||
const wrapper = mount(<AddMemberForm memberLogins={memberLogins} addMember={jest.fn()} />); | |||
const wrapper = shallow(<AddMemberForm memberLogins={memberLogins} addMember={jest.fn()} />); | |||
click(wrapper.find('button')); | |||
expect(wrapper.state('open')).toBeTruthy(); | |||
wrapper.instance().closeForm(); |
@@ -18,10 +18,12 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import React from 'react'; | |||
import { shallow, mount } from 'enzyme'; | |||
import { shallow } from 'enzyme'; | |||
import { click, mockEvent } from '../../../../../helpers/testUtils'; | |||
import ManageMemberGroupsForm from '../ManageMemberGroupsForm'; | |||
jest.mock('react-dom'); | |||
const member = { login: 'admin', name: 'Admin Istrator', avatar: '', groupCount: 3 }; | |||
const organization = { name: 'MyOrg', key: 'myorg' }; | |||
const organizationGroups = [ | |||
@@ -48,8 +50,8 @@ const userGroups = { | |||
11: { id: 11, name: 'pull-request-analysers', description: 'Technical accounts', selected: true } | |||
}; | |||
const getMountedForm = function(updateFunc = jest.fn()) { | |||
const wrapper = mount( | |||
function getMountedForm(updateFunc = jest.fn()) { | |||
const wrapper = shallow( | |||
<ManageMemberGroupsForm | |||
member={member} | |||
organization={organization} | |||
@@ -62,7 +64,7 @@ const getMountedForm = function(updateFunc = jest.fn()) { | |||
instance.setState({ loading: false, userGroups }); | |||
}); | |||
return { wrapper, instance }; | |||
}; | |||
} | |||
it('should render and open the modal', () => { | |||
const wrapper = shallow( | |||
@@ -75,7 +77,7 @@ it('should render and open the modal', () => { | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.setState({ open: true }); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(wrapper.first().getElements()).toMatchSnapshot(); | |||
}); | |||
it('should correctly handle user interactions', () => { |
@@ -18,10 +18,12 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import React from 'react'; | |||
import { shallow, mount } from 'enzyme'; | |||
import { shallow } from 'enzyme'; | |||
import { click, mockEvent } from '../../../../../helpers/testUtils'; | |||
import RemoveMemberForm from '../RemoveMemberForm'; | |||
jest.mock('react-dom'); | |||
const member = { login: 'admin', name: 'Admin Istrator', avatar: '', groupCount: 3 }; | |||
const organization = { name: 'MyOrg' }; | |||
@@ -31,12 +33,12 @@ it('should render and open the modal', () => { | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.setState({ open: true }); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(wrapper.first().getElements()).toMatchSnapshot(); | |||
}); | |||
it('should correctly handle user interactions', () => { | |||
const removeMember = jest.fn(); | |||
const wrapper = mount( | |||
const wrapper = shallow( | |||
<RemoveMemberForm member={member} removeMember={removeMember} organization={organization} /> | |||
); | |||
const instance = wrapper.instance(); |
@@ -2,6 +2,7 @@ | |||
exports[`should render and open the modal 1`] = ` | |||
<button | |||
key="add-member-button" | |||
onClick={[Function]} | |||
> | |||
organization.members.add | |||
@@ -9,12 +10,14 @@ exports[`should render and open the modal 1`] = ` | |||
`; | |||
exports[`should render and open the modal 2`] = ` | |||
<button | |||
onClick={[Function]} | |||
> | |||
organization.members.add | |||
Array [ | |||
<button | |||
onClick={[Function]} | |||
> | |||
organization.members.add | |||
</button>, | |||
<Modal | |||
contentLabel="modal form" | |||
contentLabel="users.add" | |||
onRequestClose={[Function]} | |||
> | |||
<header | |||
@@ -45,6 +48,7 @@ exports[`should render and open the modal 2`] = ` | |||
} | |||
handleValueChange={[Function]} | |||
searchUsers={[Function]} | |||
selectedUser={undefined} | |||
/> | |||
</div> | |||
</div> | |||
@@ -68,6 +72,6 @@ exports[`should render and open the modal 2`] = ` | |||
</div> | |||
</footer> | |||
</form> | |||
</Modal> | |||
</button> | |||
</Modal>, | |||
] | |||
`; |
@@ -71,6 +71,7 @@ Object { | |||
exports[`should render and open the modal 1`] = ` | |||
<a | |||
href="#" | |||
key="manage-member-button" | |||
onClick={[Function]} | |||
> | |||
organization.members.manage_groups | |||
@@ -78,13 +79,15 @@ exports[`should render and open the modal 1`] = ` | |||
`; | |||
exports[`should render and open the modal 2`] = ` | |||
<a | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
organization.members.manage_groups | |||
Array [ | |||
<a | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
organization.members.manage_groups | |||
</a>, | |||
<Modal | |||
contentLabel="modal form" | |||
contentLabel="organization.members.manage_groups" | |||
onRequestClose={[Function]} | |||
> | |||
<header | |||
@@ -117,7 +120,6 @@ exports[`should render and open the modal 2`] = ` | |||
"name": "professionals", | |||
} | |||
} | |||
key="7" | |||
onCheck={[Function]} | |||
/> | |||
<OrganizationGroupCheckbox | |||
@@ -130,7 +132,6 @@ exports[`should render and open the modal 2`] = ` | |||
"name": "pull-request-analysers", | |||
} | |||
} | |||
key="11" | |||
onCheck={[Function]} | |||
/> | |||
<OrganizationGroupCheckbox | |||
@@ -143,7 +144,6 @@ exports[`should render and open the modal 2`] = ` | |||
"name": "sonar-administrators", | |||
} | |||
} | |||
key="1" | |||
onCheck={[Function]} | |||
/> | |||
</ul> | |||
@@ -167,8 +167,8 @@ exports[`should render and open the modal 2`] = ` | |||
</div> | |||
</footer> | |||
</form> | |||
</Modal> | |||
</a> | |||
</Modal>, | |||
] | |||
`; | |||
exports[`should reset the selected groups when the modal is opened 1`] = ` |
@@ -16,6 +16,7 @@ Array [ | |||
exports[`should render and open the modal 1`] = ` | |||
<a | |||
href="#" | |||
key="remove-member-button" | |||
onClick={[Function]} | |||
> | |||
organization.members.remove | |||
@@ -23,13 +24,15 @@ exports[`should render and open the modal 1`] = ` | |||
`; | |||
exports[`should render and open the modal 2`] = ` | |||
<a | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
organization.members.remove | |||
Array [ | |||
<a | |||
href="#" | |||
onClick={[Function]} | |||
> | |||
organization.members.remove | |||
</a>, | |||
<Modal | |||
contentLabel="modal form" | |||
contentLabel="users.remove" | |||
onRequestClose={[Function]} | |||
> | |||
<header | |||
@@ -70,6 +73,6 @@ exports[`should render and open the modal 2`] = ` | |||
</div> | |||
</footer> | |||
</form> | |||
</Modal> | |||
</a> | |||
</Modal>, | |||
] | |||
`; |
@@ -17,13 +17,13 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import OrganizationPage from './components/OrganizationPage'; | |||
import OrganizationPageContainer from './components/OrganizationPage'; | |||
import OrganizationPageExtension from '../../app/components/extensions/OrganizationPageExtension'; | |||
import OrganizationContainer from './components/OrganizationContainer'; | |||
import OrganizationProjects from './components/OrganizationProjects'; | |||
import OrganizationFavoriteProjects from './components/OrganizationFavoriteProjects'; | |||
import OrganizationRules from './components/OrganizationRules'; | |||
import OrganizationAdmin from './components/OrganizationAdmin'; | |||
import OrganizationAdminContainer from './components/OrganizationAdmin'; | |||
import OrganizationEdit from './components/OrganizationEdit'; | |||
import OrganizationGroups from './components/OrganizationGroups'; | |||
import OrganizationMembersContainer from './components/OrganizationMembersContainer'; | |||
@@ -38,7 +38,7 @@ import issuesRoutes from '../issues/routes'; | |||
const routes = [ | |||
{ | |||
path: ':organizationKey', | |||
component: OrganizationPage, | |||
component: OrganizationPageContainer, | |||
childRoutes: [ | |||
{ | |||
indexRoute: { | |||
@@ -90,7 +90,7 @@ const routes = [ | |||
component: OrganizationPageExtension | |||
}, | |||
{ | |||
component: OrganizationAdmin, | |||
component: OrganizationAdminContainer, | |||
childRoutes: [ | |||
{ path: 'delete', component: OrganizationDelete }, | |||
{ path: 'edit', component: OrganizationEdit }, |
@@ -25,18 +25,14 @@ exports[`renders 2`] = ` | |||
<ul | |||
className="text-left" | |||
> | |||
<li | |||
key="foo" | |||
> | |||
<li> | |||
Foo | |||
: | |||
<DateTooltipFormatter | |||
date="2017-01-01T11:39:03+0100" | |||
/> | |||
</li> | |||
<li | |||
key="bar" | |||
> | |||
<li> | |||
Bar | |||
: | |||
<DateTooltipFormatter |
@@ -74,7 +74,7 @@ export default class MetaLink extends React.PureComponent { | |||
className="link-with-icon" | |||
href={link.url} | |||
target="_blank" | |||
onClick={!isClickable(link) && this.handleClick}> | |||
onClick={!isClickable(link) ? this.handleClick : undefined}> | |||
{this.renderLinkIcon(link)} | |||
| |||
{link.name} |
@@ -39,15 +39,21 @@ const componentWithTags = { | |||
}; | |||
it('should render without tags and admin rights', () => { | |||
expect(shallow(<MetaTags component={component} />)).toMatchSnapshot(); | |||
expect( | |||
shallow(<MetaTags component={component} />, { disableLifecycleMethods: true }) | |||
).toMatchSnapshot(); | |||
}); | |||
it('should render with tags and admin rights', () => { | |||
expect(shallow(<MetaTags component={componentWithTags} />)).toMatchSnapshot(); | |||
expect( | |||
shallow(<MetaTags component={componentWithTags} />, { disableLifecycleMethods: true }) | |||
).toMatchSnapshot(); | |||
}); | |||
it('should open the tag selector on click', () => { | |||
const wrapper = shallow(<MetaTags component={componentWithTags} />); | |||
const wrapper = shallow(<MetaTags component={componentWithTags} />, { | |||
disableLifecycleMethods: true | |||
}); | |||
expect(wrapper).toMatchSnapshot(); | |||
// open |
@@ -67,7 +67,6 @@ exports[`should match snapshot 1`] = ` | |||
<a | |||
className="link-with-icon" | |||
href="http://example.com" | |||
onClick={false} | |||
target="_blank" | |||
> | |||
<i |
@@ -48,6 +48,6 @@ it('should render correctly', () => { | |||
it('should render null when data is missing', () => { | |||
expect( | |||
shallow(<GraphsTooltipsContentDuplication {...DEFAULT_PROPS} tooltipIdx={0} />) | |||
).toMatchSnapshot(); | |||
shallow(<GraphsTooltipsContentDuplication {...DEFAULT_PROPS} tooltipIdx={0} />).type() | |||
).toBeNull(); | |||
}); |
@@ -25,5 +25,3 @@ exports[`should render correctly 1`] = ` | |||
</tr> | |||
</tbody> | |||
`; | |||
exports[`should render null when data is missing 1`] = `null`; |
@@ -97,10 +97,11 @@ export default class AddEventForm extends React.PureComponent { | |||
}; | |||
renderModal() { | |||
const header = translate(this.props.addEventButtonText); | |||
return ( | |||
<Modal contentLabel="modal form" onRequestClose={this.closeForm}> | |||
<Modal key="add-event-modal" contentLabel={header} onRequestClose={this.closeForm}> | |||
<header className="modal-head"> | |||
<h2>{translate(this.props.addEventButtonText)}</h2> | |||
<h2>{header}</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> | |||
@@ -111,7 +112,6 @@ export default class AddEventForm extends React.PureComponent { | |||
value={this.state.name} | |||
autoFocus={true} | |||
disabled={this.state.processing} | |||
className="input-medium" | |||
type="text" | |||
onChange={this.changeInput} | |||
/> | |||
@@ -136,11 +136,14 @@ export default class AddEventForm extends React.PureComponent { | |||
} | |||
render() { | |||
return ( | |||
<a className="js-add-event" href="#" onClick={this.openForm}> | |||
const linkComponent = ( | |||
<a key="add-event-link" className="js-add-event" href="#" onClick={this.openForm}> | |||
{translate(this.props.addEventButtonText)} | |||
{this.state.open && this.renderModal()} | |||
</a> | |||
); | |||
if (this.state.open) { | |||
return [linkComponent, this.renderModal()]; | |||
} | |||
return linkComponent; | |||
} | |||
} |
@@ -102,10 +102,11 @@ export default class AddGraphMetric extends React.PureComponent { | |||
renderModal() { | |||
const { metricsTypeFilter } = this.props; | |||
const header = translate('project_activity.graphs.custom.add_metric'); | |||
return ( | |||
<Modal contentLabel="graph metric add" onRequestClose={this.closeForm}> | |||
<Modal key="add-metric-modal" contentLabel={header} onRequestClose={this.closeForm}> | |||
<header className="modal-head"> | |||
<h2>{translate('project_activity.graphs.custom.add_metric')}</h2> | |||
<h2>{header}</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> | |||
<div className="modal-body"> | |||
@@ -165,11 +166,16 @@ export default class AddGraphMetric extends React.PureComponent { | |||
); | |||
} | |||
return ( | |||
<button className={this.props.className} onClick={this.openForm}> | |||
const buttonComponent = ( | |||
<button key="add-metric-button" className={this.props.className} onClick={this.openForm}> | |||
{translate('project_activity.graphs.custom.add')} | |||
{this.state.open && this.renderModal()} | |||
</button> | |||
); | |||
if (this.state.open) { | |||
return [buttonComponent, this.renderModal()]; | |||
} | |||
return buttonComponent; | |||
} | |||
} |
@@ -95,10 +95,11 @@ export default class ChangeEventForm extends React.PureComponent { | |||
}; | |||
render() { | |||
const header = translate(this.props.changeEventButtonText); | |||
return ( | |||
<Modal contentLabel="modal form" onRequestClose={this.closeForm}> | |||
<Modal contentLabel={header} onRequestClose={this.closeForm}> | |||
<header className="modal-head"> | |||
<h2>{translate(this.props.changeEventButtonText)}</h2> | |||
<h2>{header}</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> | |||
@@ -109,7 +110,6 @@ export default class ChangeEventForm extends React.PureComponent { | |||
value={this.state.name} | |||
autoFocus={true} | |||
disabled={this.state.processing} | |||
className="input-medium" | |||
type="text" | |||
onChange={this.changeInput} | |||
/> |
@@ -88,10 +88,11 @@ export default class RemoveAnalysisForm extends React.PureComponent { | |||
}; | |||
renderModal() { | |||
const header = translate('project_activity.delete_analysis'); | |||
return ( | |||
<Modal contentLabel="modal form" onRequestClose={this.closeForm}> | |||
<Modal key="delete-analysis-modal" contentLabel={header} onRequestClose={this.closeForm}> | |||
<header className="modal-head"> | |||
<h2>{translate('project_activity.delete_analysis')}</h2> | |||
<h2>{header}</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> | |||
@@ -117,11 +118,14 @@ export default class RemoveAnalysisForm extends React.PureComponent { | |||
} | |||
render() { | |||
return ( | |||
<a className="js-delete-analysis" href="#" onClick={this.openForm}> | |||
const linkComponent = ( | |||
<a key="delete-analysis-link" className="js-delete-analysis" href="#" onClick={this.openForm}> | |||
{translate('project_activity.delete_analysis')} | |||
{this.state.open && this.renderModal()} | |||
</a> | |||
); | |||
if (this.state.open) { | |||
return [linkComponent, this.renderModal()]; | |||
} | |||
return linkComponent; | |||
} | |||
} |
@@ -81,10 +81,11 @@ export default class RemoveEventForm extends React.PureComponent { | |||
}; | |||
render() { | |||
const header = translate(this.props.removeEventButtonText); | |||
return ( | |||
<Modal contentLabel="modal form" onRequestClose={this.closeForm}> | |||
<Modal contentLabel={header} onRequestClose={this.closeForm}> | |||
<header className="modal-head"> | |||
<h2>{translate(this.props.removeEventButtonText)}</h2> | |||
<h2>{header}</h2> | |||
</header> | |||
<form onSubmit={this.handleSubmit}> |
@@ -17,16 +17,16 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first, import/order */ | |||
jest.mock('../../../../api/settings', () => ({ | |||
getValues: jest.fn(() => Promise.resolve([])) | |||
})); | |||
/* eslint-disable import/order */ | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import { shallow } from 'enzyme'; | |||
import LongBranchesPattern from '../LongBranchesPattern'; | |||
import { click } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/settings', () => ({ | |||
getValues: jest.fn(() => Promise.resolve([])) | |||
})); | |||
const getValues = require('../../../../api/settings').getValues as jest.Mock<any>; | |||
beforeEach(() => { | |||
@@ -41,25 +41,25 @@ it('renders', () => { | |||
it('opens form', () => { | |||
const wrapper = shallow(<LongBranchesPattern project="project" />); | |||
(wrapper.instance() as LongBranchesPattern).mounted = true; | |||
wrapper.setState({ loading: false, setting: { value: 'release-.*' } }); | |||
click(wrapper.find('a')); | |||
expect(wrapper.find('LongBranchesPatternForm').exists()).toBeTruthy(); | |||
wrapper.find('LongBranchesPatternForm').prop<Function>('onClose')(); | |||
wrapper.update(); | |||
expect(wrapper.find('LongBranchesPatternForm').exists()).toBeFalsy(); | |||
}); | |||
it('fetches setting value on mount', () => { | |||
mount(<LongBranchesPattern project="project" />); | |||
shallow(<LongBranchesPattern project="project" />); | |||
expect(getValues).lastCalledWith('sonar.branch.longLivedBranches.regex', 'project'); | |||
}); | |||
it('fetches new setting value after change', () => { | |||
const wrapper = mount(<LongBranchesPattern project="project" />); | |||
expect(getValues.mock.calls).toHaveLength(1); | |||
const wrapper = shallow(<LongBranchesPattern project="project" />); | |||
expect(getValues).toHaveBeenCalledTimes(1); | |||
(wrapper.instance() as LongBranchesPattern).handleChange(); | |||
expect(getValues.mock.calls).toHaveLength(2); | |||
expect(getValues).toHaveBeenCalledTimes(2); | |||
}); |
@@ -17,7 +17,12 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first, import/order */ | |||
/* eslint-disable import/order */ | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import AllProjects from '../AllProjects'; | |||
import { getView, saveSort, saveView, saveVisualization } from '../../../../helpers/storage'; | |||
jest.mock('../ProjectsList', () => ({ | |||
// eslint-disable-next-line | |||
default: function ProjectsList() { | |||
@@ -54,11 +59,6 @@ jest.mock('../../../../helpers/storage', () => ({ | |||
saveVisualization: jest.fn() | |||
})); | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import AllProjects from '../AllProjects'; | |||
import { getView, saveSort, saveView, saveVisualization } from '../../../../helpers/storage'; | |||
const fetchProjects = require('../../utils').fetchProjects as jest.Mock<any>; | |||
beforeEach(() => { |
@@ -69,6 +69,8 @@ it('does not save last selection with organization', () => { | |||
it('does not render for anonymous', () => { | |||
expect( | |||
shallow(<FavoriteFilter query={query} />, { context: { currentUser: { isLoggedIn: false } } }) | |||
).toMatchSnapshot(); | |||
shallow(<FavoriteFilter query={query} />, { | |||
context: { currentUser: { isLoggedIn: false } } | |||
}).type() | |||
).toBeNull(); | |||
}); |
@@ -49,5 +49,5 @@ it('handles unknown languages', () => { | |||
}); | |||
it('does not render', () => { | |||
expect(shallow(<ProjectCardLanguages />, { context: { languages } })).toMatchSnapshot(); | |||
expect(shallow(<ProjectCardLanguages />, { context: { languages } }).type()).toBeNull(); | |||
}); |
@@ -26,5 +26,5 @@ it('renders', () => { | |||
}); | |||
it('does not render', () => { | |||
expect(shallow(<ProjectCardQualityGate />)).toMatchSnapshot(); | |||
expect(shallow(<ProjectCardQualityGate />).type()).toBeNull(); | |||
}); |
@@ -28,7 +28,29 @@ exports[`renders 1`] = ` | |||
> | |||
<PageSidebar | |||
isFavorite={false} | |||
query={Object {}} | |||
query={ | |||
Object { | |||
"coverage": undefined, | |||
"duplications": undefined, | |||
"gate": undefined, | |||
"languages": undefined, | |||
"maintainability": undefined, | |||
"new_coverage": undefined, | |||
"new_duplications": undefined, | |||
"new_lines": undefined, | |||
"new_maintainability": undefined, | |||
"new_reliability": undefined, | |||
"new_security": undefined, | |||
"reliability": undefined, | |||
"search": undefined, | |||
"security": undefined, | |||
"size": undefined, | |||
"sort": undefined, | |||
"tags": undefined, | |||
"view": undefined, | |||
"visualization": undefined, | |||
} | |||
} | |||
view="overall" | |||
visualization="risk" | |||
/> | |||
@@ -67,7 +89,29 @@ exports[`renders 1`] = ` | |||
}, | |||
] | |||
} | |||
query={Object {}} | |||
query={ | |||
Object { | |||
"coverage": undefined, | |||
"duplications": undefined, | |||
"gate": undefined, | |||
"languages": undefined, | |||
"maintainability": undefined, | |||
"new_coverage": undefined, | |||
"new_duplications": undefined, | |||
"new_lines": undefined, | |||
"new_maintainability": undefined, | |||
"new_reliability": undefined, | |||
"new_security": undefined, | |||
"reliability": undefined, | |||
"search": undefined, | |||
"security": undefined, | |||
"size": undefined, | |||
"sort": undefined, | |||
"tags": undefined, | |||
"view": undefined, | |||
"visualization": undefined, | |||
} | |||
} | |||
selectedSort="name" | |||
total={0} | |||
view="overall" | |||
@@ -92,7 +136,29 @@ exports[`renders 1`] = ` | |||
}, | |||
] | |||
} | |||
query={Object {}} | |||
query={ | |||
Object { | |||
"coverage": undefined, | |||
"duplications": undefined, | |||
"gate": undefined, | |||
"languages": undefined, | |||
"maintainability": undefined, | |||
"new_coverage": undefined, | |||
"new_duplications": undefined, | |||
"new_lines": undefined, | |||
"new_maintainability": undefined, | |||
"new_reliability": undefined, | |||
"new_security": undefined, | |||
"reliability": undefined, | |||
"search": undefined, | |||
"security": undefined, | |||
"size": undefined, | |||
"sort": undefined, | |||
"tags": undefined, | |||
"view": undefined, | |||
"visualization": undefined, | |||
} | |||
} | |||
/> | |||
<ListFooter | |||
count={1} |
@@ -1,7 +1,5 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`does not render for anonymous 1`] = `null`; | |||
exports[`handles organization 1`] = ` | |||
<header | |||
className="page-header text-center" |
@@ -1,7 +1,5 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`does not render 1`] = `null`; | |||
exports[`handles unknown languages 1`] = ` | |||
<div | |||
className="project-card-languages" | |||
@@ -9,15 +7,11 @@ exports[`handles unknown languages 1`] = ` | |||
<Tooltip | |||
overlay={ | |||
<span> | |||
<span | |||
key="cpp" | |||
> | |||
<span> | |||
cpp | |||
<br /> | |||
</span> | |||
<span | |||
key="Java" | |||
> | |||
<span> | |||
Java | |||
<br /> | |||
</span> | |||
@@ -39,15 +33,11 @@ exports[`handles unknown languages 2`] = ` | |||
<Tooltip | |||
overlay={ | |||
<span> | |||
<span | |||
key="unknown" | |||
> | |||
<span> | |||
unknown | |||
<br /> | |||
</span> | |||
<span | |||
key="Java" | |||
> | |||
<span> | |||
Java | |||
<br /> | |||
</span> | |||
@@ -69,15 +59,11 @@ exports[`renders 1`] = ` | |||
<Tooltip | |||
overlay={ | |||
<span> | |||
<span | |||
key="Java" | |||
> | |||
<span> | |||
Java | |||
<br /> | |||
</span> | |||
<span | |||
key="JavaScript" | |||
> | |||
<span> | |||
JavaScript | |||
<br /> | |||
</span> | |||
@@ -99,15 +85,11 @@ exports[`sorts languages 1`] = ` | |||
<Tooltip | |||
overlay={ | |||
<span> | |||
<span | |||
key="JavaScript" | |||
> | |||
<span> | |||
JavaScript | |||
<br /> | |||
</span> | |||
<span | |||
key="Java" | |||
> | |||
<span> | |||
Java | |||
<br /> | |||
</span> |
@@ -1,7 +1,5 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`does not render 1`] = `null`; | |||
exports[`renders 1`] = ` | |||
<div | |||
className="project-card-measure project-card-quality-gate spacer-left" |
@@ -57,6 +57,7 @@ exports[`should render maximum 10 languages in the searchbox results 1`] = ` | |||
}, | |||
] | |||
} | |||
organization={undefined} | |||
property="languages" | |||
query={ | |||
Object { | |||
@@ -130,6 +131,7 @@ exports[`should render the languages facet with the selected languages 1`] = ` | |||
}, | |||
] | |||
} | |||
organization={undefined} | |||
property="languages" | |||
query={ | |||
Object { | |||
@@ -333,6 +335,7 @@ exports[`should render the languages without the ones in the facet 1`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={undefined} | |||
options={ | |||
Array [ | |||
Object { | |||
@@ -349,6 +352,7 @@ exports[`should render the languages without the ones in the facet 1`] = ` | |||
}, | |||
] | |||
} | |||
organization={undefined} | |||
property="languages" | |||
query={ | |||
Object { |
@@ -60,6 +60,7 @@ exports[`should render maximum 10 tags in the searchbox results 1`] = ` | |||
}, | |||
] | |||
} | |||
organization={undefined} | |||
property="tags" | |||
query={ | |||
Object { | |||
@@ -121,6 +122,7 @@ exports[`should render the tags facet with the selected tags 1`] = ` | |||
onInputChange={[Function]} | |||
onOpen={[Function]} | |||
options={Array []} | |||
organization={undefined} | |||
property="tags" | |||
query={ | |||
Object { | |||
@@ -294,10 +296,12 @@ exports[`should render the tags without the ones in the facet 1`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={undefined} | |||
isLoading={false} | |||
onInputChange={[Function]} | |||
onOpen={[Function]} | |||
options={Array []} | |||
organization={undefined} | |||
property="tags" | |||
query={ | |||
Object { | |||
@@ -340,6 +344,7 @@ exports[`should render the tags without the ones in the facet 2`] = ` | |||
} | |||
footer={ | |||
<SearchableFilterFooter | |||
isFavorite={undefined} | |||
isLoading={false} | |||
onInputChange={[Function]} | |||
onOpen={[Function]} | |||
@@ -359,6 +364,7 @@ exports[`should render the tags without the ones in the facet 2`] = ` | |||
}, | |||
] | |||
} | |||
organization={undefined} | |||
property="tags" | |||
query={ | |||
Object { |
@@ -17,7 +17,13 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first, import/order */ | |||
/* eslint-disable import/order */ | |||
import * as React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import App, { Props } from '../App'; | |||
jest.mock('react-dom'); | |||
jest.mock('lodash', () => { | |||
const lodash = require.requireActual('lodash'); | |||
lodash.debounce = (fn: Function) => (...args: any[]) => fn(args); | |||
@@ -34,10 +40,6 @@ jest.mock('rc-tooltip', () => ({ | |||
jest.mock('../../../api/components', () => ({ getComponents: jest.fn() })); | |||
import * as React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import App, { Props } from '../App'; | |||
const getComponents = require('../../../api/components').getComponents as jest.Mock<any>; | |||
const organization = { key: 'org', name: 'org', projectVisibility: 'public' }; | |||
@@ -121,12 +123,15 @@ it('creates project', () => { | |||
expect(wrapper.find('CreateProjectForm').exists()).toBeFalsy(); | |||
wrapper.find('Header').prop<Function>('onProjectCreate')(); | |||
wrapper.update(); | |||
expect(wrapper.find('CreateProjectForm').exists()).toBeTruthy(); | |||
wrapper.find('CreateProjectForm').prop<Function>('onProjectCreated')(); | |||
wrapper.update(); | |||
expect(getComponents.mock.calls).toHaveLength(2); | |||
wrapper.find('CreateProjectForm').prop<Function>('onClose')(); | |||
wrapper.update(); | |||
expect(wrapper.find('CreateProjectForm').exists()).toBeFalsy(); | |||
}); | |||
@@ -17,17 +17,19 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first, import/order */ | |||
jest.mock('../../../api/permissions', () => ({ | |||
bulkApplyTemplate: jest.fn(() => Promise.resolve()), | |||
getPermissionTemplates: jest.fn(() => Promise.resolve({ permissionTemplates: [] })) | |||
})); | |||
/* eslint-disable import/order */ | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import BulkApplyTemplateModal, { Props } from '../BulkApplyTemplateModal'; | |||
import { click } from '../../../helpers/testUtils'; | |||
jest.mock('react-dom'); | |||
jest.mock('../../../api/permissions', () => ({ | |||
bulkApplyTemplate: jest.fn(() => Promise.resolve()), | |||
getPermissionTemplates: jest.fn(() => Promise.resolve({ permissionTemplates: [] })) | |||
})); | |||
const bulkApplyTemplate = require('../../../api/permissions').bulkApplyTemplate as jest.Mock<any>; | |||
const getPermissionTemplates = require('../../../api/permissions') | |||
.getPermissionTemplates as jest.Mock<any>; |
@@ -48,6 +48,7 @@ it('changes default visibility', () => { | |||
expect(onVisibilityChange).toBeCalledWith(Visibility.Private); | |||
modalWrapper.prop<Function>('onClose')(); | |||
wrapper.update(); | |||
expect(wrapper.find('ChangeVisibilityForm').exists()).toBeFalsy(); | |||
}); | |||
@@ -97,6 +97,7 @@ it('bulk applies permission template', () => { | |||
click(wrapper.find('.js-bulk-apply-permission-template')); | |||
expect(wrapper.find('BulkApplyTemplateModal')).toMatchSnapshot(); | |||
wrapper.find('BulkApplyTemplateModal').prop<Function>('onClose')(); | |||
wrapper.update(); | |||
expect(wrapper.find('BulkApplyTemplateModal').exists()).toBeFalsy(); | |||
}); | |||
@@ -37,8 +37,8 @@ export default class Details extends React.PureComponent { | |||
this.fetchDetails(); | |||
} | |||
componentDidUpdate(nextProps) { | |||
if (nextProps.params.id !== this.props.params.id) { | |||
componentDidUpdate(prevProps) { | |||
if (prevProps.params.id !== this.props.params.id) { | |||
this.fetchDetails(); | |||
} | |||
} |
@@ -19,6 +19,7 @@ | |||
*/ | |||
import * as React from 'react'; | |||
import Helmet from 'react-helmet'; | |||
import { WithRouterProps } from 'react-router'; | |||
import ProfileNotFound from './ProfileNotFound'; | |||
import ProfileHeader from '../details/ProfileHeader'; | |||
import { Profile } from '../types'; | |||
@@ -32,11 +33,10 @@ interface Props { | |||
onRequestFail: (reasong: any) => void; | |||
organization: string | null; | |||
profiles: Profile[]; | |||
router: { replace: (path: any) => void }; | |||
updateProfiles: () => Promise<void>; | |||
} | |||
export default class ProfileContainer extends React.PureComponent<Props> { | |||
export default class ProfileContainer extends React.PureComponent<Props & WithRouterProps> { | |||
componentDidMount() { | |||
const { location, profiles, router } = this.props; | |||
if (location.query.key) { |
@@ -17,14 +17,17 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { shallow } from 'enzyme'; | |||
import * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import Helmet from 'react-helmet'; | |||
import { WithRouterProps } from 'react-router'; | |||
import ProfileContainer from '../ProfileContainer'; | |||
import ProfileNotFound from '../ProfileNotFound'; | |||
import ProfileHeader from '../../details/ProfileHeader'; | |||
import { createFakeProfile } from '../../utils'; | |||
const routerProps = { router: {} } as WithRouterProps; | |||
it('should render ProfileHeader', () => { | |||
const targetProfile = createFakeProfile({ language: 'js', name: 'fake' }); | |||
const profiles = [targetProfile, createFakeProfile({ language: 'js', name: 'another' })]; | |||
@@ -35,8 +38,8 @@ it('should render ProfileHeader', () => { | |||
onRequestFail={jest.fn()} | |||
organization={null} | |||
profiles={profiles} | |||
router={{} as any} | |||
updateProfiles={updateProfiles}> | |||
updateProfiles={updateProfiles} | |||
{...routerProps}> | |||
<div /> | |||
</ProfileContainer> | |||
); | |||
@@ -57,8 +60,8 @@ it('should render ProfileNotFound', () => { | |||
onRequestFail={jest.fn()} | |||
organization={null} | |||
profiles={profiles} | |||
router={{} as any} | |||
updateProfiles={jest.fn()}> | |||
updateProfiles={jest.fn()} | |||
{...routerProps}> | |||
<div /> | |||
</ProfileContainer> | |||
); | |||
@@ -74,8 +77,8 @@ it('should render Helmet', () => { | |||
onRequestFail={jest.fn()} | |||
organization={null} | |||
profiles={profiles} | |||
router={{} as any} | |||
updateProfiles={updateProfiles}> | |||
updateProfiles={updateProfiles} | |||
{...routerProps}> | |||
<div /> | |||
</ProfileContainer> | |||
); |
@@ -17,17 +17,17 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first, import/order */ | |||
jest.mock('../../../../api/quality-profiles', () => ({ | |||
searchUsers: jest.fn(() => Promise.resolve([])), | |||
searchGroups: jest.fn(() => Promise.resolve([])) | |||
})); | |||
/* eslint-disable import/order */ | |||
import * as React from 'react'; | |||
import { mount, shallow } from 'enzyme'; | |||
import ProfilePermissions from '../ProfilePermissions'; | |||
import { click } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/quality-profiles', () => ({ | |||
searchUsers: jest.fn(() => Promise.resolve([])), | |||
searchGroups: jest.fn(() => Promise.resolve([])) | |||
})); | |||
const searchUsers = require('../../../../api/quality-profiles').searchUsers as jest.Mock<any>; | |||
const searchGroups = require('../../../../api/quality-profiles').searchGroups as jest.Mock<any>; | |||
@@ -50,16 +50,21 @@ it('renders', () => { | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
it('opens add users form', () => { | |||
it('opens add users form', async () => { | |||
searchUsers.mockImplementationOnce(() => | |||
Promise.resolve({ users: [{ login: 'luke', name: 'Luke Skywalker' }] }) | |||
); | |||
const wrapper = shallow(<ProfilePermissions profile={profile} />); | |||
(wrapper.instance() as ProfilePermissions).mounted = true; | |||
wrapper.setState({ loading: false, users: [{ login: 'luke', name: 'Luke Skywalker' }] }); | |||
expect(searchUsers).toHaveBeenCalled(); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper.find('ProfilePermissionsForm').exists()).toBeFalsy(); | |||
click(wrapper.find('button')); | |||
expect(wrapper.find('ProfilePermissionsForm').exists()).toBeTruthy(); | |||
wrapper.find('ProfilePermissionsForm').prop<Function>('onClose')(); | |||
wrapper.update(); | |||
expect(wrapper.find('ProfilePermissionsForm').exists()).toBeFalsy(); | |||
}); | |||
@@ -17,23 +17,22 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
/* eslint-disable import/first */ | |||
import * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import ProfilePermissionsFormSelect from '../ProfilePermissionsFormSelect'; | |||
jest.mock('lodash', () => { | |||
const lodash = require.requireActual('lodash'); | |||
lodash.debounce = (fn: Function) => (...args: any[]) => fn(...args); | |||
return lodash; | |||
}); | |||
import * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import ProfilePermissionsFormSelect from '../ProfilePermissionsFormSelect'; | |||
it('renders', () => { | |||
expect( | |||
shallow( | |||
<ProfilePermissionsFormSelect | |||
onChange={jest.fn()} | |||
onSearch={jest.fn()} | |||
onSearch={jest.fn(() => Promise.resolve([]))} | |||
selected={{ name: 'lambda' }} | |||
/> | |||
) | |||
@@ -49,6 +48,8 @@ it('searches', () => { | |||
selected={{ name: 'lambda' }} | |||
/> | |||
); | |||
expect(onSearch).toBeCalledWith(''); | |||
onSearch.mockClear(); | |||
wrapper.prop<Function>('onInputChange')('f'); | |||
expect(onSearch).not.toBeCalled(); |
@@ -20,7 +20,6 @@ | |||
import * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import ProfileRules from '../ProfileRules'; | |||
import { doAsync } from '../../../../helpers/testUtils'; | |||
import * as apiRules from '../../../../api/rules'; | |||
import * as apiQP from '../../../../api/quality-profiles'; | |||
@@ -82,16 +81,15 @@ const apiResponseActive = { | |||
} | |||
}); | |||
it('should render the quality profiles rules with sonarway comparison', () => { | |||
it('should render the quality profiles rules with sonarway comparison', async () => { | |||
const wrapper = shallow(<ProfileRules organization="foo" profile={PROFILE} />); | |||
const instance = wrapper.instance() as any; | |||
instance.mounted = true; | |||
instance.loadRules(); | |||
return doAsync(() => { | |||
wrapper.update(); | |||
expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(1); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(1); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
it('should show a button to activate more rules for admins', () => { | |||
@@ -116,22 +114,18 @@ it('should not show a button to activate more rules on built in profiles', () => | |||
expect(wrapper.find('.js-activate-rules')).toHaveLength(0); | |||
}); | |||
it('should not show sonarway comparison for built in profiles', () => { | |||
it('should not show sonarway comparison for built in profiles', async () => { | |||
(apiQP as any).getQualityProfile = jest.fn(() => Promise.resolve()); | |||
const wrapper = shallow( | |||
<ProfileRules organization={null} profile={{ ...PROFILE, isBuiltIn: true }} /> | |||
); | |||
const instance = wrapper.instance() as any; | |||
instance.mounted = true; | |||
instance.loadRules(); | |||
return doAsync(() => { | |||
wrapper.update(); | |||
expect(apiQP.getQualityProfile).toHaveBeenCalledTimes(0); | |||
expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(0); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(apiQP.getQualityProfile).toHaveBeenCalledTimes(0); | |||
expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(0); | |||
}); | |||
it('should not show sonarway comparison if there is no missing rules', () => { | |||
it('should not show sonarway comparison if there is no missing rules', async () => { | |||
(apiQP as any).getQualityProfile = jest.fn(() => | |||
Promise.resolve({ | |||
compareToSonarWay: { | |||
@@ -142,12 +136,8 @@ it('should not show sonarway comparison if there is no missing rules', () => { | |||
}) | |||
); | |||
const wrapper = shallow(<ProfileRules organization={null} profile={PROFILE} />); | |||
const instance = wrapper.instance() as any; | |||
instance.mounted = true; | |||
instance.loadRules(); | |||
return doAsync(() => { | |||
wrapper.update(); | |||
expect(apiQP.getQualityProfile).toHaveBeenCalledTimes(1); | |||
expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(0); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(apiQP.getQualityProfile).toHaveBeenCalledTimes(1); | |||
expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(0); | |||
}); |
@@ -6,7 +6,7 @@ exports[`renders 1`] = ` | |||
className="Select-big" | |||
clearable={false} | |||
filterOptions={[Function]} | |||
isLoading={false} | |||
isLoading={true} | |||
noResultsText="no_results" | |||
onChange={[Function]} | |||
onInputChange={[Function]} |
@@ -17,7 +17,7 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { withRouter, RouterState, IndexRouteProps, RouteComponent } from 'react-router'; | |||
import { RouterState, IndexRouteProps, RouteComponent, withRouter } from 'react-router'; | |||
const routes = [ | |||
{ |
@@ -129,6 +129,7 @@ Array [ | |||
> | |||
<CheckIcon> | |||
<svg | |||
className={undefined} | |||
height={16} | |||
viewBox="0 0 16 16" | |||
width={16} |
@@ -81,29 +81,20 @@ beforeEach(() => { | |||
it('should display correctly', async () => { | |||
const wrapper = shallow(<SystemUpgradeNotif />); | |||
expect(wrapper).toMatchSnapshot(); | |||
const instance = wrapper.instance() as SystemUpgradeNotif; | |||
instance.mounted = true; | |||
instance.fetchSystemUpgrade(); | |||
expect(wrapper.type()).toBeNull(); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
it('should display nothing', async () => { | |||
getSystemUpgrades.mockImplementationOnce(() => | |||
Promise.resolve({ updateCenterRefresh: '', upgrades: [] }) | |||
); | |||
getSystemUpgrades.mockImplementationOnce(() => { | |||
return Promise.resolve({ updateCenterRefresh: '', upgrades: [] }); | |||
}); | |||
const wrapper = shallow(<SystemUpgradeNotif />); | |||
const instance = wrapper.instance() as SystemUpgradeNotif; | |||
instance.mounted = true; | |||
instance.fetchSystemUpgrade(); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(wrapper.type()).toBeNull(); | |||
}); | |||
it('should fetch upgrade when mounting', () => { | |||
@@ -113,12 +104,8 @@ it('should fetch upgrade when mounting', () => { | |||
it('should open the upgrade form', async () => { | |||
const wrapper = shallow(<SystemUpgradeNotif />); | |||
const instance = wrapper.instance() as SystemUpgradeNotif; | |||
instance.mounted = true; | |||
instance.fetchSystemUpgrade(); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
click(wrapper.find('button')); | |||
expect(wrapper.find('SystemUpgradeForm').exists()).toBeTruthy(); | |||
}); |
@@ -1,8 +1,6 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should display correctly 1`] = `null`; | |||
exports[`should display correctly 2`] = ` | |||
exports[`should display correctly 1`] = ` | |||
<div | |||
className="page-notifs" | |||
> | |||
@@ -19,5 +17,3 @@ exports[`should display correctly 2`] = ` | |||
</div> | |||
</div> | |||
`; | |||
exports[`should display nothing 1`] = `null`; |
@@ -21,7 +21,7 @@ | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import NewOrganizationForm from '../NewOrganizationForm'; | |||
import { change, doAsync, submit } from '../../../../helpers/testUtils'; | |||
import { change, submit } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/organizations', () => ({ | |||
createOrganization: () => Promise.resolve(), | |||
@@ -29,28 +29,28 @@ jest.mock('../../../../api/organizations', () => ({ | |||
getOrganization: () => Promise.resolve(null) | |||
})); | |||
it('creates new organization', () => { | |||
it('creates new organization', async () => { | |||
const onDone = jest.fn(); | |||
const wrapper = mount(<NewOrganizationForm onDelete={jest.fn()} onDone={onDone} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'foo'); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
it('deletes organization', () => { | |||
it('deletes organization', async () => { | |||
const onDelete = jest.fn(); | |||
const wrapper = mount(<NewOrganizationForm onDelete={onDelete} onDone={jest.fn()} />); | |||
wrapper.setState({ done: true, loading: false, organization: 'foo' }); | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); |
@@ -21,35 +21,35 @@ | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import NewProjectForm from '../NewProjectForm'; | |||
import { change, doAsync, submit } from '../../../../helpers/testUtils'; | |||
import { change, submit } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/components', () => ({ | |||
createProject: () => Promise.resolve(), | |||
deleteProject: () => Promise.resolve() | |||
})); | |||
it('creates new project', () => { | |||
it('creates new project', async () => { | |||
const onDone = jest.fn(); | |||
const wrapper = mount(<NewProjectForm onDelete={jest.fn()} onDone={onDone} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'foo'); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
it('deletes project', () => { | |||
it('deletes project', async () => { | |||
const onDelete = jest.fn(); | |||
const wrapper = mount(<NewProjectForm onDelete={onDelete} onDone={jest.fn()} />); | |||
wrapper.setState({ done: true, loading: false, projectKey: 'foo' }); | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); |
@@ -21,14 +21,19 @@ | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import OrganizationStep from '../OrganizationStep'; | |||
import { click, doAsync } from '../../../../helpers/testUtils'; | |||
import { click } from '../../../../helpers/testUtils'; | |||
import { getMyOrganizations } from '../../../../api/organizations'; | |||
jest.mock('../../../../api/organizations', () => ({ | |||
getMyOrganizations: () => Promise.resolve(['user', 'another']) | |||
getMyOrganizations: jest.fn(() => Promise.resolve(['user', 'another'])) | |||
})); | |||
const currentUser = { isLoggedIn: true, login: 'user' }; | |||
beforeEach(() => { | |||
getMyOrganizations.mockClear(); | |||
}); | |||
// FIXME | |||
// - if `mount` is used, then it's not possible to correctly set the state, | |||
// because the mocked api call is used | |||
@@ -49,7 +54,7 @@ it.skip('works with personal organization', () => { | |||
expect(onContinue).toBeCalledWith('user'); | |||
}); | |||
it('works with existing organization', () => { | |||
it('works with existing organization', async () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount( | |||
<OrganizationStep | |||
@@ -61,19 +66,20 @@ it('works with existing organization', () => { | |||
stepNumber={1} | |||
/> | |||
); | |||
return doAsync(() => { | |||
click(wrapper.find('.js-existing')); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper | |||
.find('Select') | |||
.first() | |||
.prop('onChange')({ value: 'another' }); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('another'); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
click(wrapper.find('.js-existing')); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper | |||
.find('Select') | |||
.first() | |||
.prop('onChange')({ value: 'another' }); | |||
wrapper.update(); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('another'); | |||
}); | |||
it('works with new organization', () => { | |||
it('works with new organization', async () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount( | |||
<OrganizationStep | |||
@@ -85,10 +91,11 @@ it('works with new organization', () => { | |||
stepNumber={1} | |||
/> | |||
); | |||
return doAsync(() => { | |||
click(wrapper.find('.js-new')); | |||
wrapper.find('NewOrganizationForm').prop('onDone')('new'); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('new'); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
click(wrapper.find('.js-new')); | |||
wrapper.find('NewOrganizationForm').prop('onDone')('new'); | |||
wrapper.update(); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('new'); | |||
}); |
@@ -28,28 +28,28 @@ jest.mock('../../../../api/components', () => ({ | |||
deleteProject: () => Promise.resolve() | |||
})); | |||
it('creates new project', () => { | |||
it('creates new project', async () => { | |||
const onDone = jest.fn(); | |||
const wrapper = mount(<ProjectKeyStep onDelete={jest.fn()} onDone={onDone} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'foo'); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
it('deletes project', () => { | |||
it('deletes project', async () => { | |||
const onDelete = jest.fn(); | |||
const wrapper = mount(<ProjectKeyStep onDelete={onDelete} onDone={jest.fn()} />); | |||
wrapper.setState({ done: true, loading: false, projectKey: 'foo' }); | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); |
@@ -21,7 +21,7 @@ | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import TokenStep from '../TokenStep'; | |||
import { change, click, doAsync, submit } from '../../../../helpers/testUtils'; | |||
import { change, click, submit } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/user-tokens', () => ({ | |||
getTokens: () => Promise.resolve([{ name: 'foo' }]), | |||
@@ -43,11 +43,14 @@ it('generates token', async () => { | |||
/> | |||
); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'my token'); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => expect(wrapper).toMatchSnapshot()); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
it('revokes token', async () => { | |||
@@ -66,7 +69,9 @@ it('revokes token', async () => { | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => expect(wrapper).toMatchSnapshot()); | |||
await new Promise(setImmediate); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
it('continues', async () => { |
@@ -25,6 +25,9 @@ exports[`works with existing organization 1`] = ` | |||
> | |||
<div | |||
className="boxed-group onboarding-step is-open" | |||
onClick={undefined} | |||
role={undefined} | |||
tabIndex={undefined} | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -79,6 +82,7 @@ exports[`works with existing organization 1`] = ` | |||
}, | |||
] | |||
} | |||
value={undefined} | |||
> | |||
<Select | |||
addLabelText="Add \\"{label}\\"?" | |||
@@ -134,11 +138,13 @@ exports[`works with existing organization 1`] = ` | |||
searchable={true} | |||
simpleValue={false} | |||
tabSelectsValue={true} | |||
value={undefined} | |||
valueComponent={[Function]} | |||
valueKey="value" | |||
> | |||
<div | |||
className="Select input-super-large Select--single is-searchable" | |||
style={undefined} | |||
> | |||
<div | |||
className="Select-control" | |||
@@ -147,6 +153,7 @@ exports[`works with existing organization 1`] = ` | |||
onTouchEnd={[Function]} | |||
onTouchMove={[Function]} | |||
onTouchStart={[Function]} | |||
style={undefined} | |||
> | |||
<span | |||
className="Select-multi-value-wrapper" | |||
@@ -159,8 +166,11 @@ exports[`works with existing organization 1`] = ` | |||
</div> | |||
<AutosizeInput | |||
aria-activedescendant="react-select-2--value" | |||
aria-describedby={undefined} | |||
aria-expanded="false" | |||
aria-haspopup="false" | |||
aria-label={undefined} | |||
aria-labelledby={undefined} | |||
aria-owns="" | |||
className="Select-input" | |||
minWidth="5" | |||
@@ -169,6 +179,7 @@ exports[`works with existing organization 1`] = ` | |||
onFocus={[Function]} | |||
required={false} | |||
role="combobox" | |||
tabIndex={undefined} | |||
value="" | |||
> | |||
<div | |||
@@ -188,9 +199,14 @@ exports[`works with existing organization 1`] = ` | |||
/> | |||
<input | |||
aria-activedescendant="react-select-2--value" | |||
aria-describedby={undefined} | |||
aria-expanded="false" | |||
aria-haspopup="false" | |||
aria-label={undefined} | |||
aria-labelledby={undefined} | |||
aria-owns="" | |||
className={undefined} | |||
id={undefined} | |||
onBlur={[Function]} | |||
onChange={[Function]} | |||
onFocus={[Function]} | |||
@@ -202,6 +218,7 @@ exports[`works with existing organization 1`] = ` | |||
"width": "5px", | |||
} | |||
} | |||
tabIndex={undefined} | |||
value="" | |||
/> | |||
<div |
@@ -24,6 +24,9 @@ exports[`generates token 1`] = ` | |||
> | |||
<div | |||
className="boxed-group onboarding-step is-open" | |||
onClick={undefined} | |||
role={undefined} | |||
tabIndex={undefined} | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -126,6 +129,9 @@ exports[`generates token 2`] = ` | |||
> | |||
<div | |||
className="boxed-group onboarding-step is-open" | |||
onClick={undefined} | |||
role={undefined} | |||
tabIndex={undefined} | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -225,6 +231,9 @@ exports[`generates token 3`] = ` | |||
> | |||
<div | |||
className="boxed-group onboarding-step is-open" | |||
onClick={undefined} | |||
role={undefined} | |||
tabIndex={undefined} | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -322,6 +331,9 @@ exports[`revokes token 1`] = ` | |||
> | |||
<div | |||
className="boxed-group onboarding-step is-open" | |||
onClick={undefined} | |||
role={undefined} | |||
tabIndex={undefined} | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -419,6 +431,9 @@ exports[`revokes token 2`] = ` | |||
> | |||
<div | |||
className="boxed-group onboarding-step is-open" | |||
onClick={undefined} | |||
role={undefined} | |||
tabIndex={undefined} | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
@@ -498,6 +513,9 @@ exports[`revokes token 3`] = ` | |||
> | |||
<div | |||
className="boxed-group onboarding-step is-open" | |||
onClick={undefined} | |||
role={undefined} | |||
tabIndex={undefined} | |||
> | |||
<div | |||
className="onboarding-step-number" |
@@ -19,9 +19,9 @@ | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import { mount } from 'enzyme'; | |||
import Command from '../Command'; | |||
it('renders correctly', () => { | |||
expect(shallow(<Command command={'foo\nbar'} />)).toMatchSnapshot(); | |||
expect(mount(<Command command={'foo\nbar'} />)).toMatchSnapshot(); | |||
}); |
@@ -1,18 +1,23 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div | |||
className="onboarding-command" | |||
<Command | |||
command="foo | |||
bar" | |||
> | |||
<pre> | |||
foo | |||
<div | |||
className="onboarding-command" | |||
> | |||
<pre> | |||
foo | |||
bar | |||
</pre> | |||
<button | |||
data-clipboard-text="foo | |||
</pre> | |||
<button | |||
data-clipboard-text="foo | |||
bar" | |||
> | |||
copy | |||
</button> | |||
</div> | |||
> | |||
copy | |||
</button> | |||
</div> | |||
</Command> | |||
`; |
@@ -43,8 +43,8 @@ export default class ResponseExample extends React.PureComponent<Props, State> { | |||
this.fetchResponseExample(); | |||
} | |||
componentDidUpdate(nextProps: Props) { | |||
if (nextProps.action !== this.props.action) { | |||
componentDidUpdate(prevProps: Props) { | |||
if (prevProps.action !== this.props.action) { | |||
this.fetchResponseExample(); | |||
} | |||
} |
@@ -115,9 +115,11 @@ export default class LineCode extends React.PureComponent { | |||
} | |||
attachEvents() { | |||
this.symbols = this.codeNode.querySelectorAll('.sym'); | |||
for (const symbol of this.symbols) { | |||
symbol.addEventListener('click', this.handleSymbolClick); | |||
if (this.codeNode) { | |||
this.symbols = this.codeNode.querySelectorAll('.sym'); | |||
for (const symbol of this.symbols) { | |||
symbol.addEventListener('click', this.handleSymbolClick); | |||
} | |||
} | |||
} | |||
@@ -2,13 +2,18 @@ | |||
exports[`should display bubbles 1`] = ` | |||
<Bubble | |||
color={undefined} | |||
key="0" | |||
link={undefined} | |||
onClick={undefined} | |||
r={45} | |||
tooltip={undefined} | |||
x={-10} | |||
y={52.3015873015873} | |||
> | |||
<circle | |||
className="bubble-chart-bubble" | |||
onClick={undefined} | |||
r={45} | |||
style={ | |||
Object { | |||
@@ -23,13 +28,18 @@ exports[`should display bubbles 1`] = ` | |||
exports[`should display bubbles 2`] = ` | |||
<Bubble | |||
color={undefined} | |||
key="1" | |||
link={undefined} | |||
onClick={undefined} | |||
r={33.57142857142857} | |||
tooltip={undefined} | |||
x={-75} | |||
y={33.57142857142857} | |||
> | |||
<circle | |||
className="bubble-chart-bubble" | |||
onClick={undefined} | |||
r={33.57142857142857} | |||
style={ | |||
Object { | |||
@@ -44,9 +54,12 @@ exports[`should display bubbles 2`] = ` | |||
exports[`should render bubble links 1`] = ` | |||
<Bubble | |||
color={undefined} | |||
key="0" | |||
link="foo" | |||
onClick={undefined} | |||
r={45} | |||
tooltip={undefined} | |||
x={-10} | |||
y={52.3015873015873} | |||
> | |||
@@ -61,6 +74,7 @@ exports[`should render bubble links 1`] = ` | |||
> | |||
<circle | |||
className="bubble-chart-bubble" | |||
onClick={undefined} | |||
r={45} | |||
style={ | |||
Object { | |||
@@ -77,9 +91,12 @@ exports[`should render bubble links 1`] = ` | |||
exports[`should render bubble links 2`] = ` | |||
<Bubble | |||
color={undefined} | |||
key="1" | |||
link="bar" | |||
onClick={undefined} | |||
r={33.57142857142857} | |||
tooltip={undefined} | |||
x={-75} | |||
y={33.57142857142857} | |||
> | |||
@@ -94,6 +111,7 @@ exports[`should render bubble links 2`] = ` | |||
> | |||
<circle | |||
className="bubble-chart-bubble" | |||
onClick={undefined} | |||
r={33.57142857142857} | |||
style={ | |||
Object { | |||
@@ -110,10 +128,12 @@ exports[`should render bubble links 2`] = ` | |||
exports[`should render bubbles with click handlers 1`] = ` | |||
<Bubble | |||
color={undefined} | |||
key="0" | |||
link="foo" | |||
onClick={[Function]} | |||
r={45} | |||
tooltip={undefined} | |||
x={-10} | |||
y={52.3015873015873} | |||
> | |||
@@ -134,10 +154,12 @@ exports[`should render bubbles with click handlers 1`] = ` | |||
exports[`should render bubbles with click handlers 2`] = ` | |||
<Bubble | |||
color={undefined} | |||
key="1" | |||
link="bar" | |||
onClick={[Function]} | |||
r={33.57142857142857} | |||
tooltip={undefined} | |||
x={-75} | |||
y={33.57142857142857} | |||
> |
@@ -68,7 +68,9 @@ export default class MultiSelect extends React.PureComponent { | |||
componentDidMount() { | |||
this.updateSelectedElements(this.props); | |||
this.updateUnselectedElements(this.props); | |||
this.container.addEventListener('keydown', this.handleKeyboard, true); | |||
if (this.container) { | |||
this.container.addEventListener('keydown', this.handleKeyboard, true); | |||
} | |||
} | |||
componentWillReceiveProps(nextProps /*: Props */) { |