@@ -147,6 +147,14 @@ export default class BubbleChart extends React.PureComponent<Props, State> { | |||
const formatXTick = (tick: string | number | undefined) => formatMeasure(tick, metrics.x.type); | |||
const formatYTick = (tick: string | number | undefined) => formatMeasure(tick, metrics.y.type); | |||
let xDomain: [number, number] | undefined; | |||
if (items.reduce((acc, item) => acc + item.x, 0) === 0) { | |||
// All items are on the 0 axis. This won't display the grid on the X axis, | |||
// which can make the graph a little hard to read. Force the display of | |||
// the X grid. | |||
xDomain = [0, 100]; | |||
} | |||
return ( | |||
<OriginalBubbleChart<T.ComponentMeasureEnhanced> | |||
formatXTick={formatXTick} | |||
@@ -156,6 +164,7 @@ export default class BubbleChart extends React.PureComponent<Props, State> { | |||
onBubbleClick={this.handleBubbleClick} | |||
padding={[25, 60, 50, 60]} | |||
yDomain={getBubbleYDomain(this.props.domain)} | |||
xDomain={xDomain} | |||
/> | |||
); | |||
} |
@@ -20,6 +20,7 @@ | |||
import { shallow } from 'enzyme'; | |||
import { keyBy } from 'lodash'; | |||
import * as React from 'react'; | |||
import OriginalBubbleChart from 'sonar-ui-common/components/charts/BubbleChart'; | |||
import { mockComponentMeasure, mockMeasure, mockMetric } from '../../../../helpers/testMocks'; | |||
import { MetricKey } from '../../../../types/metrics'; | |||
import { enhanceComponent } from '../../utils'; | |||
@@ -36,16 +37,35 @@ const metrics = keyBy( | |||
); | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
expect(shallowRender()).toMatchSnapshot('default'); | |||
expect( | |||
shallowRender({ | |||
components: [ | |||
enhanceComponent( | |||
mockComponentMeasure(true, { | |||
measures: [ | |||
mockMeasure({ value: '0', metric: MetricKey.ncloc }), | |||
mockMeasure({ value: '0', metric: MetricKey.security_remediation_effort }), | |||
mockMeasure({ value: '0', metric: MetricKey.vulnerabilities }), | |||
mockMeasure({ value: '0', metric: MetricKey.security_rating }) | |||
] | |||
}), | |||
metrics[MetricKey.vulnerabilities], | |||
metrics | |||
) | |||
] | |||
}) | |||
).toMatchSnapshot('all on x=0'); | |||
}); | |||
it('should handle filtering', () => { | |||
const wrapper = shallowRender(); | |||
expect(wrapper.find(OriginalBubbleChart).props().items).toHaveLength(1); | |||
wrapper.instance().handleRatingFilterClick(2); | |||
expect(wrapper.state().ratingFilters).toEqual({ 2: true }); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(wrapper.find(OriginalBubbleChart).props().items).toHaveLength(0); | |||
}); | |||
function shallowRender(overrides: Partial<BubbleChart['props']> = {}) { |
@@ -1,6 +1,6 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should handle filtering 1`] = ` | |||
exports[`should render correctly: all on x=0 1`] = ` | |||
<div | |||
className="measure-overview-bubble-chart" | |||
> | |||
@@ -35,11 +35,7 @@ exports[`should handle filtering 1`] = ` | |||
</span> | |||
<ColorRatingsLegend | |||
className="spacer-top" | |||
filters={ | |||
Object { | |||
"2": true, | |||
} | |||
} | |||
filters={Object {}} | |||
onRatingClick={[Function]} | |||
/> | |||
</span> | |||
@@ -55,7 +51,113 @@ exports[`should handle filtering 1`] = ` | |||
formatXTick={[Function]} | |||
formatYTick={[Function]} | |||
height={500} | |||
items={Array []} | |||
items={ | |||
Array [ | |||
Object { | |||
"color": undefined, | |||
"data": Object { | |||
"key": "foo:src/index.tsx", | |||
"leak": "1.0", | |||
"measures": Array [ | |||
Object { | |||
"bestValue": true, | |||
"leak": "1.0", | |||
"metric": Object { | |||
"id": "ncloc", | |||
"key": "ncloc", | |||
"name": "Ncloc", | |||
"type": "NUMBER", | |||
}, | |||
"period": Object { | |||
"bestValue": true, | |||
"index": 1, | |||
"value": "1.0", | |||
}, | |||
"value": "0", | |||
}, | |||
Object { | |||
"bestValue": true, | |||
"leak": "1.0", | |||
"metric": Object { | |||
"id": "security_remediation_effort", | |||
"key": "security_remediation_effort", | |||
"name": "Security_remediation_effort", | |||
"type": "NUMBER", | |||
}, | |||
"period": Object { | |||
"bestValue": true, | |||
"index": 1, | |||
"value": "1.0", | |||
}, | |||
"value": "0", | |||
}, | |||
Object { | |||
"bestValue": true, | |||
"leak": "1.0", | |||
"metric": Object { | |||
"id": "vulnerabilities", | |||
"key": "vulnerabilities", | |||
"name": "Vulnerabilities", | |||
"type": "NUMBER", | |||
}, | |||
"period": Object { | |||
"bestValue": true, | |||
"index": 1, | |||
"value": "1.0", | |||
}, | |||
"value": "0", | |||
}, | |||
Object { | |||
"bestValue": true, | |||
"leak": "1.0", | |||
"metric": Object { | |||
"id": "security_rating", | |||
"key": "security_rating", | |||
"name": "Security_rating", | |||
"type": "RATING", | |||
}, | |||
"period": Object { | |||
"bestValue": true, | |||
"index": 1, | |||
"value": "1.0", | |||
}, | |||
"value": "0", | |||
}, | |||
], | |||
"name": "index.tsx", | |||
"path": "src/index.tsx", | |||
"qualifier": "FIL", | |||
"value": "0", | |||
}, | |||
"size": 0, | |||
"tooltip": <div | |||
className="text-left" | |||
> | |||
<React.Fragment> | |||
index.tsx | |||
<br /> | |||
</React.Fragment> | |||
<React.Fragment> | |||
Ncloc: 0 | |||
<br /> | |||
</React.Fragment> | |||
<React.Fragment> | |||
Security_remediation_effort: 0 | |||
<br /> | |||
</React.Fragment> | |||
<React.Fragment> | |||
Vulnerabilities: 0 | |||
<br /> | |||
</React.Fragment> | |||
<React.Fragment> | |||
Security_rating: \` | |||
</React.Fragment> | |||
</div>, | |||
"x": 0, | |||
"y": 0, | |||
}, | |||
] | |||
} | |||
onBubbleClick={[Function]} | |||
padding={ | |||
Array [ | |||
@@ -71,6 +173,12 @@ exports[`should handle filtering 1`] = ` | |||
45, | |||
] | |||
} | |||
xDomain={ | |||
Array [ | |||
0, | |||
100, | |||
] | |||
} | |||
/> | |||
</div> | |||
<div | |||
@@ -86,7 +194,7 @@ exports[`should handle filtering 1`] = ` | |||
</div> | |||
`; | |||
exports[`should render correctly 1`] = ` | |||
exports[`should render correctly: default 1`] = ` | |||
<div | |||
className="measure-overview-bubble-chart" | |||
> |