aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2018-09-19 16:30:22 +0200
committersonartech <sonartech@sonarsource.com>2018-10-10 09:23:05 +0200
commit33fb963df2b706520da3673e0ebd9947b768f681 (patch)
tree807051984b9ad0218072204585be77221a60cac4
parent783e6e08ecc839b4a330e20852e3f7a427777832 (diff)
downloadsonarqube-33fb963df2b706520da3673e0ebd9947b768f681.tar.gz
sonarqube-33fb963df2b706520da3673e0ebd9947b768f681.zip
SONAR-11260 Use WS api/ce/analysis_status to display warnings in dashboard
-rw-r--r--server/sonar-web/src/main/js/api/ce.ts17
-rw-r--r--server/sonar-web/src/main/js/app/components/ComponentContainer.tsx19
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx3
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx16
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/ComponentNavWarnings.tsx7
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMeta-test.tsx3
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavWarnings-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap1
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavWarnings-test.tsx.snap8
-rw-r--r--server/sonar-web/src/main/js/components/common/AnalysisWarningsModal.tsx27
-rw-r--r--server/sonar-web/src/main/js/components/common/__tests__/AnalysisWarningsModal-test.tsx20
-rw-r--r--server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/AnalysisWarningsModal-test.tsx.snap60
14 files changed, 154 insertions, 31 deletions
diff --git a/server/sonar-web/src/main/js/api/ce.ts b/server/sonar-web/src/main/js/api/ce.ts
index 3762ec76e1c..6b6476a2798 100644
--- a/server/sonar-web/src/main/js/api/ce.ts
+++ b/server/sonar-web/src/main/js/api/ce.ts
@@ -21,6 +21,23 @@ import { getJSON, post, RequestData } from '../helpers/request';
import throwGlobalError from '../app/utils/throwGlobalError';
import { Task } from '../app/types';
+export function getAnalysisStatus(data: {
+ component: string;
+ branch?: string;
+ pullRequest?: string;
+}): Promise<{
+ component: {
+ branch?: string;
+ key: string;
+ name: string;
+ organization?: string;
+ pullRequest?: string;
+ warnings: string[];
+ };
+}> {
+ return getJSON('/api/ce/analysis_status', data).catch(throwGlobalError);
+}
+
export function getActivity(data: RequestData): Promise<{ tasks: Task[] }> {
return getJSON('/api/ce/activity', data);
}
diff --git a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
index f7c488be19a..ef37ea8376e 100644
--- a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
+++ b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
@@ -26,7 +26,7 @@ import ComponentNav from './nav/component/ComponentNav';
import { Component, BranchLike, Measure, Task } from '../types';
import handleRequiredAuthorization from '../utils/handleRequiredAuthorization';
import { getBranches, getPullRequests } from '../../api/branches';
-import { getTasksForComponent } from '../../api/ce';
+import { getTasksForComponent, getAnalysisStatus } from '../../api/ce';
import { getComponentData } from '../../api/components';
import { getMeasures } from '../../api/measures';
import { getComponentNavigation } from '../../api/nav';
@@ -58,6 +58,7 @@ interface State {
isPending: boolean;
loading: boolean;
tasksInProgress?: Task[];
+ warnings: string[];
}
const FETCH_STATUS_WAIT_TIME = 3000;
@@ -72,7 +73,7 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
- this.state = { branchLikes: [], isPending: false, loading: true };
+ this.state = { branchLikes: [], isPending: false, loading: true, warnings: [] };
}
componentDidMount() {
@@ -138,6 +139,7 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
loading: false
});
this.fetchStatus(component);
+ this.fetchWarnings(component, branchLike);
}
})
.catch(onError);
@@ -254,6 +256,18 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
);
};
+ fetchWarnings = (component: Component, branchLike?: BranchLike) => {
+ getAnalysisStatus({
+ component: component.key,
+ ...getBranchLikeQuery(branchLike)
+ }).then(
+ ({ component }) => {
+ this.setState({ warnings: component.warnings });
+ },
+ () => {}
+ );
+ };
+
getCurrentBranchLike = (branchLikes: BranchLike[]) => {
const { query } = this.props.location;
return query.pullRequest
@@ -341,6 +355,7 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
isInProgress={isInProgress}
isPending={isPending}
location={this.props.location}
+ warnings={this.state.warnings}
/>
)}
{loading ? (
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
index 7d5ca616c2f..8e0d69dc235 100644
--- a/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
@@ -43,6 +43,7 @@ jest.mock('../../../api/branches', () => ({
}));
jest.mock('../../../api/ce', () => ({
+ getAnalysisStatus: jest.fn().mockResolvedValue({ component: { warnings: [] } }),
getTasksForComponent: jest.fn().mockResolvedValue({ queue: [] })
}));
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx
index 9a1332c4dcd..89561422d42 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx
@@ -39,6 +39,7 @@ interface Props {
isInProgress?: boolean;
isPending?: boolean;
location: {};
+ warnings: string[];
}
export default class ComponentNav extends React.PureComponent<Props> {
@@ -98,7 +99,7 @@ export default class ComponentNav extends React.PureComponent<Props> {
branchLike={currentBranchLike}
branchMeasures={this.props.branchMeasures}
component={component}
- currentTask={currentTask}
+ warnings={this.props.warnings}
/>
</div>
<ComponentNavMenu
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx
index f6c5487409c..217ee6d1976 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.tsx
@@ -27,8 +27,7 @@ import {
isLoggedIn,
HomePageType,
HomePage,
- Measure,
- Task
+ Measure
} from '../../../types';
import BranchMeasures from '../../../../components/common/BranchMeasures';
import BranchStatus from '../../../../components/common/BranchStatus';
@@ -54,10 +53,16 @@ interface Props extends StateProps {
branchLike?: BranchLike;
branchMeasures?: Measure[];
component: Component;
- currentTask?: Task;
+ warnings: string[];
}
-export function ComponentNavMeta({ branchLike, branchMeasures, component, currentTask, currentUser }: Props) {
+export function ComponentNavMeta({
+ branchLike,
+ branchMeasures,
+ component,
+ currentUser,
+ warnings
+}: Props) {
const mainBranch = !branchLike || isMainBranch(branchLike);
const longBranch = isLongLivingBranch(branchLike);
const currentPage = getCurrentPage(component, branchLike);
@@ -65,8 +70,7 @@ export function ComponentNavMeta({ branchLike, branchMeasures, component, curren
return (
<div className="navbar-context-meta">
- {currentTask &&
- Boolean(currentTask.warningCount) && <ComponentNavWarnings task={currentTask} />}
+ {warnings.length > 0 && <ComponentNavWarnings warnings={warnings} />}
{component.analysisDate && (
<div className="spacer-left text-ellipsis">
<DateTimeFormatter date={component.analysisDate} />
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavWarnings.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavWarnings.tsx
index 192d562afd7..a18d094080c 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavWarnings.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavWarnings.tsx
@@ -21,7 +21,6 @@ import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { lazyLoad } from '../../../../components/lazyLoad';
import WarningIcon from '../../../../components/icons-components/WarningIcon';
-import { Task } from '../../../types';
import { translate, translateWithParameters } from '../../../../helpers/l10n';
const AnalysisWarningsModal = lazyLoad(() =>
@@ -29,7 +28,7 @@ const AnalysisWarningsModal = lazyLoad(() =>
);
interface Props {
- task: Pick<Task, 'id' | 'warningCount'>;
+ warnings: string[];
}
interface State {
@@ -62,7 +61,7 @@ export default class ComponentNavWarnings extends React.PureComponent<Props, Sta
<a href="#" onClick={this.handleClick}>
{translateWithParameters(
'component_navigation.x_warnings',
- String(this.props.task.warningCount)
+ String(this.props.warnings.length)
)}
</a>
)
@@ -70,7 +69,7 @@ export default class ComponentNavWarnings extends React.PureComponent<Props, Sta
/>
</div>
{this.state.modal && (
- <AnalysisWarningsModal onClose={this.handleCloseModal} taskId={this.props.task.id} />
+ <AnalysisWarningsModal onClose={this.handleCloseModal} warnings={this.props.warnings} />
)}
</>
);
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx
index b0f633badb5..b06e39767ca 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx
@@ -36,6 +36,7 @@ it('renders', () => {
component={component}
currentBranchLike={undefined}
location={{}}
+ warnings={[]}
/>
);
wrapper.setState({ isInProgress: true, isPending: true });
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMeta-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMeta-test.tsx
index 74ad5181300..ea2e2016e25 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMeta-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMeta-test.tsx
@@ -52,6 +52,7 @@ it('renders status of short-living branch', () => {
branchMeasures={MEASURES}
component={COMPONENT}
currentUser={{ isLoggedIn: false }}
+ warnings={[]}
/>
)
).toMatchSnapshot();
@@ -70,6 +71,7 @@ it('renders meta for long-living branch', () => {
branchLike={branch}
component={COMPONENT}
currentUser={{ isLoggedIn: false }}
+ warnings={[]}
/>
)
).toMatchSnapshot();
@@ -90,6 +92,7 @@ it('renders meta for pull request', () => {
branchLike={pullRequest}
component={COMPONENT}
currentUser={{ isLoggedIn: false }}
+ warnings={[]}
/>
)
).toMatchSnapshot();
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavWarnings-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavWarnings-test.tsx
index 9eba3b71968..95c6431ba03 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavWarnings-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavWarnings-test.tsx
@@ -22,7 +22,7 @@ import { shallow } from 'enzyme';
import ComponentNavWarnings from '../ComponentNavWarnings';
it('should render', () => {
- const wrapper = shallow(<ComponentNavWarnings task={{ id: 'abcd1234' }} />);
+ const wrapper = shallow(<ComponentNavWarnings warnings={['warning 1']} />);
wrapper.setState({ modal: true });
expect(wrapper).toMatchSnapshot();
});
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap
index b95d5c4732b..3e0cf719787 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap
+++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNav-test.tsx.snap
@@ -43,6 +43,7 @@ exports[`renders 1`] = `
"qualifier": "TRK",
}
}
+ warnings={Array []}
/>
</div>
<ComponentNavMenu
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavWarnings-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavWarnings-test.tsx.snap
index 1f672b50096..02ba68a66f4 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavWarnings-test.tsx.snap
+++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavWarnings-test.tsx.snap
@@ -17,7 +17,7 @@ exports[`should render 1`] = `
href="#"
onClick={[Function]}
>
- component_navigation.x_warnings.undefined
+ component_navigation.x_warnings.1
</a>,
}
}
@@ -25,7 +25,11 @@ exports[`should render 1`] = `
</div>
<LazyLoader
onClose={[Function]}
- taskId="abcd1234"
+ warnings={
+ Array [
+ "warning 1",
+ ]
+ }
/>
</React.Fragment>
`;
diff --git a/server/sonar-web/src/main/js/components/common/AnalysisWarningsModal.tsx b/server/sonar-web/src/main/js/components/common/AnalysisWarningsModal.tsx
index 97af1814d03..b1fc7698a4f 100644
--- a/server/sonar-web/src/main/js/components/common/AnalysisWarningsModal.tsx
+++ b/server/sonar-web/src/main/js/components/common/AnalysisWarningsModal.tsx
@@ -27,7 +27,8 @@ import { getTask } from '../../api/ce';
interface Props {
onClose: () => void;
- taskId: string;
+ taskId?: string;
+ warnings?: string[];
}
interface State {
@@ -37,19 +38,25 @@ interface State {
export default class AnalysisWarningsModal extends React.PureComponent<Props, State> {
mounted = false;
- state: State = {
- loading: true,
- warnings: []
- };
+
+ constructor(props: Props) {
+ super(props);
+ this.state = { loading: !props.warnings, warnings: props.warnings || [] };
+ }
componentDidMount() {
this.mounted = true;
- this.loadWarnings();
+ if (!this.props.warnings && this.props.taskId) {
+ this.loadWarnings(this.props.taskId);
+ }
}
componentDidUpdate(prevProps: Props) {
- if (prevProps.taskId !== this.props.taskId) {
- this.loadWarnings();
+ const { taskId, warnings } = this.props;
+ if (!warnings && taskId && prevProps.taskId !== taskId) {
+ this.loadWarnings(taskId);
+ } else if (warnings && prevProps.warnings !== warnings) {
+ this.setState({ warnings });
}
}
@@ -57,9 +64,9 @@ export default class AnalysisWarningsModal extends React.PureComponent<Props, St
this.mounted = false;
}
- loadWarnings() {
+ loadWarnings(taskId: string) {
this.setState({ loading: true });
- getTask(this.props.taskId, ['warnings']).then(
+ getTask(taskId, ['warnings']).then(
({ warnings = [] }) => {
if (this.mounted) {
this.setState({ loading: false, warnings });
diff --git a/server/sonar-web/src/main/js/components/common/__tests__/AnalysisWarningsModal-test.tsx b/server/sonar-web/src/main/js/components/common/__tests__/AnalysisWarningsModal-test.tsx
index 51ffa11a653..017a937588a 100644
--- a/server/sonar-web/src/main/js/components/common/__tests__/AnalysisWarningsModal-test.tsx
+++ b/server/sonar-web/src/main/js/components/common/__tests__/AnalysisWarningsModal-test.tsx
@@ -24,16 +24,26 @@ import { waitAndUpdate } from '../../../helpers/testUtils';
import { getTask } from '../../../api/ce';
jest.mock('../../../api/ce', () => ({
- getTask: jest
- .fn()
- .mockResolvedValue({
- warnings: ['message foo', 'message-bar', 'multiline message\nsecondline\n third line']
- })
+ getTask: jest.fn().mockResolvedValue({
+ warnings: ['message foo', 'message-bar', 'multiline message\nsecondline\n third line']
+ })
}));
+beforeEach(() => {
+ (getTask as jest.Mock<any>).mockClear();
+});
+
it('should fetch warnings and render', async () => {
const wrapper = shallow(<AnalysisWarningsModal onClose={jest.fn()} taskId="abcd1234" />);
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
expect(getTask).toBeCalledWith('abcd1234', ['warnings']);
});
+
+it('should render warnings without fetch', () => {
+ const wrapper = shallow(
+ <AnalysisWarningsModal onClose={jest.fn()} warnings={['warning 1', 'warning 2']} />
+ );
+ expect(wrapper).toMatchSnapshot();
+ expect(getTask).not.toBeCalled();
+});
diff --git a/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/AnalysisWarningsModal-test.tsx.snap b/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/AnalysisWarningsModal-test.tsx.snap
index c52023d0b5d..d11642c2553 100644
--- a/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/AnalysisWarningsModal-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/AnalysisWarningsModal-test.tsx.snap
@@ -90,3 +90,63 @@ exports[`should fetch warnings and render 1`] = `
</footer>
</Modal>
`;
+
+exports[`should render warnings without fetch 1`] = `
+<Modal
+ contentLabel="warnings"
+ onRequestClose={[MockFunction]}
+>
+ <header
+ className="modal-head"
+ >
+ <h2>
+ warnings
+ </h2>
+ </header>
+ <div
+ className="modal-body modal-container js-analysis-warnings"
+ >
+ <DeferredSpinner
+ loading={false}
+ timeout={100}
+ >
+ <div
+ className="panel panel-vertical"
+ key="0"
+ >
+ <WarningIcon
+ className="pull-left spacer-right"
+ />
+ <div
+ className="overflow-hidden markdown"
+ >
+ warning 1
+ </div>
+ </div>
+ <div
+ className="panel panel-vertical"
+ key="1"
+ >
+ <WarningIcon
+ className="pull-left spacer-right"
+ />
+ <div
+ className="overflow-hidden markdown"
+ >
+ warning 2
+ </div>
+ </div>
+ </DeferredSpinner>
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <ResetButtonLink
+ className="js-modal-close"
+ onClick={[MockFunction]}
+ >
+ close
+ </ResetButtonLink>
+ </footer>
+</Modal>
+`;