@@ -36,12 +36,9 @@ import { translate } from '../../../../helpers/l10n'; | |||
import { isLoggedIn } from '../../../../helpers/users'; | |||
import { getCurrentUser, Store } from '../../../../store/rootReducer'; | |||
interface StateProps { | |||
currentUser: T.CurrentUser; | |||
} | |||
interface Props extends StateProps { | |||
export interface Props { | |||
branchLike?: T.BranchLike; | |||
currentUser: T.CurrentUser; | |||
component: T.Component; | |||
warnings: string[]; | |||
} | |||
@@ -100,7 +97,7 @@ export function ComponentNavMeta({ branchLike, component, currentUser, warnings | |||
); | |||
} | |||
function getCurrentPage(component: T.Component, branchLike: T.BranchLike | undefined) { | |||
export function getCurrentPage(component: T.Component, branchLike: T.BranchLike | undefined) { | |||
let currentPage: T.HomePage | undefined; | |||
if (component.qualifier === 'VW' || component.qualifier === 'SVW') { | |||
currentPage = { type: 'PORTFOLIO', component: component.key }; | |||
@@ -115,7 +112,7 @@ function getCurrentPage(component: T.Component, branchLike: T.BranchLike | undef | |||
return currentPage; | |||
} | |||
const mapStateToProps = (state: Store): StateProps => ({ | |||
const mapStateToProps = (state: Store) => ({ | |||
currentUser: getCurrentUser(state) | |||
}); | |||
@@ -19,40 +19,70 @@ | |||
*/ | |||
import * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import { ComponentNavMeta } from '../ComponentNavMeta'; | |||
import { ComponentNavMeta, getCurrentPage, Props } from '../ComponentNavMeta'; | |||
import { | |||
mockShortLivingBranch, | |||
mockComponent, | |||
mockLongLivingBranch, | |||
mockPullRequest | |||
mockPullRequest, | |||
mockCurrentUser, | |||
mockLoggedInUser | |||
} from '../../../../../helpers/testMocks'; | |||
it('renders status of short-living branch', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
}); | |||
describe('#ComponentNavMeta', () => { | |||
it('renders status of short-living branch', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
}); | |||
it('renders meta for long-living branch', () => { | |||
expect(shallowRender({ branchLike: mockLongLivingBranch() })).toMatchSnapshot(); | |||
}); | |||
it('renders meta for long-living branch', () => { | |||
expect( | |||
shallowRender({ branchLike: mockLongLivingBranch(), currentUser: mockLoggedInUser() }) | |||
).toMatchSnapshot(); | |||
}); | |||
it('renders meta for pull request', () => { | |||
expect( | |||
shallowRender({ | |||
branchLike: mockPullRequest({ | |||
url: 'https://example.com/pull/1234' | |||
it('renders meta for pull request', () => { | |||
expect( | |||
shallowRender({ | |||
branchLike: mockPullRequest({ | |||
url: 'https://example.com/pull/1234' | |||
}) | |||
}) | |||
}) | |||
).toMatchSnapshot(); | |||
).toMatchSnapshot(); | |||
}); | |||
}); | |||
describe('#getCurrentPage', () => { | |||
it('should return a portfolio page', () => { | |||
expect(getCurrentPage(mockComponent({ key: 'foo', qualifier: 'VW' }), undefined)).toEqual({ | |||
type: 'PORTFOLIO', | |||
component: 'foo' | |||
}); | |||
}); | |||
it('should return an app page', () => { | |||
expect( | |||
getCurrentPage( | |||
mockComponent({ key: 'foo', qualifier: 'APP' }), | |||
mockLongLivingBranch({ name: 'develop' }) | |||
) | |||
).toEqual({ type: 'APPLICATION', component: 'foo', branch: 'develop' }); | |||
}); | |||
it('should return a portfolio page', () => { | |||
expect(getCurrentPage(mockComponent(), mockShortLivingBranch())).toEqual({ | |||
type: 'PROJECT', | |||
component: 'my-project', | |||
branch: undefined | |||
}); | |||
}); | |||
}); | |||
function shallowRender(props = {}) { | |||
function shallowRender(props: Partial<Props> = {}) { | |||
return shallow( | |||
<ComponentNavMeta | |||
branchLike={mockShortLivingBranch()} | |||
component={mockComponent({ analysisDate: '2017-01-02T00:00:00.000Z', version: '0.0.1' })} | |||
currentUser={{ | |||
isLoggedIn: false | |||
}} | |||
currentUser={mockCurrentUser()} | |||
warnings={[]} | |||
{...props} | |||
/> |
@@ -1,6 +1,6 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders meta for long-living branch 1`] = ` | |||
exports[`#ComponentNavMeta renders meta for long-living branch 1`] = ` | |||
<div | |||
className="navbar-context-meta" | |||
> | |||
@@ -23,10 +23,24 @@ exports[`renders meta for long-living branch 1`] = ` | |||
0.0.1 | |||
</div> | |||
</Tooltip> | |||
<div | |||
className="navbar-context-meta-secondary" | |||
> | |||
<Connect(HomePageSelect) | |||
className="spacer-left" | |||
currentPage={ | |||
Object { | |||
"branch": "master", | |||
"component": "my-project", | |||
"type": "PROJECT", | |||
} | |||
} | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`renders meta for pull request 1`] = ` | |||
exports[`#ComponentNavMeta renders meta for pull request 1`] = ` | |||
<div | |||
className="navbar-context-meta" | |||
> | |||
@@ -69,7 +83,7 @@ exports[`renders meta for pull request 1`] = ` | |||
</div> | |||
`; | |||
exports[`renders status of short-living branch 1`] = ` | |||
exports[`#ComponentNavMeta renders status of short-living branch 1`] = ` | |||
<div | |||
className="navbar-context-meta" | |||
> |
@@ -18,56 +18,50 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import * as React from 'react'; | |||
import { connect } from 'react-redux'; | |||
import UserExternalIdentity from './UserExternalIdentity'; | |||
import UserGroups from './UserGroups'; | |||
import UserScmAccounts from './UserScmAccounts'; | |||
import { getCurrentUser, areThereCustomOrganizations, Store } from '../../../store/rootReducer'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { isSonarCloud } from '../../../helpers/system'; | |||
import { whenLoggedIn } from '../../../components/hoc/whenLoggedIn'; | |||
interface Props { | |||
customOrganizations?: boolean; | |||
user: T.LoggedInUser; | |||
export interface Props { | |||
currentUser: T.LoggedInUser; | |||
} | |||
function Profile({ customOrganizations, user }: Props) { | |||
export function Profile({ currentUser }: Props) { | |||
return ( | |||
<div className="account-body account-container"> | |||
<div className="boxed-group boxed-group-inner"> | |||
<div className="spacer-bottom"> | |||
{translate('login')}: <strong id="login">{user.login}</strong> | |||
{translate('login')}: <strong id="login">{currentUser.login}</strong> | |||
</div> | |||
{!user.local && user.externalProvider !== 'sonarqube' && ( | |||
{!currentUser.local && currentUser.externalProvider !== 'sonarqube' && ( | |||
<div className="spacer-bottom" id="identity-provider"> | |||
<UserExternalIdentity user={user} /> | |||
<UserExternalIdentity user={currentUser} /> | |||
</div> | |||
)} | |||
{!!user.email && ( | |||
{Boolean(currentUser.email) && ( | |||
<div className="spacer-bottom"> | |||
{translate('my_profile.email')}: <strong id="email">{user.email}</strong> | |||
{translate('my_profile.email')}: <strong id="email">{currentUser.email}</strong> | |||
</div> | |||
)} | |||
{!customOrganizations && ( | |||
{!isSonarCloud() && ( | |||
<> | |||
<hr className="account-separator" /> | |||
<UserGroups groups={user.groups} /> | |||
<UserGroups groups={currentUser.groups} /> | |||
</> | |||
)} | |||
<hr /> | |||
<UserScmAccounts scmAccounts={user.scmAccounts} user={user} /> | |||
<UserScmAccounts scmAccounts={currentUser.scmAccounts} user={currentUser} /> | |||
</div> | |||
</div> | |||
); | |||
} | |||
const mapStateToProps = (state: Store) => ({ | |||
customOrganizations: areThereCustomOrganizations(state), | |||
user: getCurrentUser(state) as T.LoggedInUser | |||
}); | |||
export default connect(mapStateToProps)(Profile); | |||
export default whenLoggedIn(Profile); |
@@ -0,0 +1,59 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info 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 * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import { Profile, Props } from '../Profile'; | |||
import { mockLoggedInUser } from '../../../../helpers/testMocks'; | |||
import { isSonarCloud } from '../../../../helpers/system'; | |||
jest.mock('../../../../helpers/system', () => ({ isSonarCloud: jest.fn().mockReturnValue(false) })); | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
}); | |||
it('should render email', () => { | |||
expect( | |||
shallowRender(mockLoggedInUser({ email: 'john@doe.com' })) | |||
.find('#email') | |||
.exists() | |||
).toBe(true); | |||
}); | |||
it('should render external identity', () => { | |||
expect( | |||
shallowRender(mockLoggedInUser({ local: false, externalProvider: 'github' })) | |||
.find('UserExternalIdentity') | |||
.exists() | |||
).toBe(true); | |||
}); | |||
it('should not display user groups', () => { | |||
(isSonarCloud as jest.Mock).mockReturnValueOnce(true); | |||
expect( | |||
shallowRender() | |||
.find('UserGroups') | |||
.exists() | |||
).toBe(false); | |||
}); | |||
function shallowRender(currentUser: Props['currentUser'] = mockLoggedInUser()) { | |||
return shallow(<Profile currentUser={currentUser} />); | |||
} |
@@ -0,0 +1,58 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should render correctly 1`] = ` | |||
<div | |||
className="account-body account-container" | |||
> | |||
<div | |||
className="boxed-group boxed-group-inner" | |||
> | |||
<div | |||
className="spacer-bottom" | |||
> | |||
login | |||
: | |||
<strong | |||
id="login" | |||
> | |||
luke | |||
</strong> | |||
</div> | |||
<div | |||
className="spacer-bottom" | |||
id="identity-provider" | |||
> | |||
<UserExternalIdentity | |||
user={ | |||
Object { | |||
"groups": Array [], | |||
"isLoggedIn": true, | |||
"login": "luke", | |||
"name": "Skywalker", | |||
"scmAccounts": Array [], | |||
} | |||
} | |||
/> | |||
</div> | |||
<hr | |||
className="account-separator" | |||
/> | |||
<UserGroups | |||
groups={Array []} | |||
/> | |||
<hr /> | |||
<UserScmAccounts | |||
scmAccounts={Array []} | |||
user={ | |||
Object { | |||
"groups": Array [], | |||
"isLoggedIn": true, | |||
"login": "luke", | |||
"name": "Skywalker", | |||
"scmAccounts": Array [], | |||
} | |||
} | |||
/> | |||
</div> | |||
</div> | |||
`; |
@@ -0,0 +1,58 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info 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 * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import PluginActions from '../PluginActions'; | |||
import { PluginInstalled, PluginAvailable } from '../../../../api/plugins'; | |||
const installedPlugin: PluginInstalled = { | |||
key: 'foo', | |||
name: 'Foo', | |||
filename: 'foo.zip', | |||
hash: '', | |||
implementationBuild: '', | |||
sonarLintSupported: true, | |||
termsAndConditionsUrl: 'https://url', | |||
updatedAt: 1, | |||
updates: [{ status: 'COMPATIBLE', requires: [] }], | |||
version: '7.7' | |||
}; | |||
const availablePlugin: PluginAvailable = { | |||
key: 'foo', | |||
name: 'Foo', | |||
release: { version: '7.7', date: 'date' }, | |||
termsAndConditionsUrl: 'https://url', | |||
update: { status: 'COMPATIBLE', requires: [] } | |||
}; | |||
it('should render installed plugin correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
expect(shallowRender({ plugin: { ...installedPlugin, editionBundled: true } })).toMatchSnapshot(); | |||
}); | |||
it('should render available plugin correctly', () => { | |||
expect(shallowRender({ plugin: availablePlugin })).toMatchSnapshot(); | |||
expect(shallowRender({ plugin: { ...availablePlugin, editionBundled: true } })).toMatchSnapshot(); | |||
}); | |||
function shallowRender(props: Partial<PluginActions['props']> = {}) { | |||
return shallow(<PluginActions plugin={installedPlugin} refreshPending={jest.fn()} {...props} />); | |||
} |
@@ -0,0 +1,116 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should render available plugin correctly 1`] = ` | |||
<div | |||
className="js-actions" | |||
> | |||
<p | |||
className="little-spacer-bottom" | |||
> | |||
<Checkbox | |||
checked={false} | |||
className="js-terms" | |||
id="plugin-terms-foo" | |||
onCheck={[Function]} | |||
thirdState={false} | |||
> | |||
<label | |||
className="little-spacer-left" | |||
htmlFor="plugin-terms-foo" | |||
> | |||
marketplace.i_accept_the | |||
</label> | |||
</Checkbox> | |||
<a | |||
className="js-plugin-terms nowrap little-spacer-left" | |||
href="https://url" | |||
target="_blank" | |||
> | |||
marketplace.terms_and_conditions | |||
</a> | |||
</p> | |||
<Button | |||
className="js-install" | |||
disabled={true} | |||
onClick={[Function]} | |||
> | |||
marketplace.install | |||
</Button> | |||
</div> | |||
`; | |||
exports[`should render available plugin correctly 2`] = ` | |||
<div | |||
className="js-actions" | |||
> | |||
<div> | |||
<p | |||
className="little-spacer-bottom" | |||
> | |||
marketplace.available_under_commercial_license | |||
</p> | |||
<a | |||
target="_blank" | |||
> | |||
marketplace.learn_more | |||
</a> | |||
</div> | |||
</div> | |||
`; | |||
exports[`should render installed plugin correctly 1`] = ` | |||
<div | |||
className="js-actions" | |||
> | |||
<div | |||
className="display-inlin-block" | |||
> | |||
<PluginUpdateButton | |||
disabled={false} | |||
key="0" | |||
onClick={[Function]} | |||
update={ | |||
Object { | |||
"requires": Array [], | |||
"status": "COMPATIBLE", | |||
} | |||
} | |||
/> | |||
<Button | |||
className="js-uninstall button-red little-spacer-left" | |||
disabled={false} | |||
onClick={[Function]} | |||
> | |||
marketplace.uninstall | |||
</Button> | |||
</div> | |||
</div> | |||
`; | |||
exports[`should render installed plugin correctly 2`] = ` | |||
<div | |||
className="js-actions" | |||
> | |||
<p> | |||
<CheckIcon | |||
className="little-spacer-right" | |||
/> | |||
marketplace.installed | |||
</p> | |||
<div | |||
className="spacer-top" | |||
> | |||
<PluginUpdateButton | |||
disabled={false} | |||
key="0" | |||
onClick={[Function]} | |||
update={ | |||
Object { | |||
"requires": Array [], | |||
"status": "COMPATIBLE", | |||
} | |||
} | |||
/> | |||
</div> | |||
</div> | |||
`; |
@@ -59,6 +59,7 @@ function shallowRender(props: Partial<Meta['props']> = {}) { | |||
appState={mockAppState({ organizationsEnabled: true })} | |||
component={mockComponent()} | |||
currentUser={mockLoggedInUser()} | |||
metrics={{}} | |||
onComponentChange={jest.fn()} | |||
organization={mockOrganization()} | |||
userOrganizations={[mockOrganization()]} |
@@ -39,6 +39,33 @@ exports[`should hide QG and QP links if the organization has a paid plan, and th | |||
onComponentChange={[MockFunction]} | |||
/> | |||
</div> | |||
<AnalysesList | |||
component={ | |||
Object { | |||
"breadcrumbs": Array [], | |||
"key": "my-project", | |||
"name": "MyProject", | |||
"organization": "foo", | |||
"qualifier": "TRK", | |||
"qualityGate": Object { | |||
"isDefault": true, | |||
"key": "30", | |||
"name": "Sonar way", | |||
}, | |||
"qualityProfiles": Array [ | |||
Object { | |||
"deleted": false, | |||
"key": "my-qp", | |||
"language": "ts", | |||
"name": "Sonar way", | |||
}, | |||
], | |||
"tags": Array [], | |||
} | |||
} | |||
metrics={Object {}} | |||
qualifier="TRK" | |||
/> | |||
<MetaLinks | |||
component={ | |||
Object { | |||
@@ -75,6 +102,11 @@ exports[`should hide QG and QP links if the organization has a paid plan, and th | |||
organization="foo" | |||
/> | |||
</div> | |||
<BadgesModal | |||
metrics={Object {}} | |||
project="my-project" | |||
qualifier="TRK" | |||
/> | |||
</div> | |||
`; | |||
@@ -117,6 +149,33 @@ exports[`should render correctly 1`] = ` | |||
onComponentChange={[MockFunction]} | |||
/> | |||
</div> | |||
<AnalysesList | |||
component={ | |||
Object { | |||
"breadcrumbs": Array [], | |||
"key": "my-project", | |||
"name": "MyProject", | |||
"organization": "foo", | |||
"qualifier": "TRK", | |||
"qualityGate": Object { | |||
"isDefault": true, | |||
"key": "30", | |||
"name": "Sonar way", | |||
}, | |||
"qualityProfiles": Array [ | |||
Object { | |||
"deleted": false, | |||
"key": "my-qp", | |||
"language": "ts", | |||
"name": "Sonar way", | |||
}, | |||
], | |||
"tags": Array [], | |||
} | |||
} | |||
metrics={Object {}} | |||
qualifier="TRK" | |||
/> | |||
<div | |||
className="overview-meta-card" | |||
id="overview-meta-quality-gate" | |||
@@ -182,6 +241,11 @@ exports[`should render correctly 1`] = ` | |||
organization="foo" | |||
/> | |||
</div> | |||
<BadgesModal | |||
metrics={Object {}} | |||
project="my-project" | |||
qualifier="TRK" | |||
/> | |||
</div> | |||
`; | |||
@@ -224,6 +288,33 @@ exports[`should show QG and QP links if the organization has a paid plan, and th | |||
onComponentChange={[MockFunction]} | |||
/> | |||
</div> | |||
<AnalysesList | |||
component={ | |||
Object { | |||
"breadcrumbs": Array [], | |||
"key": "my-project", | |||
"name": "MyProject", | |||
"organization": "foo", | |||
"qualifier": "TRK", | |||
"qualityGate": Object { | |||
"isDefault": true, | |||
"key": "30", | |||
"name": "Sonar way", | |||
}, | |||
"qualityProfiles": Array [ | |||
Object { | |||
"deleted": false, | |||
"key": "my-qp", | |||
"language": "ts", | |||
"name": "Sonar way", | |||
}, | |||
], | |||
"tags": Array [], | |||
} | |||
} | |||
metrics={Object {}} | |||
qualifier="TRK" | |||
/> | |||
<div | |||
className="overview-meta-card" | |||
id="overview-meta-quality-gate" | |||
@@ -289,5 +380,10 @@ exports[`should show QG and QP links if the organization has a paid plan, and th | |||
organization="foo" | |||
/> | |||
</div> | |||
<BadgesModal | |||
metrics={Object {}} | |||
project="my-project" | |||
qualifier="TRK" | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,56 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info 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 * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import ProfileProjects from '../ProfileProjects'; | |||
import { mockQualityProfile } from '../../../../helpers/testMocks'; | |||
import { waitAndUpdate } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/quality-profiles', () => ({ | |||
getProfileProjects: jest.fn().mockResolvedValue({ | |||
results: [ | |||
{ | |||
id: '633a5180-1ad7-4008-a5cb-e1d3cec4c816', | |||
key: 'org.sonarsource.xml:xml', | |||
name: 'SonarXML', | |||
selected: true | |||
} | |||
], | |||
paging: { pageIndex: 1, pageSize: 2, total: 10 }, | |||
more: true | |||
}) | |||
})); | |||
it('should render correctly', async () => { | |||
const wrapper = shallowRender(); | |||
expect(wrapper).toMatchSnapshot(); | |||
await waitAndUpdate(wrapper); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
function shallowRender(props: Partial<ProfileProjects['props']> = {}) { | |||
return shallow( | |||
<ProfileProjects | |||
organization="foo" | |||
profile={mockQualityProfile({ actions: { associateProjects: true } })} | |||
{...props} | |||
/> | |||
); | |||
} |
@@ -0,0 +1,95 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should render correctly 1`] = ` | |||
<div | |||
className="boxed-group quality-profile-projects" | |||
> | |||
<div | |||
className="boxed-group-actions" | |||
> | |||
<Button | |||
className="js-change-projects" | |||
onClick={[Function]} | |||
> | |||
quality_profiles.change_projects | |||
</Button> | |||
</div> | |||
<header | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
projects | |||
</h2> | |||
</header> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<i | |||
className="spinner" | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`should render correctly 2`] = ` | |||
<div | |||
className="boxed-group quality-profile-projects" | |||
> | |||
<div | |||
className="boxed-group-actions" | |||
> | |||
<Button | |||
className="js-change-projects" | |||
onClick={[Function]} | |||
> | |||
quality_profiles.change_projects | |||
</Button> | |||
</div> | |||
<header | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
projects | |||
</h2> | |||
</header> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<ul> | |||
<li | |||
className="spacer-top js-profile-project" | |||
data-key="org.sonarsource.xml:xml" | |||
key="org.sonarsource.xml:xml" | |||
> | |||
<Link | |||
className="link-with-icon" | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/dashboard", | |||
"query": Object { | |||
"id": "org.sonarsource.xml:xml", | |||
}, | |||
} | |||
} | |||
> | |||
<QualifierIcon | |||
qualifier="TRK" | |||
/> | |||
<span> | |||
SonarXML | |||
</span> | |||
</Link> | |||
</li> | |||
</ul> | |||
<ListFooter | |||
count={1} | |||
loadMore={[Function]} | |||
ready={true} | |||
total={10} | |||
/> | |||
</div> | |||
</div> | |||
`; |
@@ -22,7 +22,7 @@ import * as theme from '../../../app/theme'; | |||
import { getTextColor } from '../../../helpers/colors'; | |||
import { getBaseUrl } from '../../../helpers/urls'; | |||
interface Props { | |||
export interface Props { | |||
identityProvider?: T.IdentityProvider; | |||
user: T.User; | |||
} |
@@ -0,0 +1,86 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 SonarSource SA | |||
* mailto:info 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 * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import UserListItemIdentity, { Props, ExternalProvider } from '../UserListItemIdentity'; | |||
describe('#UserListItemIdentity', () => { | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
}); | |||
function shallowRender(props: Partial<Props> = {}) { | |||
return shallow( | |||
<UserListItemIdentity | |||
identityProvider={{ | |||
backgroundColor: 'blue', | |||
iconPath: 'icon/path', | |||
key: 'foo', | |||
name: 'Foo Provider' | |||
}} | |||
user={{ | |||
active: true, | |||
email: 'obi.one@empire', | |||
externalProvider: 'foo', | |||
lastConnectionDate: '2019-01-18T15:06:33+0100', | |||
local: false, | |||
login: 'obi', | |||
name: 'One', | |||
scmAccounts: [] | |||
}} | |||
{...props} | |||
/> | |||
); | |||
} | |||
}); | |||
describe('#ExternalProvider', () => { | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
}); | |||
it('should render the user external provider and identity', () => { | |||
expect(shallowRender({ identityProvider: undefined })).toMatchSnapshot(); | |||
}); | |||
function shallowRender(props: Partial<Props> = {}) { | |||
return shallow( | |||
<ExternalProvider | |||
identityProvider={{ | |||
backgroundColor: 'blue', | |||
iconPath: 'icon/path', | |||
key: 'foo', | |||
name: 'Foo Provider' | |||
}} | |||
user={{ | |||
active: true, | |||
email: 'obi.one@empire', | |||
externalProvider: 'foo', | |||
lastConnectionDate: '2019-01-18T15:06:33+0100', | |||
local: false, | |||
login: 'obi', | |||
name: 'One', | |||
scmAccounts: [] | |||
}} | |||
{...props} | |||
/> | |||
); | |||
} | |||
}); |
@@ -0,0 +1,80 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`#ExternalProvider should render correctly 1`] = ` | |||
<div | |||
className="js-user-identity-provider little-spacer-top" | |||
> | |||
<div | |||
className="identity-provider" | |||
style={ | |||
Object { | |||
"backgroundColor": "blue", | |||
"color": "#fff", | |||
} | |||
} | |||
> | |||
<img | |||
alt="Foo Provider" | |||
className="little-spacer-right" | |||
height="14" | |||
src="icon/path" | |||
width="14" | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`#ExternalProvider should render the user external provider and identity 1`] = ` | |||
<div | |||
className="js-user-identity-provider little-spacer-top" | |||
> | |||
<span> | |||
foo | |||
: | |||
</span> | |||
</div> | |||
`; | |||
exports[`#UserListItemIdentity should render correctly 1`] = ` | |||
<td> | |||
<div> | |||
<strong | |||
className="js-user-name" | |||
> | |||
One | |||
</strong> | |||
<span | |||
className="js-user-login note little-spacer-left" | |||
> | |||
obi | |||
</span> | |||
</div> | |||
<div | |||
className="js-user-email little-spacer-top" | |||
> | |||
obi.one@empire | |||
</div> | |||
<ExternalProvider | |||
identityProvider={ | |||
Object { | |||
"backgroundColor": "blue", | |||
"iconPath": "icon/path", | |||
"key": "foo", | |||
"name": "Foo Provider", | |||
} | |||
} | |||
user={ | |||
Object { | |||
"active": true, | |||
"email": "obi.one@empire", | |||
"externalProvider": "foo", | |||
"lastConnectionDate": "2019-01-18T15:06:33+0100", | |||
"local": false, | |||
"login": "obi", | |||
"name": "One", | |||
"scmAccounts": Array [], | |||
} | |||
} | |||
/> | |||
</td> | |||
`; |