Test coverage for line chart annotations

This commit is contained in:
Michael Lange
2020-08-03 18:52:53 -07:00
parent 51a5209459
commit f04b646dcb
3 changed files with 112 additions and 4 deletions

View File

@@ -271,16 +271,21 @@ export default class LineChart extends Component.extend(WindowResizable) {
if (!annotations || !annotations.length) return null;
return annotations.map(annotation => {
let sortedAnnotations = annotations.sortBy(xProp);
if (timeseries) {
sortedAnnotations = sortedAnnotations.reverse();
}
return sortedAnnotations.map(annotation => {
const x = xScale(annotation[xProp]);
const y = 0; // TODO: prevent overlap by staggering y-offset
const time = this.xFormat(timeseries)(annotation[xProp]);
const formattedX = this.xFormat(timeseries)(annotation[xProp]);
return {
annotation,
style: `transform:translate(${x}px,${y}px)`,
icon: iconFor[annotation.type],
iconClass: iconClassFor[annotation.type],
label: `${annotation.type} event at ${time}`,
label: `${annotation.type} event at ${formattedX}`,
};
});
}

View File

@@ -28,7 +28,7 @@
</svg>
<div data-test-annotations class="line-chart-annotations" style={{this.chartAnnotationsStyle}}>
{{#each this.processedAnnotations as |annotation|}}
<div class="chart-annotation {{annotation.iconClass}}" style={{annotation.style}}>
<div data-test-annotation class="chart-annotation {{annotation.iconClass}}" style={{annotation.style}}>
<button
type="button"
class="indicator"

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,103 @@
import { findAll, click, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';
import moment from 'moment';
const REF_DATE = new Date();
module('Integration | Component | line chart', function(hooks) {
setupRenderingTest(hooks);
test('when a chart has annotations, they are rendered in order', async function(assert) {
const annotations = [{ x: 2, type: 'info' }, { x: 1, type: 'error' }, { x: 3, type: 'info' }];
this.setProperties({
annotations,
data: [{ x: 1, y: 1 }, { x: 10, y: 10 }],
});
await render(hbs`
<LineChart
@xProp="x"
@yProp="y"
@data={{this.data}}
@annotations={{this.annotations}} />
`);
const sortedAnnotations = annotations.sortBy('x');
findAll('[data-test-annotation]').forEach((annotation, idx) => {
const datum = sortedAnnotations[idx];
assert.equal(
annotation.querySelector('button').getAttribute('title'),
`${datum.type} event at ${datum.x}`
);
});
});
test('when a chart has annotations and is timeseries, annotations are sorted reverse-chronologically', async function(assert) {
const annotations = [
{
x: moment(REF_DATE)
.add(2, 'd')
.toDate(),
type: 'info',
},
{
x: moment(REF_DATE)
.add(1, 'd')
.toDate(),
type: 'error',
},
{
x: moment(REF_DATE)
.add(3, 'd')
.toDate(),
type: 'info',
},
];
this.setProperties({
annotations,
data: [{ x: 1, y: 1 }, { x: 10, y: 10 }],
});
await render(hbs`
<LineChart
@xProp="x"
@yProp="y"
@timeseries={{true}}
@data={{this.data}}
@annotations={{this.annotations}} />
`);
const sortedAnnotations = annotations.sortBy('x').reverse();
findAll('[data-test-annotation]').forEach((annotation, idx) => {
const datum = sortedAnnotations[idx];
assert.equal(
annotation.querySelector('button').getAttribute('title'),
`${datum.type} event at ${moment(datum.x).format('MMM DD, HH:mm')}`
);
});
});
test('clicking annotations calls the onAnnotationClick action with the annotation as an argument', async function(assert) {
const annotations = [{ x: 2, type: 'info', meta: { data: 'here' } }];
this.setProperties({
annotations,
data: [{ x: 1, y: 1 }, { x: 10, y: 10 }],
click: sinon.spy(),
});
await render(hbs`
<LineChart
@xProp="x"
@yProp="y"
@data={{this.data}}
@annotations={{this.annotations}}
@onAnnotationClick={{this.click}} />
`);
await click('[data-test-annotation] button');
assert.ok(this.click.calledWith(annotations[0]));
});
});