@@ -20,27 +20,7 @@ | |||
import { getJSON, post, postJSON, RequestData } from 'sonar-ui-common/helpers/request'; | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
import getCoverageStatus from '../components/SourceViewer/helpers/getCoverageStatus'; | |||
import { RawIssue } from '../helpers/issues'; | |||
export interface IssueResponse { | |||
components?: Array<{ key: string; name: string }>; | |||
issue: RawIssue; | |||
rules?: Array<{}>; | |||
users?: Array<T.UserBase>; | |||
} | |||
interface IssuesResponse { | |||
components?: { key: string; organization: string; name: string }[]; | |||
effortTotal: number; | |||
facets: Array<{ | |||
property: string; | |||
values: { count: number; val: string }[]; | |||
}>; | |||
issues: RawIssue[]; | |||
paging: T.Paging; | |||
rules?: Array<{}>; | |||
users?: Array<T.UserBase>; | |||
} | |||
import { IssueResponse, RawIssuesResponse } from '../types/issues'; | |||
type FacetName = | |||
| 'assigned_to_me' | |||
@@ -63,7 +43,7 @@ type FacetName = | |||
| 'tags' | |||
| 'types'; | |||
export function searchIssues(query: RequestData): Promise<IssuesResponse> { | |||
export function searchIssues(query: RequestData): Promise<RawIssuesResponse> { | |||
return getJSON('/api/issues/search', query); | |||
} | |||
@@ -72,7 +52,7 @@ export function getFacets( | |||
facets: FacetName[] | |||
): Promise<{ | |||
facets: Array<{ property: string; values: T.FacetValue[] }>; | |||
response: IssuesResponse; | |||
response: RawIssuesResponse; | |||
}> { | |||
const data = { | |||
...query, | |||
@@ -88,7 +68,7 @@ export function getFacets( | |||
export function getFacet( | |||
query: RequestData, | |||
facet: FacetName | |||
): Promise<{ facet: { count: number; val: string }[]; response: IssuesResponse }> { | |||
): Promise<{ facet: { count: number; val: string }[]; response: RawIssuesResponse }> { | |||
return getFacets(query, [facet]).then(r => { | |||
return { facet: r.facets[0].values, response: r.response }; | |||
}); |
@@ -51,6 +51,13 @@ import { | |||
} from '../../../helpers/branch-like'; | |||
import { isSonarCloud } from '../../../helpers/system'; | |||
import { BranchLike } from '../../../types/branch-like'; | |||
import { | |||
Facet, | |||
FetchIssuesPromise, | |||
ReferencedComponent, | |||
ReferencedLanguage, | |||
ReferencedRule | |||
} from '../../../types/issues'; | |||
import { SecurityStandard } from '../../../types/security'; | |||
import * as actions from '../actions'; | |||
import ConciseIssuesList from '../conciseIssuesList/ConciseIssuesList'; | |||
@@ -60,16 +67,11 @@ import '../styles.css'; | |||
import { | |||
areMyIssuesSelected, | |||
areQueriesEqual, | |||
Facet, | |||
getOpen, | |||
mapFacet, | |||
parseFacets, | |||
parseQuery, | |||
Query, | |||
RawFacet, | |||
ReferencedComponent, | |||
ReferencedLanguage, | |||
ReferencedRule, | |||
saveMyIssues, | |||
scrollToIssue, | |||
serializeQuery, | |||
@@ -86,28 +88,15 @@ import NoIssues from './NoIssues'; | |||
import NoMyIssues from './NoMyIssues'; | |||
import PageActions from './PageActions'; | |||
interface FetchIssuesPromise { | |||
components: ReferencedComponent[]; | |||
effortTotal: number; | |||
facets: RawFacet[]; | |||
issues: T.Issue[]; | |||
languages: ReferencedLanguage[]; | |||
paging: T.Paging; | |||
rules: ReferencedRule[]; | |||
users: T.UserBase[]; | |||
} | |||
interface Props { | |||
branchLike?: BranchLike; | |||
component?: T.Component; | |||
currentUser: T.CurrentUser; | |||
fetchBranchStatus: (branchLike: BranchLike, projectKey: string) => Promise<void>; | |||
fetchIssues: (query: T.RawQuery, requestOrganizations?: boolean) => Promise<FetchIssuesPromise>; | |||
fetchIssues: (query: T.RawQuery) => Promise<FetchIssuesPromise>; | |||
location: Location; | |||
onBranchesChange?: () => void; | |||
organization?: { key: string }; | |||
router: Pick<Router, 'push' | 'replace'>; | |||
userOrganizations: T.Organization[]; | |||
} | |||
export interface State { | |||
@@ -424,17 +413,12 @@ export default class App extends React.PureComponent<Props, State> { | |||
.join(',') | |||
: undefined; | |||
const organizationKey = | |||
(component && component.organization) || | |||
(this.props.organization && this.props.organization.key); | |||
const parameters: T.Dict<string | undefined> = { | |||
...getBranchLikeQuery(this.props.branchLike), | |||
componentKeys: component && component.key, | |||
s: 'FILE_LINE', | |||
...serializeQuery(query), | |||
ps: '100', | |||
organization: organizationKey, | |||
facets, | |||
...additional | |||
}; | |||
@@ -452,7 +436,7 @@ export default class App extends React.PureComponent<Props, State> { | |||
Object.assign(parameters, { assignees: '__me__' }); | |||
} | |||
return this.props.fetchIssues(parameters, false); | |||
return this.props.fetchIssues(parameters); | |||
}; | |||
fetchFirstIssues() { | |||
@@ -630,7 +614,9 @@ export default class App extends React.PureComponent<Props, State> { | |||
})); | |||
} | |||
}, | |||
() => {} | |||
() => { | |||
/* Do nothing */ | |||
} | |||
); | |||
}; | |||
@@ -701,27 +687,20 @@ export default class App extends React.PureComponent<Props, State> { | |||
const { component } = this.props; | |||
const { myIssues, query } = this.state; | |||
const organizationKey = | |||
(component && component.organization) || | |||
(this.props.organization && this.props.organization.key); | |||
const parameters = { | |||
...getBranchLikeQuery(this.props.branchLike), | |||
componentKeys: component && component.key, | |||
facets: mapFacet(property), | |||
s: 'FILE_LINE', | |||
...serializeQuery({ ...query, ...changes }), | |||
ps: 1, | |||
organization: organizationKey | |||
ps: 1 | |||
}; | |||
if (myIssues) { | |||
Object.assign(parameters, { assignees: '__me__' }); | |||
} | |||
return this.props | |||
.fetchIssues(parameters, false) | |||
.then(({ facets }) => parseFacets(facets)[property]); | |||
return this.props.fetchIssues(parameters).then(({ facets }) => parseFacets(facets)[property]); | |||
}; | |||
closeFacet = (property: string) => { | |||
@@ -918,7 +897,6 @@ export default class App extends React.PureComponent<Props, State> { | |||
fetchIssues={checkAll ? this.fetchIssues : this.getCheckedIssues} | |||
onClose={this.handleCloseBulkChange} | |||
onDone={this.handleBulkChangeDone} | |||
organization={this.props.organization} | |||
/> | |||
)} | |||
</div> | |||
@@ -926,20 +904,9 @@ export default class App extends React.PureComponent<Props, State> { | |||
} | |||
renderFacets() { | |||
const { component, currentUser, userOrganizations, branchLike } = this.props; | |||
const { component, currentUser, branchLike } = this.props; | |||
const { query } = this.state; | |||
const organizationKey = | |||
(component && component.organization) || | |||
(this.props.organization && this.props.organization.key); | |||
const userOrganization = | |||
!isSonarCloud() || | |||
userOrganizations.find(o => { | |||
return o.key === organizationKey; | |||
}); | |||
const hideAuthorFacet = !userOrganization; | |||
return ( | |||
<div className="layout-page-filters"> | |||
{currentUser.isLoggedIn && !isSonarCloud() && ( | |||
@@ -954,14 +921,12 @@ export default class App extends React.PureComponent<Props, State> { | |||
component={component} | |||
createdAfterIncludesTime={this.createdAfterIncludesTime()} | |||
facets={this.state.facets} | |||
hideAuthorFacet={hideAuthorFacet} | |||
loadSearchResultCount={this.loadSearchResultCount} | |||
loadingFacets={this.state.loadingFacets} | |||
myIssues={this.state.myIssues} | |||
onFacetToggle={this.handleFacetToggle} | |||
onFilterChange={this.handleFilterChange} | |||
openFacets={this.state.openFacets} | |||
organization={this.props.organization} | |||
query={query} | |||
referencedComponentsById={this.state.referencedComponentsById} | |||
referencedComponentsByKey={this.state.referencedComponentsByKey} | |||
@@ -1029,7 +994,7 @@ export default class App extends React.PureComponent<Props, State> { | |||
} | |||
renderList() { | |||
const { branchLike, component, currentUser, organization } = this.props; | |||
const { branchLike, component, currentUser } = this.props; | |||
const { issues, loading, loadingMore, openIssue, paging } = this.state; | |||
const selectedIndex = this.getSelectedIndex(); | |||
const selectedIssue = selectedIndex !== undefined ? issues[selectedIndex] : undefined; | |||
@@ -1063,7 +1028,6 @@ export default class App extends React.PureComponent<Props, State> { | |||
onIssueClick={this.openIssue} | |||
onPopupToggle={this.handlePopupToggle} | |||
openPopup={this.state.openPopup} | |||
organization={organization} | |||
selectedIssue={selectedIssue} | |||
/> | |||
)} | |||
@@ -1101,7 +1065,7 @@ export default class App extends React.PureComponent<Props, State> { | |||
{this.renderBulkChange(openIssue)} | |||
<PageActions | |||
canSetHome={Boolean(!this.props.organization && !this.props.component)} | |||
canSetHome={!this.props.component} | |||
effortTotal={this.state.effortTotal} | |||
onReload={this.handleReload} | |||
paging={paging} |
@@ -17,53 +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. | |||
*/ | |||
import { uniq } from 'lodash'; | |||
import { connect } from 'react-redux'; | |||
import { Dispatch } from 'redux'; | |||
import { lazyLoadComponent } from 'sonar-ui-common/components/lazyLoadComponent'; | |||
import { searchIssues } from '../../../api/issues'; | |||
import { getOrganizations } from '../../../api/organizations'; | |||
import throwGlobalError from '../../../app/utils/throwGlobalError'; | |||
import { withRouter } from '../../../components/hoc/withRouter'; | |||
import { parseIssueFromResponse } from '../../../helpers/issues'; | |||
import { receiveOrganizations } from '../../../store/organizations'; | |||
import { fetchBranchStatus } from '../../../store/rootActions'; | |||
import { | |||
areThereCustomOrganizations, | |||
getCurrentUser, | |||
getMyOrganizations, | |||
Store | |||
} from '../../../store/rootReducer'; | |||
import { getCurrentUser, Store } from '../../../store/rootReducer'; | |||
import { FetchIssuesPromise } from '../../../types/issues'; | |||
const IssuesAppContainer = lazyLoadComponent(() => import('./App'), 'IssuesAppContainer'); | |||
interface StateProps { | |||
currentUser: T.CurrentUser; | |||
userOrganizations: T.Organization[]; | |||
fetchIssues: (query: T.RawQuery) => Promise<FetchIssuesPromise>; | |||
} | |||
const mapStateToProps = (state: Store): StateProps => ({ | |||
currentUser: getCurrentUser(state), | |||
userOrganizations: getMyOrganizations(state) | |||
fetchIssues | |||
}); | |||
const fetchIssueOrganizations = (organizationKeys: string[]) => (dispatch: Dispatch) => { | |||
if (!organizationKeys.length) { | |||
return Promise.resolve(); | |||
} | |||
return getOrganizations({ organizations: organizationKeys.join() }).then( | |||
response => dispatch(receiveOrganizations(response.organizations)), | |||
throwGlobalError | |||
); | |||
}; | |||
const fetchIssues = (query: T.RawQuery, requestOrganizations = true) => ( | |||
// use `Function` to be able to do `dispatch(...).then(...)` | |||
dispatch: Function, | |||
getState: () => Store | |||
) => { | |||
const organizationsEnabled = areThereCustomOrganizations(getState()); | |||
const fetchIssues = (query: T.RawQuery) => { | |||
return searchIssues({ | |||
...query, | |||
additionalFields: '_all', | |||
@@ -75,22 +51,12 @@ const fetchIssues = (query: T.RawQuery, requestOrganizations = true) => ( | |||
); | |||
return { ...response, issues: parsedIssues }; | |||
}) | |||
.then(response => { | |||
const organizationKeys = uniq([ | |||
...response.issues.map(issue => issue.organization), | |||
...(response.components || []).map(component => component.organization) | |||
]); | |||
return organizationsEnabled && requestOrganizations | |||
? dispatch(fetchIssueOrganizations(organizationKeys)).then(() => response) | |||
: response; | |||
}) | |||
.catch(throwGlobalError); | |||
}; | |||
// have to type cast this, because of async action | |||
const mapDispatchToProps = { | |||
fetchBranchStatus: fetchBranchStatus as any, | |||
fetchIssues: fetchIssues as any | |||
fetchBranchStatus: fetchBranchStatus as any | |||
}; | |||
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(IssuesAppContainer)); |
@@ -56,7 +56,6 @@ interface Props { | |||
fetchIssues: (x: {}) => Promise<{ issues: T.Issue[]; paging: T.Paging }>; | |||
onClose: () => void; | |||
onDone: () => void; | |||
organization: { key: string } | undefined; | |||
} | |||
interface FormFields { | |||
@@ -64,7 +63,6 @@ interface FormFields { | |||
assignee?: AssigneeOption; | |||
comment?: string; | |||
notifications?: boolean; | |||
organization?: string; | |||
removeTags?: Array<{ label: string; value: string }>; | |||
severity?: string; | |||
transition?: string; | |||
@@ -94,20 +92,13 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> { | |||
constructor(props: Props) { | |||
super(props); | |||
let organization = props.component && props.component.organization; | |||
if (props.organization && !organization) { | |||
organization = props.organization.key; | |||
} | |||
this.state = { initialTags: [], issues: [], loading: true, submitting: false, organization }; | |||
this.state = { initialTags: [], issues: [], loading: true, submitting: false }; | |||
} | |||
componentDidMount() { | |||
this.mounted = true; | |||
Promise.all([ | |||
this.loadIssues(), | |||
searchIssueTags({ organization: this.state.organization }) | |||
]).then( | |||
Promise.all([this.loadIssues(), searchIssueTags({})]).then( | |||
([{ issues, paging }, tags]) => { | |||
if (this.mounted) { | |||
if (issues.length > MAX_PAGE_SIZE) { | |||
@@ -178,7 +169,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> { | |||
}; | |||
handleTagsSearch = (query: string) => { | |||
return searchIssueTags({ organization: this.state.organization, q: query }).then(tags => | |||
return searchIssueTags({ q: query }).then(tags => | |||
tags.map(tag => ({ label: tag, value: tag })) | |||
); | |||
}; |
@@ -20,26 +20,12 @@ | |||
import * as React from 'react'; | |||
import QualifierIcon from 'sonar-ui-common/components/icons/QualifierIcon'; | |||
import { collapsePath, limitComponentName } from 'sonar-ui-common/helpers/path'; | |||
import Organization from '../../../components/shared/Organization'; | |||
import { getSelectedLocation } from '../utils'; | |||
interface Props { | |||
component?: T.Component; | |||
issue: Pick< | |||
T.Issue, | |||
| 'component' | |||
| 'componentLongName' | |||
| 'componentQualifier' | |||
| 'flows' | |||
| 'organization' | |||
| 'project' | |||
| 'projectName' | |||
| 'secondaryLocations' | |||
| 'subProject' | |||
| 'subProjectName' | |||
>; | |||
issue: T.Issue; | |||
link?: boolean; | |||
organization: { key: string } | undefined; | |||
selectedFlowIndex?: number; | |||
selectedLocationIndex?: number; | |||
} | |||
@@ -47,12 +33,9 @@ interface Props { | |||
export default function ComponentBreadcrumbs({ | |||
component, | |||
issue, | |||
organization, | |||
selectedFlowIndex, | |||
selectedLocationIndex | |||
}: Props) { | |||
const displayOrganization = | |||
!organization && (!component || ['VW', 'SVW'].includes(component.qualifier)); | |||
const displayProject = !component || !['TRK', 'BRC', 'DIR'].includes(component.qualifier); | |||
const displaySubProject = !component || !['BRC', 'DIR'].includes(component.qualifier); | |||
@@ -63,8 +46,6 @@ export default function ComponentBreadcrumbs({ | |||
<div className="component-name text-ellipsis"> | |||
<QualifierIcon className="spacer-right" qualifier={issue.componentQualifier} /> | |||
{displayOrganization && <Organization link={false} organizationKey={issue.organization} />} | |||
{displayProject && ( | |||
<span title={issue.projectName}> | |||
{limitComponentName(issue.projectName)} |
@@ -33,7 +33,6 @@ interface Props { | |||
onIssueClick: (issueKey: string) => void; | |||
onPopupToggle: (issue: string, popupName: string, open?: boolean) => void; | |||
openPopup: { issue: string; name: string } | undefined; | |||
organization: { key: string } | undefined; | |||
selectedIssue: T.Issue | undefined; | |||
} | |||
@@ -85,7 +84,6 @@ export default class IssuesList extends React.PureComponent<Props, State> { | |||
onFilterChange={this.props.onFilterChange} | |||
onPopupToggle={this.props.onPopupToggle} | |||
openPopup={openPopup && openPopup.issue === issue.key ? openPopup.name : undefined} | |||
organization={this.props.organization} | |||
previousIssue={index > 0 ? issues[index - 1] : undefined} | |||
selected={selectedIssue != null && selectedIssue.key === issue.key} | |||
/> |
@@ -34,7 +34,6 @@ interface Props { | |||
onFilterChange: (changes: Partial<Query>) => void; | |||
onPopupToggle: (issue: string, popupName: string, open?: boolean) => void; | |||
openPopup: string | undefined; | |||
organization: { key: string } | undefined; | |||
previousIssue: T.Issue | undefined; | |||
selected: boolean; | |||
} | |||
@@ -99,11 +98,7 @@ export default class ListItem extends React.PureComponent<Props> { | |||
<div className="issues-workspace-list-item"> | |||
{displayComponent && ( | |||
<div className="issues-workspace-list-component note"> | |||
<ComponentBreadcrumbs | |||
component={component} | |||
issue={this.props.issue} | |||
organization={this.props.organization} | |||
/> | |||
<ComponentBreadcrumbs component={component} issue={this.props.issue} /> | |||
</div> | |||
)} | |||
<Issue |
@@ -71,7 +71,7 @@ const ISSUES = [ | |||
const FACETS = [{ property: 'severities', values: [{ val: 'MINOR', count: 4 }] }]; | |||
const PAGING = { pageIndex: 1, pageSize: 100, total: 4 }; | |||
const referencedComponent = { key: 'foo-key', name: 'bar', organization: 'John', uuid: 'foo-uuid' }; | |||
const referencedComponent = { key: 'foo-key', name: 'bar', uuid: 'foo-uuid' }; | |||
it('should render a list of issue', async () => { | |||
const wrapper = shallowRender(); | |||
@@ -393,13 +393,12 @@ it('should handle createAfter query param with time', async () => { | |||
wrapper.instance().fetchIssues({}); | |||
expect(fetchIssues).toBeCalledWith( | |||
expect.objectContaining({ createdAfter: '2020-10-21T17:21:00+0000' }), | |||
false | |||
expect.objectContaining({ createdAfter: '2020-10-21T17:21:00+0000' }) | |||
); | |||
}); | |||
function fetchIssuesMockFactory(keyCount = 0, lineCount = 1) { | |||
return jest.fn().mockImplementation(({ p }: any) => | |||
return jest.fn().mockImplementation(({ p }: { p: number }) => | |||
Promise.resolve({ | |||
components: [referencedComponent], | |||
effortTotal: 1, | |||
@@ -439,7 +438,6 @@ function shallowRender(props: Partial<App['props']> = {}) { | |||
breadcrumbs: [], | |||
key: 'foo', | |||
name: 'bar', | |||
organization: 'John', | |||
qualifier: 'Doe' | |||
}} | |||
currentUser={mockLoggedInUser()} | |||
@@ -456,9 +454,7 @@ function shallowRender(props: Partial<App['props']> = {}) { | |||
})} | |||
location={mockLocation({ pathname: '/issues', query: {} })} | |||
onBranchesChange={() => {}} | |||
organization={{ key: 'foo' }} | |||
router={mockRouter()} | |||
userOrganizations={[]} | |||
{...props} | |||
/> | |||
); |
@@ -20,15 +20,16 @@ | |||
import { shallow } from 'enzyme'; | |||
import * as React from 'react'; | |||
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; | |||
import { searchIssueTags } from '../../../../api/issues'; | |||
import { mockIssue } from '../../../../helpers/testMocks'; | |||
import BulkChangeModal, { MAX_PAGE_SIZE } from '../BulkChangeModal'; | |||
jest.mock('../../../../api/issues', () => ({ | |||
searchIssueTags: () => Promise.resolve([undefined, []]) | |||
searchIssueTags: jest.fn().mockResolvedValue([undefined, []]) | |||
})); | |||
jest.mock('../BulkChangeModal', () => { | |||
const mock = require.requireActual('../BulkChangeModal'); | |||
const mock = jest.requireActual('../BulkChangeModal'); | |||
mock.MAX_PAGE_SIZE = 1; | |||
return mock; | |||
}); | |||
@@ -92,6 +93,12 @@ it('should properly handle the search for assignee', async () => { | |||
expect(result).toMatchSnapshot(); | |||
}); | |||
it('should properly handle the search for tags', async () => { | |||
const wrapper = getWrapper([]); | |||
await wrapper.instance().handleTagsSearch('query'); | |||
expect(searchIssueTags).toBeCalled(); | |||
}); | |||
const getWrapper = (issues: T.Issue[]) => { | |||
return shallow<BulkChangeModal>( | |||
<BulkChangeModal | |||
@@ -109,7 +116,6 @@ const getWrapper = (issues: T.Issue[]) => { | |||
} | |||
onClose={() => {}} | |||
onDone={() => {}} | |||
organization={undefined} | |||
/> | |||
); | |||
}; |
@@ -19,31 +19,25 @@ | |||
*/ | |||
import { shallow } from 'enzyme'; | |||
import * as React from 'react'; | |||
import { mockIssue } from '../../../../helpers/testMocks'; | |||
import { ComponentQualifier } from '../../../../types/component'; | |||
import ComponentBreadcrumbs from '../ComponentBreadcrumbs'; | |||
const baseIssue = { | |||
const baseIssue = mockIssue(false, { | |||
component: 'comp', | |||
componentLongName: 'comp-name', | |||
componentQualifier: ComponentQualifier.File, | |||
flows: [], | |||
organization: 'org', | |||
project: 'proj', | |||
projectName: 'proj-name', | |||
secondaryLocations: [] | |||
}; | |||
projectName: 'proj-name' | |||
}); | |||
it('renders', () => { | |||
expect( | |||
shallow( | |||
<ComponentBreadcrumbs component={undefined} issue={baseIssue} organization={undefined} /> | |||
) | |||
shallow(<ComponentBreadcrumbs component={undefined} issue={baseIssue} />) | |||
).toMatchSnapshot(); | |||
}); | |||
it('renders with sub-project', () => { | |||
const issue = { ...baseIssue, subProject: 'sub-proj', subProjectName: 'sub-proj-name' }; | |||
expect( | |||
shallow(<ComponentBreadcrumbs component={undefined} issue={issue} organization={undefined} />) | |||
).toMatchSnapshot(); | |||
expect(shallow(<ComponentBreadcrumbs component={undefined} issue={issue} />)).toMatchSnapshot(); | |||
}); |
@@ -46,7 +46,6 @@ function shallowRender(overrides: Partial<IssuesList['props']> = {}) { | |||
onIssueClick={jest.fn()} | |||
onPopupToggle={jest.fn()} | |||
openPopup={undefined} | |||
organization={undefined} | |||
selectedIssue={undefined} | |||
{...overrides} | |||
/> |
@@ -103,7 +103,6 @@ exports[`should switch to source view if an issue is selected 1`] = ` | |||
"breadcrumbs": Array [], | |||
"key": "foo", | |||
"name": "bar", | |||
"organization": "John", | |||
"qualifier": "Doe", | |||
} | |||
} | |||
@@ -121,11 +120,9 @@ exports[`should switch to source view if an issue is selected 1`] = ` | |||
"key": "foo", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -152,11 +149,9 @@ exports[`should switch to source view if an issue is selected 1`] = ` | |||
"key": "bar", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -233,11 +228,9 @@ exports[`should switch to source view if an issue is selected 1`] = ` | |||
"key": "third", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ | |||
@@ -283,11 +276,9 @@ exports[`should switch to source view if an issue is selected 1`] = ` | |||
"key": "fourth", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -309,11 +300,6 @@ exports[`should switch to source view if an issue is selected 1`] = ` | |||
onIssueCheck={[Function]} | |||
onIssueClick={[Function]} | |||
onPopupToggle={[Function]} | |||
organization={ | |||
Object { | |||
"key": "foo", | |||
} | |||
} | |||
selectedIssue={ | |||
Object { | |||
"actions": Array [], | |||
@@ -327,11 +313,9 @@ exports[`should switch to source view if an issue is selected 1`] = ` | |||
"key": "foo", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -403,11 +387,9 @@ exports[`should switch to source view if an issue is selected 2`] = ` | |||
"key": "foo", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -434,11 +416,9 @@ exports[`should switch to source view if an issue is selected 2`] = ` | |||
"key": "bar", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -515,11 +495,9 @@ exports[`should switch to source view if an issue is selected 2`] = ` | |||
"key": "third", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ | |||
@@ -565,11 +543,9 @@ exports[`should switch to source view if an issue is selected 2`] = ` | |||
"key": "fourth", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -654,11 +630,9 @@ exports[`should switch to source view if an issue is selected 2`] = ` | |||
"key": "third", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ |
@@ -8,10 +8,6 @@ exports[`renders 1`] = ` | |||
className="spacer-right" | |||
qualifier="FIL" | |||
/> | |||
<Connect(Organization) | |||
link={false} | |||
organizationKey="org" | |||
/> | |||
<span | |||
title="proj-name" | |||
> | |||
@@ -36,10 +32,6 @@ exports[`renders with sub-project 1`] = ` | |||
className="spacer-right" | |||
qualifier="FIL" | |||
/> | |||
<Connect(Organization) | |||
link={false} | |||
organizationKey="org" | |||
/> | |||
<span | |||
title="proj-name" | |||
> |
@@ -25,11 +25,9 @@ exports[`should render correctly 2`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -68,11 +66,9 @@ exports[`should render correctly 2`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN3", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -107,11 +103,9 @@ exports[`should render correctly 2`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], |
@@ -77,11 +77,9 @@ exports[`should render CrossComponentSourceViewer correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ | |||
@@ -180,11 +178,9 @@ exports[`should render CrossComponentSourceViewer correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ |
@@ -32,11 +32,9 @@ const issue: T.Issue = { | |||
fromHotspot: false, | |||
key: '', | |||
message: '', | |||
organization: '', | |||
project: '', | |||
projectKey: '', | |||
projectName: '', | |||
projectOrganization: '', | |||
rule: '', | |||
ruleName: '', | |||
secondaryLocations: [], |
@@ -18,11 +18,9 @@ exports[`should render 1`] = ` | |||
"fromHotspot": false, | |||
"key": "", | |||
"message": "", | |||
"organization": "", | |||
"project": "", | |||
"projectKey": "", | |||
"projectName": "", | |||
"projectOrganization": "", | |||
"rule": "", | |||
"ruleName": "", | |||
"secondaryLocations": Array [], |
@@ -33,11 +33,9 @@ exports[`should render correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -71,11 +69,9 @@ exports[`should render correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -110,11 +106,9 @@ exports[`should render correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -217,11 +211,9 @@ exports[`should render correctly 2`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ | |||
@@ -324,11 +316,9 @@ exports[`should render correctly 2`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ | |||
@@ -432,11 +422,9 @@ exports[`should render correctly 2`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ |
@@ -40,11 +40,9 @@ exports[`should render flow locations in different file 1`] = ` | |||
"key": "", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -211,11 +209,9 @@ exports[`should render taint analysis issues correctly 1`] = ` | |||
"key": "", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], |
@@ -111,11 +111,9 @@ exports[`should render correctly 2`] = ` | |||
"key": "1", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ |
@@ -24,7 +24,8 @@ import { highlightTerm } from 'sonar-ui-common/helpers/search'; | |||
import ListStyleFacet from '../../../components/facet/ListStyleFacet'; | |||
import Avatar from '../../../components/ui/Avatar'; | |||
import { isUserActive } from '../../../helpers/users'; | |||
import { Facet, Query, searchAssignees } from '../utils'; | |||
import { Facet } from '../../../types/issues'; | |||
import { Query, searchAssignees } from '../utils'; | |||
interface Props { | |||
assigned: boolean; |
@@ -23,7 +23,8 @@ import { translate } from 'sonar-ui-common/helpers/l10n'; | |||
import { highlightTerm } from 'sonar-ui-common/helpers/search'; | |||
import { searchIssueAuthors } from '../../../api/issues'; | |||
import ListStyleFacet from '../../../components/facet/ListStyleFacet'; | |||
import { Facet, Query } from '../utils'; | |||
import { Facet } from '../../../types/issues'; | |||
import { Query } from '../utils'; | |||
interface Props { | |||
component: T.Component | undefined; | |||
@@ -32,7 +33,6 @@ interface Props { | |||
onChange: (changes: Partial<Query>) => void; | |||
onToggle: (property: string) => void; | |||
open: boolean; | |||
organization: string | undefined; | |||
query: Query; | |||
stats: T.Dict<number> | undefined; | |||
authors: string[]; | |||
@@ -50,7 +50,6 @@ export default class AuthorFacet extends React.PureComponent<Props> { | |||
const project = | |||
component && ['TRK', 'VW', 'APP'].includes(component.qualifier) ? component.key : undefined; | |||
return searchIssueAuthors({ | |||
organization: this.props.organization, | |||
project, | |||
ps: SEARCH_SIZE, // maximum | |||
q: query |
@@ -28,7 +28,8 @@ import ListStyleFacet from '../../../components/facet/ListStyleFacet'; | |||
import { getBranchLikeQuery } from '../../../helpers/branch-like'; | |||
import { BranchLike } from '../../../types/branch-like'; | |||
import { TreeComponentWithPath } from '../../../types/component'; | |||
import { Facet, Query } from '../utils'; | |||
import { Facet } from '../../../types/issues'; | |||
import { Query } from '../utils'; | |||
interface Props { | |||
branchLike?: BranchLike; |
@@ -29,7 +29,8 @@ import ListStyleFacet from '../../../components/facet/ListStyleFacet'; | |||
import { getBranchLikeQuery } from '../../../helpers/branch-like'; | |||
import { BranchLike } from '../../../types/branch-like'; | |||
import { TreeComponentWithPath } from '../../../types/component'; | |||
import { Facet, Query } from '../utils'; | |||
import { Facet } from '../../../types/issues'; | |||
import { Query } from '../utils'; | |||
interface Props { | |||
branchLike?: BranchLike; |
@@ -24,7 +24,8 @@ import { translate } from 'sonar-ui-common/helpers/l10n'; | |||
import { highlightTerm } from 'sonar-ui-common/helpers/search'; | |||
import ListStyleFacet from '../../../components/facet/ListStyleFacet'; | |||
import { getLanguages, Store } from '../../../store/rootReducer'; | |||
import { Facet, Query, ReferencedLanguage } from '../utils'; | |||
import { Facet, ReferencedLanguage } from '../../../types/issues'; | |||
import { Query } from '../utils'; | |||
interface InstalledLanguage { | |||
key: string; |
@@ -25,7 +25,8 @@ import { highlightTerm } from 'sonar-ui-common/helpers/search'; | |||
import { getTree, searchProjects } from '../../../api/components'; | |||
import ListStyleFacet from '../../../components/facet/ListStyleFacet'; | |||
import { ComponentQualifier } from '../../../types/component'; | |||
import { Facet, Query, ReferencedComponent } from '../utils'; | |||
import { Facet, ReferencedComponent } from '../../../types/issues'; | |||
import { Query } from '../utils'; | |||
interface Props { | |||
component: T.Component | undefined; |
@@ -22,7 +22,8 @@ import * as React from 'react'; | |||
import { translate } from 'sonar-ui-common/helpers/l10n'; | |||
import { searchRules } from '../../../api/rules'; | |||
import ListStyleFacet from '../../../components/facet/ListStyleFacet'; | |||
import { Facet, Query, ReferencedRule } from '../utils'; | |||
import { Facet, ReferencedRule } from '../../../types/issues'; | |||
import { Query } from '../utils'; | |||
interface Props { | |||
fetching: boolean; | |||
@@ -31,7 +32,6 @@ interface Props { | |||
onChange: (changes: Partial<Query>) => void; | |||
onToggle: (property: string) => void; | |||
open: boolean; | |||
organization: string | undefined; | |||
query: Query; | |||
referencedRules: T.Dict<ReferencedRule>; | |||
rules: string[]; | |||
@@ -40,11 +40,10 @@ interface Props { | |||
export default class RuleFacet extends React.PureComponent<Props> { | |||
handleSearch = (query: string, page = 1) => { | |||
const { languages, organization } = this.props; | |||
const { languages } = this.props; | |||
return searchRules({ | |||
f: 'name,langName', | |||
languages: languages.length ? languages.join() : undefined, | |||
organization, | |||
q: query, | |||
p: page, | |||
ps: 30, |
@@ -22,7 +22,13 @@ import { connect } from 'react-redux'; | |||
import { getGlobalSettingValue, Store } from '../../../store/rootReducer'; | |||
import { BranchLike } from '../../../types/branch-like'; | |||
import { ComponentQualifier } from '../../../types/component'; | |||
import { Facet, Query, ReferencedComponent, ReferencedLanguage, ReferencedRule } from '../utils'; | |||
import { | |||
Facet, | |||
ReferencedComponent, | |||
ReferencedLanguage, | |||
ReferencedRule | |||
} from '../../../types/issues'; | |||
import { Query } from '../utils'; | |||
import AssigneeFacet from './AssigneeFacet'; | |||
import AuthorFacet from './AuthorFacet'; | |||
import CreationDateFacet from './CreationDateFacet'; | |||
@@ -44,14 +50,12 @@ export interface Props { | |||
component: T.Component | undefined; | |||
createdAfterIncludesTime: boolean; | |||
facets: T.Dict<Facet | undefined>; | |||
hideAuthorFacet?: boolean; | |||
loadSearchResultCount: (property: string, changes: Partial<Query>) => Promise<Facet>; | |||
loadingFacets: T.Dict<boolean>; | |||
myIssues: boolean; | |||
onFacetToggle: (property: string) => void; | |||
onFilterChange: (changes: Partial<Query>) => void; | |||
openFacets: T.Dict<boolean>; | |||
organization: { key: string } | undefined; | |||
query: Query; | |||
referencedComponentsById: T.Dict<ReferencedComponent>; | |||
referencedComponentsByKey: T.Dict<ReferencedComponent>; | |||
@@ -99,22 +103,11 @@ export class Sidebar extends React.PureComponent<Props> { | |||
} | |||
render() { | |||
const { | |||
component, | |||
createdAfterIncludesTime, | |||
facets, | |||
hideAuthorFacet, | |||
openFacets, | |||
query | |||
} = this.props; | |||
const { component, createdAfterIncludesTime, facets, openFacets, query } = this.props; | |||
const displayProjectsFacet = | |||
!component || !['TRK', 'BRC', 'DIR', 'DEV_PRJ'].includes(component.qualifier); | |||
const displayAuthorFacet = !hideAuthorFacet && (!component || component.qualifier !== 'DEV'); | |||
const organizationKey = | |||
(component && component.organization) || | |||
(this.props.organization && this.props.organization.key); | |||
const displayAuthorFacet = !component || component.qualifier !== 'DEV'; | |||
return ( | |||
<> | |||
@@ -214,7 +207,6 @@ export class Sidebar extends React.PureComponent<Props> { | |||
onChange={this.props.onFilterChange} | |||
onToggle={this.props.onFacetToggle} | |||
open={!!openFacets.rules} | |||
organization={organizationKey} | |||
query={query} | |||
referencedRules={this.props.referencedRules} | |||
rules={query.rules} | |||
@@ -227,7 +219,6 @@ export class Sidebar extends React.PureComponent<Props> { | |||
onChange={this.props.onFilterChange} | |||
onToggle={this.props.onFacetToggle} | |||
open={!!openFacets.tags} | |||
organization={organizationKey} | |||
query={query} | |||
stats={facets.tags} | |||
tags={query.tags} | |||
@@ -270,7 +261,6 @@ export class Sidebar extends React.PureComponent<Props> { | |||
onChange={this.props.onFilterChange} | |||
onToggle={this.props.onFacetToggle} | |||
open={!!openFacets.authors} | |||
organization={organizationKey} | |||
query={query} | |||
stats={facets.authors} | |||
/> |
@@ -34,8 +34,9 @@ import { | |||
renderSansTop25Category, | |||
renderSonarSourceSecurityCategory | |||
} from '../../../helpers/security-standard'; | |||
import { Facet } from '../../../types/issues'; | |||
import { SecurityStandard, Standards, StandardType } from '../../../types/security'; | |||
import { Facet, formatFacetStat, Query, STANDARDS } from '../utils'; | |||
import { formatFacetStat, Query, STANDARDS } from '../utils'; | |||
interface Props { | |||
cwe: string[]; |
@@ -25,7 +25,8 @@ import { highlightTerm } from 'sonar-ui-common/helpers/search'; | |||
import { searchIssueTags } from '../../../api/issues'; | |||
import { colors } from '../../../app/theme'; | |||
import ListStyleFacet from '../../../components/facet/ListStyleFacet'; | |||
import { Facet, Query } from '../utils'; | |||
import { Facet } from '../../../types/issues'; | |||
import { Query } from '../utils'; | |||
interface Props { | |||
component: T.Component | undefined; | |||
@@ -34,7 +35,6 @@ interface Props { | |||
onChange: (changes: Partial<Query>) => void; | |||
onToggle: (property: string) => void; | |||
open: boolean; | |||
organization: string | undefined; | |||
query: Query; | |||
stats: T.Dict<number> | undefined; | |||
tags: string[]; | |||
@@ -48,7 +48,6 @@ export default class TagFacet extends React.PureComponent<Props> { | |||
const project = | |||
component && ['TRK', 'VW', 'APP'].includes(component.qualifier) ? component.key : undefined; | |||
return searchIssueTags({ | |||
organization: this.props.organization, | |||
project, | |||
ps: SEARCH_SIZE, | |||
q: query |
@@ -23,7 +23,8 @@ import * as React from 'react'; | |||
import { getTree, searchProjects } from '../../../../api/components'; | |||
import { mockComponent } from '../../../../helpers/testMocks'; | |||
import { ComponentQualifier } from '../../../../types/component'; | |||
import { Query, ReferencedComponent } from '../../utils'; | |||
import { ReferencedComponent } from '../../../../types/issues'; | |||
import { Query } from '../../utils'; | |||
import ProjectFacet from '../ProjectFacet'; | |||
jest.mock('../../../../api/components', () => ({ | |||
@@ -31,7 +32,6 @@ jest.mock('../../../../api/components', () => ({ | |||
searchProjects: jest.fn().mockResolvedValue({ | |||
components: [], | |||
facets: [], | |||
organizations: [], | |||
paging: {} | |||
}) | |||
})); | |||
@@ -77,8 +77,8 @@ it('should handle search for projects in portfolio', async () => { | |||
describe("ListStyleFacet's renderers", () => { | |||
const components: ReferencedComponent[] = [ | |||
{ key: 'projectKey', name: 'First Project Name', organization: '', uuid: '141324' }, | |||
{ key: 'projectKey2', name: 'Second Project Name', organization: '', uuid: '643878' } | |||
{ key: 'projectKey', name: 'First Project Name', uuid: '141324' }, | |||
{ key: 'projectKey2', name: 'Second Project Name', uuid: '643878' } | |||
]; | |||
const referencedComponents = keyBy(components, c => c.key); | |||
const wrapper = shallowRender({ referencedComponents }); |
@@ -0,0 +1,80 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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 { shallow } from 'enzyme'; | |||
import * as React from 'react'; | |||
import { searchRules } from '../../../../api/rules'; | |||
import { mockReferencedRule } from '../../../../helpers/mocks/issues'; | |||
import { mockRule } from '../../../../helpers/testMocks'; | |||
import { Query } from '../../utils'; | |||
import RuleFacet from '../RuleFacet'; | |||
jest.mock('../../../../api/rules', () => ({ | |||
searchRules: jest.fn().mockResolvedValue({}) | |||
})); | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
}); | |||
it('should handle search', async () => { | |||
const wrapper = shallowRender(); | |||
const query = 'query'; | |||
await wrapper.instance().handleSearch(query); | |||
expect(searchRules).toBeCalledWith(expect.objectContaining({ languages: 'js,java', q: query })); | |||
}); | |||
describe('ListStyleFacet Renderers', () => { | |||
const referencedRules = { r1: mockReferencedRule() }; | |||
const instance = shallowRender({ referencedRules }).instance(); | |||
it('should include renderFacetItem', () => { | |||
const rule = referencedRules.r1; | |||
expect(instance.getRuleName('r1')).toBe(`(${rule.langName}) ${rule.name}`); | |||
expect(instance.getRuleName('nonexistent')).toBe('nonexistent'); | |||
}); | |||
it('should include renderSearchResult', () => { | |||
const rule = mockRule(); | |||
expect(instance.renderSearchResult(rule)).toBe(`(${rule.langName}) ${rule.name}`); | |||
expect(instance.renderSearchResult(mockRule({ langName: '' }))).toBe(rule.name); | |||
}); | |||
}); | |||
function shallowRender(props: Partial<RuleFacet['props']> = {}) { | |||
return shallow<RuleFacet>( | |||
<RuleFacet | |||
fetching={true} | |||
languages={['js', 'java']} | |||
loadSearchResultCount={jest.fn()} | |||
onChange={jest.fn()} | |||
onToggle={jest.fn()} | |||
open={false} | |||
query={{} as Query} | |||
referencedRules={{}} | |||
rules={['r1']} | |||
stats={{}} | |||
{...props} | |||
/> | |||
); | |||
} |
@@ -85,7 +85,6 @@ const renderSidebar = (props?: Partial<Sidebar['props']>) => { | |||
onFacetToggle={jest.fn()} | |||
onFilterChange={jest.fn()} | |||
openFacets={{}} | |||
organization={undefined} | |||
query={{ types: [''] } as Query} | |||
referencedComponentsById={{}} | |||
referencedComponentsByKey={{}} |
@@ -0,0 +1,30 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should render correctly 1`] = ` | |||
<ListStyleFacet | |||
facetHeader="issues.facet.rules" | |||
fetching={true} | |||
getFacetItemText={[Function]} | |||
getSearchResultKey={[Function]} | |||
getSearchResultText={[Function]} | |||
loadSearchResultCount={[Function]} | |||
maxInitialItems={15} | |||
maxItems={100} | |||
minSearchLength={2} | |||
onChange={[MockFunction]} | |||
onSearch={[Function]} | |||
onToggle={[MockFunction]} | |||
open={false} | |||
property="rules" | |||
query={Object {}} | |||
renderFacetItem={[Function]} | |||
renderSearchResult={[Function]} | |||
searchPlaceholder="search.search_for_rules" | |||
stats={Object {}} | |||
values={ | |||
Array [ | |||
"r1", | |||
] | |||
} | |||
/> | |||
`; |
@@ -32,6 +32,7 @@ import { | |||
import { scrollToElement } from 'sonar-ui-common/helpers/scrolling'; | |||
import { get, save } from 'sonar-ui-common/helpers/storage'; | |||
import { searchUsers } from '../../api/users'; | |||
import { Facet, RawFacet } from '../../types/issues'; | |||
import { SecurityStandard, StandardType } from '../../types/security'; | |||
export interface Query { | |||
@@ -150,15 +151,6 @@ export function serializeQuery(query: Query): T.RawQuery { | |||
export const areQueriesEqual = (a: T.RawQuery, b: T.RawQuery) => | |||
queriesEqual(parseQuery(a), parseQuery(b)); | |||
export interface RawFacet { | |||
property: string; | |||
values: Array<{ val: string; count: number }>; | |||
} | |||
export interface Facet { | |||
[value: string]: number; | |||
} | |||
export function mapFacet(facet: string) { | |||
const propertyMapping: T.Dict<string> = { | |||
modules: 'moduleUuids' | |||
@@ -192,23 +184,6 @@ export function formatFacetStat(stat: number | undefined) { | |||
return stat && formatMeasure(stat, 'SHORT_INT'); | |||
} | |||
export interface ReferencedComponent { | |||
key: string; | |||
name: string; | |||
organization: string; | |||
path?: string; | |||
uuid: string; | |||
} | |||
export interface ReferencedLanguage { | |||
name: string; | |||
} | |||
export interface ReferencedRule { | |||
langName?: string; | |||
name: string; | |||
} | |||
export const searchAssignees = ( | |||
query: string, | |||
page = 1 |
@@ -84,11 +84,9 @@ exports[`should render correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -120,11 +118,9 @@ exports[`should render correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], |
@@ -32,10 +32,8 @@ const issueBase: T.Issue = { | |||
flows: [], | |||
fromHotspot: false, | |||
message: '', | |||
organization: '', | |||
project: '', | |||
projectName: '', | |||
projectOrganization: '', | |||
projectKey: '', | |||
rule: '', | |||
ruleName: '', |
@@ -65,11 +65,9 @@ exports[`should render correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -96,11 +94,9 @@ exports[`should render correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -207,11 +203,9 @@ exports[`should render correctly for last, new, and highlighted lines 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -238,11 +232,9 @@ exports[`should render correctly for last, new, and highlighted lines 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -364,11 +356,9 @@ exports[`should render correctly with coverage 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -395,11 +385,9 @@ exports[`should render correctly with coverage 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -567,11 +555,9 @@ exports[`should render correctly with duplication information 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -598,11 +584,9 @@ exports[`should render correctly with duplication information 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -694,11 +678,9 @@ exports[`should render correctly with issues info 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -725,11 +707,9 @@ exports[`should render correctly with issues info 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -789,11 +769,9 @@ exports[`should render correctly with issues info 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -820,11 +798,9 @@ exports[`should render correctly with issues info 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -916,11 +892,9 @@ exports[`should render correctly: no SCM 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -947,11 +921,9 @@ exports[`should render correctly: no SCM 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], |
@@ -64,11 +64,9 @@ exports[`render code 1`] = ` | |||
"key": "issue-1", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -95,11 +93,9 @@ exports[`render code 1`] = ` | |||
"key": "issue-2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], |
@@ -17,11 +17,9 @@ exports[`render issues list 1`] = ` | |||
"fromHotspot": false, | |||
"key": "foo", | |||
"message": "", | |||
"organization": "", | |||
"project": "", | |||
"projectKey": "", | |||
"projectName": "", | |||
"projectOrganization": "", | |||
"rule": "", | |||
"ruleName": "", | |||
"secondaryLocations": Array [], | |||
@@ -50,11 +48,9 @@ exports[`render issues list 1`] = ` | |||
"fromHotspot": false, | |||
"key": "bar", | |||
"message": "", | |||
"organization": "", | |||
"project": "", | |||
"projectKey": "", | |||
"projectName": "", | |||
"projectOrganization": "", | |||
"rule": "", | |||
"ruleName": "", | |||
"secondaryLocations": Array [], |
@@ -22,11 +22,9 @@ exports[`should render hotspots correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -58,11 +56,9 @@ exports[`should render hotspots correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -121,11 +117,9 @@ exports[`should render issues correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -171,11 +165,9 @@ exports[`should render issues correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], |
@@ -17,9 +17,9 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { IssueResponse } from '../../api/issues'; | |||
import throwGlobalError from '../../app/utils/throwGlobalError'; | |||
import { parseIssueFromResponse } from '../../helpers/issues'; | |||
import { IssueResponse } from '../../types/issues'; | |||
export const updateIssue = ( | |||
onChange: (issue: T.Issue) => void, |
@@ -19,7 +19,7 @@ | |||
*/ | |||
import * as React from 'react'; | |||
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; | |||
import { IssueResponse } from '../../../api/issues'; | |||
import { IssueResponse } from '../../../types/issues'; | |||
import { updateIssue } from '../actions'; | |||
import IssueAssign from './IssueAssign'; | |||
import IssueCommentAction from './IssueCommentAction'; |
@@ -27,10 +27,7 @@ import SetAssigneePopup from '../popups/SetAssigneePopup'; | |||
interface Props { | |||
isOpen: boolean; | |||
issue: Pick< | |||
T.Issue, | |||
'assignee' | 'assigneeActive' | 'assigneeAvatar' | 'assigneeName' | 'projectOrganization' | |||
>; | |||
issue: T.Issue; | |||
canAssign: boolean; | |||
onAssign: (login: string) => void; | |||
togglePopup: (popup: string, show?: boolean) => void; | |||
@@ -80,7 +77,7 @@ export default class IssueAssign extends React.PureComponent<Props> { | |||
closeOnEscape={true} | |||
onRequestClose={this.handleClose} | |||
open={this.props.isOpen && this.props.canAssign} | |||
overlay={<SetAssigneePopup issue={this.props.issue} onSelect={this.props.onAssign} />}> | |||
overlay={<SetAssigneePopup onSelect={this.props.onAssign} />}> | |||
<ButtonLink | |||
className="issue-action issue-action-with-options js-issue-assign" | |||
onClick={this.toggleAssign}> |
@@ -31,21 +31,12 @@ export interface IssueMessageProps { | |||
manualVulnerability: boolean; | |||
message: string; | |||
onOpenRule: WorkspaceContextShape['openRule']; | |||
organization: string; | |||
ruleKey: string; | |||
ruleStatus?: RuleStatus; | |||
} | |||
export default function IssueMessage(props: IssueMessageProps) { | |||
const { | |||
engine, | |||
engineName, | |||
manualVulnerability, | |||
message, | |||
organization, | |||
ruleKey, | |||
ruleStatus | |||
} = props; | |||
const { engine, engineName, manualVulnerability, message, ruleKey, ruleStatus } = props; | |||
const ruleEngine = engineName ? engineName : engine; | |||
return ( | |||
@@ -54,7 +45,11 @@ export default function IssueMessage(props: IssueMessageProps) { | |||
<ButtonLink | |||
aria-label={translate('issue.why_this_issue.long')} | |||
className="issue-see-rule spacer-right text-baseline" | |||
onClick={() => props.onOpenRule({ key: ruleKey, organization })}> | |||
onClick={() => | |||
props.onOpenRule({ | |||
key: ruleKey | |||
}) | |||
}> | |||
{translate('issue.why_this_issue')} | |||
</ButtonLink> | |||
@@ -21,7 +21,8 @@ import * as React from 'react'; | |||
import { ButtonLink } from 'sonar-ui-common/components/controls/buttons'; | |||
import Toggler from 'sonar-ui-common/components/controls/Toggler'; | |||
import DropdownIcon from 'sonar-ui-common/components/icons/DropdownIcon'; | |||
import { IssueResponse, setIssueSeverity } from '../../../api/issues'; | |||
import { setIssueSeverity } from '../../../api/issues'; | |||
import { IssueResponse } from '../../../types/issues'; | |||
import SeverityHelper from '../../shared/SeverityHelper'; | |||
import SetSeverityPopup from '../popups/SetSeverityPopup'; | |||
@@ -29,7 +29,7 @@ import SetIssueTagsPopup from '../popups/SetIssueTagsPopup'; | |||
interface Props { | |||
canSetTags: boolean; | |||
isOpen: boolean; | |||
issue: Pick<T.Issue, 'key' | 'projectOrganization' | 'tags'>; | |||
issue: Pick<T.Issue, 'key' | 'tags'>; | |||
onChange: (issue: T.Issue) => void; | |||
togglePopup: (popup: string, show?: boolean) => void; | |||
} | |||
@@ -64,13 +64,7 @@ export default class IssueTags extends React.PureComponent<Props> { | |||
<Toggler | |||
onRequestClose={this.handleClose} | |||
open={this.props.isOpen} | |||
overlay={ | |||
<SetIssueTagsPopup | |||
organization={issue.projectOrganization} | |||
selectedTags={tags} | |||
setTags={this.setTags} | |||
/> | |||
}> | |||
overlay={<SetIssueTagsPopup selectedTags={tags} setTags={this.setTags} />}> | |||
<ButtonLink | |||
className="issue-action issue-action-with-options js-issue-edit-tags" | |||
onClick={this.toggleSetTags}> |
@@ -84,7 +84,6 @@ export default function IssueTitleBar(props: IssueTitleBarProps) { | |||
manualVulnerability={issue.fromHotspot && issue.type === 'VULNERABILITY'} | |||
message={issue.message} | |||
onOpenRule={openRule} | |||
organization={issue.organization} | |||
ruleKey={issue.rule} | |||
ruleStatus={issue.ruleStatus as RuleStatus | undefined} | |||
/> |
@@ -23,8 +23,9 @@ import Toggler from 'sonar-ui-common/components/controls/Toggler'; | |||
import DropdownIcon from 'sonar-ui-common/components/icons/DropdownIcon'; | |||
import IssueTypeIcon from 'sonar-ui-common/components/icons/IssueTypeIcon'; | |||
import { translate } from 'sonar-ui-common/helpers/l10n'; | |||
import { IssueResponse, setIssueType } from '../../../api/issues'; | |||
import { setIssueType } from '../../../api/issues'; | |||
import { colors } from '../../../app/theme'; | |||
import { IssueResponse } from '../../../types/issues'; | |||
import SetTypePopup from '../popups/SetTypePopup'; | |||
interface Props { |
@@ -20,14 +20,14 @@ | |||
import { shallow } from 'enzyme'; | |||
import * as React from 'react'; | |||
import { click } from 'sonar-ui-common/helpers/testUtils'; | |||
import { mockIssue } from '../../../../helpers/testMocks'; | |||
import IssueAssign from '../IssueAssign'; | |||
const issue = { | |||
const issue = mockIssue(false, { | |||
assignee: 'john', | |||
assigneeAvatar: 'gravatarhash', | |||
assigneeName: 'John Doe', | |||
projectOrganization: 'org' | |||
}; | |||
assigneeName: 'John Doe' | |||
}); | |||
it('should render without the action when the correct rights are missing', () => { | |||
expect(shallowRender({ canAssign: false })).toMatchSnapshot(); | |||
@@ -38,7 +38,9 @@ it('should render with the action', () => { | |||
}); | |||
it('should render a fallback assignee display if assignee info are not available', () => { | |||
expect(shallowRender({ issue: { projectOrganization: 'org' } })).toMatchSnapshot(); | |||
expect( | |||
shallowRender({ issue: mockIssue(false, { assignee: undefined, assigneeName: undefined }) }) | |||
).toMatchSnapshot(); | |||
}); | |||
it('should open the popup when the button is clicked', () => { |
@@ -40,7 +40,9 @@ it('should handle click correctly', () => { | |||
const onOpenRule = jest.fn(); | |||
const wrapper = shallowRender({ onOpenRule }); | |||
click(wrapper.find(ButtonLink)); | |||
expect(onOpenRule).toBeCalledWith({ key: 'javascript:S1067', organization: 'myorg' }); | |||
expect(onOpenRule).toBeCalledWith({ | |||
key: 'javascript:S1067' | |||
}); | |||
}); | |||
function shallowRender(props: Partial<IssueMessageProps> = {}) { | |||
@@ -49,7 +51,6 @@ function shallowRender(props: Partial<IssueMessageProps> = {}) { | |||
manualVulnerability={false} | |||
message="Reduce the number of conditional operators (4) used in the expression" | |||
onOpenRule={jest.fn()} | |||
organization="myorg" | |||
ruleKey="javascript:S1067" | |||
{...props} | |||
/> |
@@ -28,11 +28,9 @@ exports[`should render commentable correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -73,11 +71,9 @@ exports[`should render commentable correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -118,11 +114,9 @@ exports[`should render commentable correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -163,11 +157,9 @@ exports[`should render commentable correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -219,11 +211,9 @@ exports[`should render commentable correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -274,11 +264,9 @@ exports[`should render effort correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -318,11 +306,9 @@ exports[`should render effort correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -362,11 +348,9 @@ exports[`should render effort correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -406,11 +390,9 @@ exports[`should render effort correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -463,11 +445,9 @@ exports[`should render effort correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -517,11 +497,9 @@ exports[`should render issue correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -560,11 +538,9 @@ exports[`should render issue correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -603,11 +579,9 @@ exports[`should render issue correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -646,11 +620,9 @@ exports[`should render issue correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -693,11 +665,9 @@ exports[`should render issue correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -747,11 +717,9 @@ exports[`should render security hotspot correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -790,11 +758,9 @@ exports[`should render security hotspot correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -833,11 +799,9 @@ exports[`should render security hotspot correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -880,11 +844,9 @@ exports[`should render security hotspot correctly 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], |
@@ -19,14 +19,6 @@ exports[`should open the popup when the button is clicked 2`] = ` | |||
open={true} | |||
overlay={ | |||
<Connect(withCurrentUser(SetAssigneePopup)) | |||
issue={ | |||
Object { | |||
"assignee": "john", | |||
"assigneeAvatar": "gravatarhash", | |||
"assigneeName": "John Doe", | |||
"projectOrganization": "org", | |||
} | |||
} | |||
onSelect={[MockFunction]} | |||
/> | |||
} | |||
@@ -68,11 +60,6 @@ exports[`should render a fallback assignee display if assignee info are not avai | |||
open={false} | |||
overlay={ | |||
<Connect(withCurrentUser(SetAssigneePopup)) | |||
issue={ | |||
Object { | |||
"projectOrganization": "org", | |||
} | |||
} | |||
onSelect={[MockFunction]} | |||
/> | |||
} | |||
@@ -104,14 +91,6 @@ exports[`should render with the action 1`] = ` | |||
open={false} | |||
overlay={ | |||
<Connect(withCurrentUser(SetAssigneePopup)) | |||
issue={ | |||
Object { | |||
"assignee": "john", | |||
"assigneeAvatar": "gravatarhash", | |||
"assigneeName": "John Doe", | |||
"projectOrganization": "org", | |||
} | |||
} | |||
onSelect={[MockFunction]} | |||
/> | |||
} |
@@ -18,7 +18,6 @@ exports[`should open the popup when the button is clicked 2`] = ` | |||
open={true} | |||
overlay={ | |||
<SetIssueTagsPopup | |||
organization="foo" | |||
selectedTags={ | |||
Array [ | |||
"mytag", | |||
@@ -56,7 +55,6 @@ exports[`should render with the action 1`] = ` | |||
open={false} | |||
overlay={ | |||
<SetIssueTagsPopup | |||
organization="foo" | |||
selectedTags={ | |||
Array [ | |||
"mytag", |
@@ -33,11 +33,9 @@ exports[`should render correctly: default 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -102,7 +100,6 @@ exports[`should render correctly: issue message 1`] = ` | |||
manualVulnerability={false} | |||
message="Reduce the number of conditional operators (4) used in the expression" | |||
onOpenRule={[Function]} | |||
organization="myorg" | |||
ruleKey="javascript:S1067" | |||
/> | |||
`; | |||
@@ -140,11 +137,9 @@ exports[`should render correctly: with filter 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -217,11 +212,9 @@ exports[`should render correctly: with filter 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [], | |||
@@ -328,11 +321,9 @@ exports[`should render correctly: with multi locations 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ | |||
@@ -503,11 +494,9 @@ exports[`should render correctly: with multi locations and link 1`] = ` | |||
"key": "AVsae-CQS-9G3txfbFN2", | |||
"line": 25, | |||
"message": "Reduce the number of conditional operators (4) used in the expression", | |||
"organization": "myorg", | |||
"project": "myproject", | |||
"projectKey": "foo", | |||
"projectName": "Foo", | |||
"projectOrganization": "org", | |||
"rule": "javascript:S1067", | |||
"ruleName": "foo", | |||
"secondaryLocations": Array [ |
@@ -31,7 +31,6 @@ import Avatar from '../../ui/Avatar'; | |||
interface Props { | |||
currentUser: T.CurrentUser; | |||
issue: Pick<T.Issue, 'projectOrganization'>; | |||
onSelect: (login: string) => void; | |||
} | |||
@@ -25,7 +25,6 @@ import { searchIssueTags } from '../../../api/issues'; | |||
import TagsSelector from '../../tags/TagsSelector'; | |||
interface Props { | |||
organization: string; | |||
selectedTags: string[]; | |||
setTags: (tags: string[]) => void; | |||
} | |||
@@ -35,6 +34,7 @@ interface State { | |||
} | |||
const LIST_SIZE = 10; | |||
const MAX_LIST_SIZE = 100; | |||
export default class SetIssueTagsPopup extends React.PureComponent<Props, State> { | |||
mounted = false; | |||
@@ -51,8 +51,7 @@ export default class SetIssueTagsPopup extends React.PureComponent<Props, State> | |||
onSearch = (query: string) => { | |||
return searchIssueTags({ | |||
q: query, | |||
ps: Math.min(this.props.selectedTags.length - 1 + LIST_SIZE, 100), | |||
organization: this.props.organization | |||
ps: Math.min(this.props.selectedTags.length - 1 + LIST_SIZE, MAX_LIST_SIZE) | |||
}).then( | |||
(tags: string[]) => { | |||
if (this.mounted) { |
@@ -47,11 +47,6 @@ it('should allow to search for a user on SQ', async () => { | |||
function shallowRender(props: Partial<SetAssigneePopup['props']> = {}) { | |||
return shallow( | |||
<SetAssigneePopup | |||
currentUser={mockLoggedInUser()} | |||
issue={{ projectOrganization: 'foo' }} | |||
onSelect={jest.fn()} | |||
{...props} | |||
/> | |||
<SetAssigneePopup currentUser={mockLoggedInUser()} onSelect={jest.fn()} {...props} /> | |||
); | |||
} |
@@ -22,9 +22,7 @@ import * as React from 'react'; | |||
import SetIssueTagsPopup from '../SetIssueTagsPopup'; | |||
it('should render tags popup correctly', () => { | |||
const element = shallow( | |||
<SetIssueTagsPopup organization="foo" selectedTags={['mytag']} setTags={jest.fn()} /> | |||
); | |||
const element = shallow(<SetIssueTagsPopup selectedTags={['mytag']} setTags={jest.fn()} />); | |||
element.setState({ searchResult: ['mytag', 'test', 'second'] }); | |||
expect(element).toMatchSnapshot(); | |||
}); |
@@ -79,19 +79,18 @@ it('should render correctly', () => { | |||
).toMatchSnapshot('open component'); | |||
expect( | |||
shallowRender({ | |||
rules: [{ key: 'foo', organization: 'default' }], | |||
rules: [{ key: 'foo' }], | |||
open: { rule: 'foo' } | |||
}) | |||
).toMatchSnapshot('open rule'); | |||
}); | |||
it('should correctly load data from local storage', () => { | |||
const rule1 = { [TYPE_KEY]: WorkspaceTypes.Rule, key: 'foo', organization: 'default' }; | |||
const rule1 = { [TYPE_KEY]: WorkspaceTypes.Rule, key: 'foo' }; | |||
const rule2 = { | |||
[TYPE_KEY]: WorkspaceTypes.Rule, | |||
key: 'baz', | |||
name: 'Baz', | |||
organization: 'default' | |||
name: 'Baz' | |||
}; | |||
const component = { | |||
[TYPE_KEY]: WorkspaceTypes.Component, | |||
@@ -115,7 +114,7 @@ it('should correctly load data from local storage', () => { | |||
it('should correctly store data locally', () => { | |||
const wrapper = shallowRender({ | |||
components: [{ branchLike: mockBranch(), key: 'foo' }], | |||
rules: [{ key: 'foo', organization: 'default' }] | |||
rules: [{ key: 'foo' }] | |||
}); | |||
wrapper.instance().saveWorkspace(); | |||
expect((save as jest.Mock).mock.calls[0][1]).toMatchSnapshot(); | |||
@@ -129,7 +128,7 @@ it('should load rule engine names', async () => { | |||
it('should allow elements to be loaded and updated', () => { | |||
const component = { key: 'foo', branchLike: mockBranch() }; | |||
const rule = { key: 'bar', organization: 'default' }; | |||
const rule = { key: 'bar' }; | |||
const wrapper = shallowRender({ | |||
components: [component], | |||
rules: [rule] | |||
@@ -155,7 +154,7 @@ it('should allow elements to be loaded and updated', () => { | |||
it('should be resizable', () => { | |||
(get as jest.Mock).mockReturnValue( | |||
JSON.stringify([{ [TYPE_KEY]: WorkspaceTypes.Rule, key: 'foo', organization: 'default' }]) | |||
JSON.stringify([{ [TYPE_KEY]: WorkspaceTypes.Rule, key: 'foo' }]) | |||
); | |||
const wrapper = shallowRender({ open: { rule: 'foo' } }); | |||
const instance = wrapper.instance(); | |||
@@ -180,8 +179,7 @@ it('should be resizable', () => { | |||
it('should be openable/collapsible', () => { | |||
const rule = { | |||
key: 'baz', | |||
name: 'Baz', | |||
organization: 'default' | |||
name: 'Baz' | |||
}; | |||
const component = { | |||
branchLike: mockBranch(), |
@@ -1,6 +1,6 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should correctly store data locally 1`] = `"[{\\"branchLike\\":{\\"analysisDate\\":\\"2018-01-01\\",\\"excludedFromPurge\\":true,\\"isMain\\":false,\\"name\\":\\"branch-6.7\\"},\\"key\\":\\"foo\\",\\"__type__\\":\\"component\\"},{\\"key\\":\\"foo\\",\\"organization\\":\\"default\\",\\"__type__\\":\\"rule\\"}]"`; | |||
exports[`should correctly store data locally 1`] = `"[{\\"branchLike\\":{\\"analysisDate\\":\\"2018-01-01\\",\\"excludedFromPurge\\":true,\\"isMain\\":false,\\"name\\":\\"branch-6.7\\"},\\"key\\":\\"foo\\",\\"__type__\\":\\"component\\"},{\\"key\\":\\"foo\\",\\"__type__\\":\\"rule\\"}]"`; | |||
exports[`should render correctly: default 1`] = ` | |||
<ContextProvider | |||
@@ -111,7 +111,6 @@ exports[`should render correctly: open rule 1`] = ` | |||
Array [ | |||
Object { | |||
"key": "foo", | |||
"organization": "default", | |||
}, | |||
] | |||
} | |||
@@ -127,7 +126,6 @@ exports[`should render correctly: open rule 1`] = ` | |||
rule={ | |||
Object { | |||
"key": "foo", | |||
"organization": "default", | |||
} | |||
} | |||
/> |
@@ -31,7 +31,6 @@ export interface ComponentDescriptor { | |||
export interface RuleDescriptor { | |||
key: string; | |||
name?: string; | |||
organization: string; | |||
} | |||
export interface WorkspaceContextShape { |
@@ -18,11 +18,13 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { ComponentQualifier } from '../../types/component'; | |||
import { IssueType } from '../../types/issues'; | |||
import { | |||
getComponentDrilldownUrl, | |||
getComponentIssuesUrl, | |||
getComponentOverviewUrl, | |||
getComponentSecurityHotspotsUrl, | |||
getIssuesUrl, | |||
getQualityGatesUrl, | |||
getQualityGateUrl | |||
} from '../urls'; | |||
@@ -121,3 +123,13 @@ describe('#getQualityGate(s)Url', () => { | |||
expect(getQualityGateUrl('bar')).toEqual({ pathname: '/quality_gates/show/bar' }); | |||
}); | |||
}); | |||
describe('getIssuesUrl', () => { | |||
it('should work as expected', () => { | |||
const type = IssueType.Bug; | |||
expect(getIssuesUrl({ type })).toEqual({ | |||
pathname: '/issues', | |||
query: { type } | |||
}); | |||
}); | |||
}); |
@@ -22,15 +22,10 @@ import BugIcon from 'sonar-ui-common/components/icons/BugIcon'; | |||
import CodeSmellIcon from 'sonar-ui-common/components/icons/CodeSmellIcon'; | |||
import SecurityHotspotIcon from 'sonar-ui-common/components/icons/SecurityHotspotIcon'; | |||
import VulnerabilityIcon from 'sonar-ui-common/components/icons/VulnerabilityIcon'; | |||
import { IssueType } from '../types/issues'; | |||
import { IssueType, RawIssue } from '../types/issues'; | |||
import { MetricKey } from '../types/metrics'; | |||
import { ISSUE_TYPES } from './constants'; | |||
interface Comment { | |||
login: string; | |||
[x: string]: any; | |||
} | |||
interface Rule {} | |||
interface Component { | |||
@@ -38,29 +33,6 @@ interface Component { | |||
name: string; | |||
} | |||
interface IssueBase { | |||
severity: string; | |||
[x: string]: any; | |||
} | |||
export interface RawIssue extends IssueBase { | |||
assignee?: string; | |||
author?: string; | |||
comments?: Array<Comment>; | |||
component: string; | |||
flows?: Array<{ | |||
// `componentName` is not available in RawIssue | |||
locations?: Array<T.Omit<T.FlowLocation, 'componentName'>>; | |||
}>; | |||
key: string; | |||
line?: number; | |||
project: string; | |||
rule: string; | |||
status: string; | |||
subProject?: string; | |||
textRange?: T.TextRange; | |||
} | |||
export function sortByType<T extends Pick<T.Issue, 'type'>>(issues: T[]): T[] { | |||
return sortBy(issues, issue => ISSUE_TYPES.indexOf(issue.type)); | |||
} |
@@ -0,0 +1,28 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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 { ReferencedRule } from '../../types/issues'; | |||
export function mockReferencedRule(overrides: Partial<ReferencedRule> = {}): ReferencedRule { | |||
return { | |||
langName: 'Javascript', | |||
name: 'RuleFoo', | |||
...overrides | |||
}; | |||
} |
@@ -407,11 +407,9 @@ export function mockIssue(withLocations = false, overrides: Partial<T.Issue> = { | |||
key: 'AVsae-CQS-9G3txfbFN2', | |||
line: 25, | |||
message: 'Reduce the number of conditional operators (4) used in the expression', | |||
organization: 'myorg', | |||
project: 'myproject', | |||
projectKey: 'foo', | |||
projectName: 'Foo', | |||
projectOrganization: 'org', | |||
rule: 'javascript:S1067', | |||
ruleName: 'foo', | |||
secondaryLocations: [], |
@@ -99,8 +99,8 @@ export function getPullRequestUrl(project: string, pullRequest: string): Locatio | |||
/** | |||
* Generate URL for a global issues page | |||
*/ | |||
export function getIssuesUrl(query: Query, organization?: string): Location { | |||
const pathname = organization ? `/organizations/${organization}/issues` : '/issues'; | |||
export function getIssuesUrl(query: Query): Location { | |||
const pathname = '/issues'; | |||
return { pathname, query }; | |||
} | |||
@@ -29,3 +29,85 @@ export enum IssueScope { | |||
Main = 'MAIN', | |||
Test = 'TEST' | |||
} | |||
interface Comment { | |||
login: string; | |||
[x: string]: any; | |||
} | |||
interface IssueBase { | |||
severity: string; | |||
[x: string]: any; | |||
} | |||
export interface RawIssue extends IssueBase { | |||
assignee?: string; | |||
author?: string; | |||
comments?: Array<Comment>; | |||
component: string; | |||
flows?: Array<{ | |||
// `componentName` is not available in RawIssue | |||
locations?: Array<T.Omit<T.FlowLocation, 'componentName'>>; | |||
}>; | |||
key: string; | |||
line?: number; | |||
project: string; | |||
rule: string; | |||
status: string; | |||
subProject?: string; | |||
textRange?: T.TextRange; | |||
} | |||
export interface IssueResponse { | |||
components?: Array<{ key: string; name: string }>; | |||
issue: RawIssue; | |||
rules?: Array<{}>; | |||
users?: Array<T.UserBase>; | |||
} | |||
export interface RawIssuesResponse { | |||
components: ReferencedComponent[]; | |||
effortTotal: number; | |||
facets: RawFacet[]; | |||
issues: RawIssue[]; | |||
languages: ReferencedLanguage[]; | |||
paging: T.Paging; | |||
rules?: Array<{}>; | |||
users?: Array<T.UserBase>; | |||
} | |||
export interface FetchIssuesPromise { | |||
components: ReferencedComponent[]; | |||
effortTotal: number; | |||
facets: RawFacet[]; | |||
issues: T.Issue[]; | |||
languages: ReferencedLanguage[]; | |||
paging: T.Paging; | |||
rules: ReferencedRule[]; | |||
users: T.UserBase[]; | |||
} | |||
export interface ReferencedComponent { | |||
key: string; | |||
name: string; | |||
path?: string; | |||
uuid: string; | |||
} | |||
export interface ReferencedLanguage { | |||
name: string; | |||
} | |||
export interface ReferencedRule { | |||
langName?: string; | |||
name: string; | |||
} | |||
export interface RawFacet { | |||
property: string; | |||
values: Array<{ val: string; count: number }>; | |||
} | |||
export interface Facet { | |||
[value: string]: number; | |||
} |
@@ -343,10 +343,8 @@ declare namespace T { | |||
fromHotspot: boolean; | |||
line?: number; | |||
message: string; | |||
organization: string; | |||
project: string; | |||
projectName: string; | |||
projectOrganization: string; | |||
projectKey: string; | |||
pullRequest?: string; | |||
resolution?: string; |