mirror of
https://github.com/flutter/samples.git
synced 2025-11-13 00:08:24 +00:00
Add flutter_web samples (#75)
This commit is contained in:
committed by
Andrew Brogdon
parent
42f2dce01b
commit
3fe927cb29
404
web/charts/common/test/chart/bar/bar_label_decorator_test.dart
Normal file
404
web/charts/common/test/chart/bar/bar_label_decorator_test.dart
Normal file
@@ -0,0 +1,404 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import 'dart:math' show Rectangle;
|
||||
import 'package:charts_common/src/chart/common/processed_series.dart'
|
||||
show ImmutableSeries;
|
||||
import 'package:charts_common/src/common/color.dart' show Color;
|
||||
import 'package:charts_common/src/common/graphics_factory.dart'
|
||||
show GraphicsFactory;
|
||||
import 'package:charts_common/src/common/line_style.dart' show LineStyle;
|
||||
import 'package:charts_common/src/common/text_element.dart'
|
||||
show TextDirection, TextElement, MaxWidthStrategy;
|
||||
import 'package:charts_common/src/common/text_measurement.dart'
|
||||
show TextMeasurement;
|
||||
import 'package:charts_common/src/common/text_style.dart' show TextStyle;
|
||||
import 'package:charts_common/src/chart/bar/bar_renderer.dart'
|
||||
show ImmutableBarRendererElement;
|
||||
import 'package:charts_common/src/chart/cartesian/axis/spec/axis_spec.dart'
|
||||
show TextStyleSpec;
|
||||
import 'package:charts_common/src/chart/common/chart_canvas.dart'
|
||||
show ChartCanvas;
|
||||
import 'package:charts_common/src/chart/bar/bar_label_decorator.dart'
|
||||
show BarLabelDecorator, BarLabelAnchor, BarLabelPosition;
|
||||
import 'package:charts_common/src/data/series.dart' show AccessorFn;
|
||||
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class MockCanvas extends Mock implements ChartCanvas {}
|
||||
|
||||
/// A fake [GraphicsFactory] that returns [FakeTextStyle] and [FakeTextElement].
|
||||
class FakeGraphicsFactory extends GraphicsFactory {
|
||||
@override
|
||||
TextStyle createTextPaint() => new FakeTextStyle();
|
||||
|
||||
@override
|
||||
TextElement createTextElement(String text) => new FakeTextElement(text);
|
||||
|
||||
@override
|
||||
LineStyle createLinePaint() => new MockLinePaint();
|
||||
}
|
||||
|
||||
/// Stores [TextStyle] properties for test to verify.
|
||||
class FakeTextStyle implements TextStyle {
|
||||
Color color;
|
||||
int fontSize;
|
||||
String fontFamily;
|
||||
}
|
||||
|
||||
/// Fake [TextElement] which returns text length as [horizontalSliceWidth].
|
||||
///
|
||||
/// Font size is returned for [verticalSliceWidth] and [baseline].
|
||||
class FakeTextElement implements TextElement {
|
||||
final String text;
|
||||
TextStyle textStyle;
|
||||
int maxWidth;
|
||||
MaxWidthStrategy maxWidthStrategy;
|
||||
TextDirection textDirection;
|
||||
double opacity;
|
||||
|
||||
FakeTextElement(this.text);
|
||||
|
||||
TextMeasurement get measurement => new TextMeasurement(
|
||||
horizontalSliceWidth: text.length.toDouble(),
|
||||
verticalSliceWidth: textStyle.fontSize.toDouble(),
|
||||
baseline: textStyle.fontSize.toDouble());
|
||||
}
|
||||
|
||||
class MockLinePaint extends Mock implements LineStyle {}
|
||||
|
||||
class FakeBarRendererElement implements ImmutableBarRendererElement<String> {
|
||||
final _series = new MockImmutableSeries<String>();
|
||||
final AccessorFn<String> labelAccessor;
|
||||
final String datum;
|
||||
final Rectangle<int> bounds;
|
||||
final List<String> data;
|
||||
int index;
|
||||
|
||||
FakeBarRendererElement(
|
||||
this.datum, this.bounds, this.labelAccessor, this.data) {
|
||||
index = data.indexOf(datum);
|
||||
when(_series.labelAccessorFn).thenReturn(labelAccessor);
|
||||
when(_series.data).thenReturn(data);
|
||||
}
|
||||
|
||||
ImmutableSeries<String> get series => _series;
|
||||
}
|
||||
|
||||
class MockImmutableSeries<D> extends Mock implements ImmutableSeries<D> {}
|
||||
|
||||
void main() {
|
||||
ChartCanvas canvas;
|
||||
GraphicsFactory graphicsFactory;
|
||||
Rectangle<int> drawBounds;
|
||||
|
||||
setUpAll(() {
|
||||
canvas = new MockCanvas();
|
||||
graphicsFactory = new FakeGraphicsFactory();
|
||||
drawBounds = new Rectangle(0, 0, 200, 100);
|
||||
});
|
||||
|
||||
group('horizontal bar chart', () {
|
||||
test('Paint labels with default settings', () {
|
||||
final data = ['A', 'B'];
|
||||
final barElements = [
|
||||
// 'LabelA' and 'LabelB' both have lengths of 6.
|
||||
// 'LabelB' would not fit inside the bar in auto setting because it has
|
||||
// width of 5.
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 20, 50, 20), (_) => 'LabelA', data),
|
||||
new FakeBarRendererElement(
|
||||
'B', new Rectangle(0, 70, 5, 20), (_) => 'LabelB', data)
|
||||
];
|
||||
final decorator = new BarLabelDecorator();
|
||||
|
||||
decorator.decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
final captured =
|
||||
verify(canvas.drawText(captureAny, captureAny, captureAny)).captured;
|
||||
// Draw text is called twice (once for each bar) and all 3 parameters were
|
||||
// captured. Total parameters captured expected to be 6.
|
||||
expect(captured, hasLength(6));
|
||||
// For bar 'A'.
|
||||
expect(captured[0].maxWidth, equals(50 - decorator.labelPadding * 2));
|
||||
expect(captured[0].textDirection, equals(TextDirection.ltr));
|
||||
expect(captured[1], equals(decorator.labelPadding));
|
||||
expect(captured[2],
|
||||
equals(30 - decorator.insideLabelStyleSpec.fontSize ~/ 2));
|
||||
// For bar 'B'.
|
||||
expect(
|
||||
captured[3].maxWidth, equals(200 - 5 - decorator.labelPadding * 2));
|
||||
expect(captured[3].textDirection, equals(TextDirection.ltr));
|
||||
expect(captured[4], equals(5 + decorator.labelPadding));
|
||||
expect(captured[5],
|
||||
equals(80 - decorator.outsideLabelStyleSpec.fontSize ~/ 2));
|
||||
});
|
||||
|
||||
test('LabelPosition.auto paints inside bar if outside bar has less width',
|
||||
() {
|
||||
final barElements = [
|
||||
// 'LabelABC' would not fit inside the bar in auto setting because it
|
||||
// has a width of 8.
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 6, 20), (_) => 'LabelABC', ['A']),
|
||||
];
|
||||
// Draw bounds with width of 10 means that space inside the bar is larger.
|
||||
final smallDrawBounds = new Rectangle(0, 0, 10, 20);
|
||||
|
||||
new BarLabelDecorator(
|
||||
labelPadding: 0, // Turn off label padding for testing.
|
||||
insideLabelStyleSpec: new TextStyleSpec(fontSize: 10))
|
||||
.decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: smallDrawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
final captured =
|
||||
verify(canvas.drawText(captureAny, captureAny, captureAny)).captured;
|
||||
expect(captured, hasLength(3));
|
||||
expect(captured[0].maxWidth, equals(6));
|
||||
expect(captured[0].textDirection, equals(TextDirection.ltr));
|
||||
expect(captured[1], equals(0));
|
||||
expect(captured[2], equals(5));
|
||||
});
|
||||
|
||||
test('LabelPosition.inside always paints inside the bar', () {
|
||||
final barElements = [
|
||||
// 'LabelABC' would not fit inside the bar in auto setting because it
|
||||
// has a width of 8.
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 6, 20), (_) => 'LabelABC', ['A']),
|
||||
];
|
||||
|
||||
new BarLabelDecorator(
|
||||
labelPosition: BarLabelPosition.inside,
|
||||
labelPadding: 0, // Turn off label padding for testing.
|
||||
insideLabelStyleSpec: new TextStyleSpec(fontSize: 10))
|
||||
.decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
final captured =
|
||||
verify(canvas.drawText(captureAny, captureAny, captureAny)).captured;
|
||||
expect(captured, hasLength(3));
|
||||
expect(captured[0].maxWidth, equals(6));
|
||||
expect(captured[0].textDirection, equals(TextDirection.ltr));
|
||||
expect(captured[1], equals(0));
|
||||
expect(captured[2], equals(5));
|
||||
});
|
||||
|
||||
test('LabelPosition.outside always paints outside the bar', () {
|
||||
final barElements = [
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 10, 20), (_) => 'Label', ['A']),
|
||||
];
|
||||
|
||||
new BarLabelDecorator(
|
||||
labelPosition: BarLabelPosition.outside,
|
||||
labelPadding: 0, // Turn off label padding for testing.
|
||||
outsideLabelStyleSpec: new TextStyleSpec(fontSize: 10))
|
||||
.decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
final captured =
|
||||
verify(canvas.drawText(captureAny, captureAny, captureAny)).captured;
|
||||
expect(captured, hasLength(3));
|
||||
expect(captured[0].maxWidth, equals(190));
|
||||
expect(captured[0].textDirection, equals(TextDirection.ltr));
|
||||
expect(captured[1], equals(10));
|
||||
expect(captured[2], equals(5));
|
||||
});
|
||||
|
||||
test('Inside and outside label styles are applied', () {
|
||||
final data = ['A', 'B'];
|
||||
final barElements = [
|
||||
// 'LabelA' and 'LabelB' both have lengths of 6.
|
||||
// 'LabelB' would not fit inside the bar in auto setting because it has
|
||||
// width of 5.
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 20, 50, 20), (_) => 'LabelA', data),
|
||||
new FakeBarRendererElement(
|
||||
'B', new Rectangle(0, 70, 5, 20), (_) => 'LabelB', data)
|
||||
];
|
||||
final insideColor = new Color(r: 0, g: 0, b: 0);
|
||||
final outsideColor = new Color(r: 255, g: 255, b: 255);
|
||||
final decorator = new BarLabelDecorator(
|
||||
labelPadding: 0,
|
||||
insideLabelStyleSpec: new TextStyleSpec(
|
||||
fontSize: 10, fontFamily: 'insideFont', color: insideColor),
|
||||
outsideLabelStyleSpec: new TextStyleSpec(
|
||||
fontSize: 8, fontFamily: 'outsideFont', color: outsideColor));
|
||||
|
||||
decorator.decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
final captured =
|
||||
verify(canvas.drawText(captureAny, captureAny, captureAny)).captured;
|
||||
// Draw text is called twice (once for each bar) and all 3 parameters were
|
||||
// captured. Total parameters captured expected to be 6.
|
||||
expect(captured, hasLength(6));
|
||||
// For bar 'A'.
|
||||
expect(captured[0].maxWidth, equals(50));
|
||||
expect(captured[0].textDirection, equals(TextDirection.ltr));
|
||||
expect(captured[0].textStyle.fontFamily, equals('insideFont'));
|
||||
expect(captured[0].textStyle.color, equals(insideColor));
|
||||
expect(captured[1], equals(0));
|
||||
expect(captured[2], equals(30 - 5));
|
||||
// For bar 'B'.
|
||||
expect(captured[3].maxWidth, equals(200 - 5));
|
||||
expect(captured[3].textDirection, equals(TextDirection.ltr));
|
||||
expect(captured[3].textStyle.fontFamily, equals('outsideFont'));
|
||||
expect(captured[3].textStyle.color, equals(outsideColor));
|
||||
expect(captured[4], equals(5));
|
||||
expect(captured[5], equals(80 - 4));
|
||||
});
|
||||
|
||||
test('TextAnchor.end starts on the right most of bar', () {
|
||||
final barElements = [
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 10, 20), (_) => 'LabelA', ['A'])
|
||||
];
|
||||
|
||||
new BarLabelDecorator(
|
||||
labelAnchor: BarLabelAnchor.end,
|
||||
labelPosition: BarLabelPosition.inside,
|
||||
labelPadding: 0, // Turn off label padding for testing.
|
||||
insideLabelStyleSpec: new TextStyleSpec(fontSize: 10))
|
||||
.decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
final captured =
|
||||
verify(canvas.drawText(captureAny, captureAny, captureAny)).captured;
|
||||
expect(captured, hasLength(3));
|
||||
expect(captured[0].maxWidth, equals(10));
|
||||
expect(captured[0].textDirection, equals(TextDirection.rtl));
|
||||
expect(captured[1], equals(10));
|
||||
expect(captured[2], equals(5));
|
||||
});
|
||||
|
||||
test('RTL TextAnchor.start starts on the right', () {
|
||||
final barElements = [
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 10, 20), (_) => 'LabelA', ['A'])
|
||||
];
|
||||
|
||||
new BarLabelDecorator(
|
||||
labelAnchor: BarLabelAnchor.start,
|
||||
labelPosition: BarLabelPosition.inside,
|
||||
labelPadding: 0, // Turn off label padding for testing.
|
||||
insideLabelStyleSpec: new TextStyleSpec(fontSize: 10))
|
||||
.decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false,
|
||||
rtl: true);
|
||||
|
||||
final captured =
|
||||
verify(canvas.drawText(captureAny, captureAny, captureAny)).captured;
|
||||
expect(captured, hasLength(3));
|
||||
expect(captured[0].maxWidth, equals(10));
|
||||
expect(captured[0].textDirection, equals(TextDirection.rtl));
|
||||
expect(captured[1], equals(10));
|
||||
expect(captured[2], equals(5));
|
||||
});
|
||||
|
||||
test('RTL TextAnchor.end starts on the left', () {
|
||||
final barElements = [
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 10, 20), (_) => 'LabelA', ['A'])
|
||||
];
|
||||
|
||||
new BarLabelDecorator(
|
||||
labelAnchor: BarLabelAnchor.end,
|
||||
labelPosition: BarLabelPosition.inside,
|
||||
labelPadding: 0, // Turn off label padding for testing.
|
||||
insideLabelStyleSpec: new TextStyleSpec(fontSize: 10))
|
||||
.decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false,
|
||||
rtl: true);
|
||||
|
||||
final captured =
|
||||
verify(canvas.drawText(captureAny, captureAny, captureAny)).captured;
|
||||
expect(captured, hasLength(3));
|
||||
expect(captured[0].maxWidth, equals(10));
|
||||
expect(captured[0].textDirection, equals(TextDirection.ltr));
|
||||
expect(captured[1], equals(0));
|
||||
expect(captured[2], equals(5));
|
||||
});
|
||||
});
|
||||
|
||||
group('Null and empty label scenarios', () {
|
||||
test('Skip label if label accessor does not exist', () {
|
||||
final barElements = [
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 10, 20), null, ['A'])
|
||||
];
|
||||
|
||||
new BarLabelDecorator().decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
verifyNever(canvas.drawText(any, any, any));
|
||||
});
|
||||
|
||||
test('Skip label if label is null or empty', () {
|
||||
final data = ['A', 'B'];
|
||||
final barElements = [
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 10, 20), null, data),
|
||||
new FakeBarRendererElement(
|
||||
'B', new Rectangle(0, 50, 10, 20), (_) => '', data),
|
||||
];
|
||||
|
||||
new BarLabelDecorator().decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
verifyNever(canvas.drawText(any, any, any));
|
||||
});
|
||||
|
||||
test('Skip label if no width available', () {
|
||||
final barElements = [
|
||||
new FakeBarRendererElement(
|
||||
'A', new Rectangle(0, 0, 200, 20), (_) => 'a', ['A'])
|
||||
];
|
||||
|
||||
new BarLabelDecorator(
|
||||
labelPadding: 0,
|
||||
labelPosition: BarLabelPosition.outside,
|
||||
).decorate(barElements, canvas, graphicsFactory,
|
||||
drawBounds: drawBounds,
|
||||
animationPercent: 1.0,
|
||||
renderingVertically: false);
|
||||
|
||||
verifyNever(canvas.drawText(any, any, any));
|
||||
});
|
||||
});
|
||||
}
|
||||
882
web/charts/common/test/chart/bar/bar_renderer_test.dart
Normal file
882
web/charts/common/test/chart/bar/bar_renderer_test.dart
Normal file
@@ -0,0 +1,882 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import 'package:charts_common/src/chart/bar/bar_renderer.dart';
|
||||
import 'package:charts_common/src/chart/bar/bar_renderer_config.dart';
|
||||
import 'package:charts_common/src/chart/bar/base_bar_renderer.dart';
|
||||
import 'package:charts_common/src/chart/bar/base_bar_renderer_config.dart';
|
||||
import 'package:charts_common/src/chart/cartesian/cartesian_chart.dart';
|
||||
import 'package:charts_common/src/chart/cartesian/axis/axis.dart';
|
||||
import 'package:charts_common/src/chart/common/chart_canvas.dart';
|
||||
import 'package:charts_common/src/chart/common/chart_context.dart';
|
||||
import 'package:charts_common/src/chart/common/processed_series.dart'
|
||||
show MutableSeries;
|
||||
import 'package:charts_common/src/common/material_palette.dart'
|
||||
show MaterialPalette;
|
||||
import 'package:charts_common/src/common/color.dart';
|
||||
import 'package:charts_common/src/data/series.dart' show Series;
|
||||
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
/// Datum/Row for the chart.
|
||||
class MyRow {
|
||||
final String campaign;
|
||||
final int clickCount;
|
||||
MyRow(this.campaign, this.clickCount);
|
||||
}
|
||||
|
||||
class MockAxis<D> extends Mock implements Axis<D> {}
|
||||
|
||||
class MockCanvas extends Mock implements ChartCanvas {}
|
||||
|
||||
class MockContext extends Mock implements ChartContext {}
|
||||
|
||||
class MockChart extends Mock implements CartesianChart {}
|
||||
|
||||
class FakeBarRenderer<D> extends BarRenderer<D> {
|
||||
int paintBarCallCount = 0;
|
||||
|
||||
factory FakeBarRenderer({BarRendererConfig config, String rendererId}) {
|
||||
return new FakeBarRenderer._internal(
|
||||
config: config, rendererId: rendererId);
|
||||
}
|
||||
|
||||
FakeBarRenderer._internal({BarRendererConfig config, String rendererId})
|
||||
: super.internal(config: config, rendererId: rendererId);
|
||||
|
||||
@override
|
||||
void paintBar(ChartCanvas canvas, double animationPercent,
|
||||
Iterable<BarRendererElement<D>> barElements) {
|
||||
paintBarCallCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
BarRenderer renderer;
|
||||
List<MutableSeries<String>> seriesList;
|
||||
List<MutableSeries<String>> groupedStackedSeriesList;
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Convenience methods for creating mocks.
|
||||
/////////////////////////////////////////
|
||||
_configureBaseRenderer(BaseBarRenderer renderer, bool vertical) {
|
||||
final context = new MockContext();
|
||||
when(context.chartContainerIsRtl).thenReturn(false);
|
||||
when(context.isRtl).thenReturn(false);
|
||||
final verticalChart = new MockChart();
|
||||
when(verticalChart.vertical).thenReturn(vertical);
|
||||
when(verticalChart.context).thenReturn(context);
|
||||
renderer.onAttach(verticalChart);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
BarRenderer makeRenderer({BarRendererConfig config}) {
|
||||
final renderer = new BarRenderer(config: config);
|
||||
_configureBaseRenderer(renderer, true);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
FakeBarRenderer makeFakeRenderer({BarRendererConfig config}) {
|
||||
final renderer = new FakeBarRenderer(config: config);
|
||||
_configureBaseRenderer(renderer, true);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
var myFakeDesktopAData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
var myFakeTabletAData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
var myFakeMobileAData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
var myFakeDesktopBData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
var myFakeTabletBData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
var myFakeMobileBData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
seriesList = [
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Desktop',
|
||||
colorFn: (_, __) => MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeDesktopAData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Tablet',
|
||||
colorFn: (_, __) => MaterialPalette.red.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeTabletAData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Mobile',
|
||||
colorFn: (_, __) => MaterialPalette.green.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeMobileAData))
|
||||
];
|
||||
|
||||
groupedStackedSeriesList = [
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Desktop A',
|
||||
seriesCategory: 'A',
|
||||
colorFn: (_, __) => MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeDesktopAData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Tablet A',
|
||||
seriesCategory: 'A',
|
||||
colorFn: (_, __) => MaterialPalette.red.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeTabletAData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Mobile A',
|
||||
seriesCategory: 'A',
|
||||
colorFn: (_, __) => MaterialPalette.green.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeMobileAData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Desktop B',
|
||||
seriesCategory: 'B',
|
||||
colorFn: (_, __) => MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeDesktopBData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Tablet B',
|
||||
seriesCategory: 'B',
|
||||
colorFn: (_, __) => MaterialPalette.red.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeTabletBData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Mobile B',
|
||||
seriesCategory: 'B',
|
||||
colorFn: (_, __) => MaterialPalette.green.shadeDefault,
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeMobileBData))
|
||||
];
|
||||
});
|
||||
|
||||
group('preprocess', () {
|
||||
test('with grouped bars', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarRendererConfig(groupingType: BarGroupingType.grouped));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(2));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(2 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
});
|
||||
|
||||
test('with grouped stacked bars', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarRendererConfig(
|
||||
groupingType: BarGroupingType.groupedStacked));
|
||||
|
||||
renderer.preprocessSeries(groupedStackedSeriesList);
|
||||
|
||||
expect(groupedStackedSeriesList.length, equals(6));
|
||||
|
||||
// Validate Desktop A series.
|
||||
var series = groupedStackedSeriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(stackKeyKey), equals('A'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(10));
|
||||
expect(element.measureOffsetPlusMeasure, equals(15));
|
||||
expect(series.measureOffsetFn(0), equals(10));
|
||||
|
||||
// Validate Tablet A series.
|
||||
series = groupedStackedSeriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(stackKeyKey), equals('A'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
|
||||
// Validate Mobile A series.
|
||||
series = groupedStackedSeriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(stackKeyKey), equals('A'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
|
||||
// Validate Desktop B series.
|
||||
series = groupedStackedSeriesList[3];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(stackKeyKey), equals('B'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(10));
|
||||
expect(element.measureOffsetPlusMeasure, equals(15));
|
||||
expect(series.measureOffsetFn(0), equals(10));
|
||||
|
||||
// Validate Tablet B series.
|
||||
series = groupedStackedSeriesList[4];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(stackKeyKey), equals('B'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
|
||||
// Validate Mobile B series.
|
||||
series = groupedStackedSeriesList[5];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(stackKeyKey), equals('B'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
});
|
||||
|
||||
test('with stacked bars', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarRendererConfig(groupingType: BarGroupingType.stacked));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(10));
|
||||
expect(element.measureOffsetPlusMeasure, equals(15));
|
||||
expect(series.measureOffsetFn(0), equals(10));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
});
|
||||
|
||||
test('with stacked bars containing zero and null', () {
|
||||
// Set up some nulls and zeros in the data.
|
||||
seriesList[2].data[0] = new MyRow('MyCampaign1', null);
|
||||
seriesList[2].data[2] = new MyRow('MyCampaign3', 0);
|
||||
|
||||
seriesList[1].data[1] = new MyRow('MyCampaign2', null);
|
||||
seriesList[1].data[3] = new MyRow('MyOtherCampaign', 0);
|
||||
|
||||
seriesList[0].data[2] = new MyRow('MyCampaign3', 0);
|
||||
|
||||
renderer = makeRenderer(
|
||||
config: new BarRendererConfig(groupingType: BarGroupingType.stacked));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.measureOffset, equals(25));
|
||||
expect(element.measureOffsetPlusMeasure, equals(50));
|
||||
expect(series.measureOffsetFn(1), equals(25));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.measureOffset, equals(100));
|
||||
expect(element.measureOffsetPlusMeasure, equals(100));
|
||||
expect(series.measureOffsetFn(2), equals(100));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.measureOffset, equals(75));
|
||||
expect(element.measureOffsetPlusMeasure, equals(150));
|
||||
expect(series.measureOffsetFn(3), equals(75));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.measureOffset, equals(25));
|
||||
expect(element.measureOffsetPlusMeasure, equals(25));
|
||||
expect(series.measureOffsetFn(1), equals(25));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(100));
|
||||
expect(series.measureOffsetFn(2), equals(0));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.measureOffset, equals(75));
|
||||
expect(element.measureOffsetPlusMeasure, equals(75));
|
||||
expect(series.measureOffsetFn(3), equals(75));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(0));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(25));
|
||||
expect(series.measureOffsetFn(1), equals(0));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(0));
|
||||
expect(series.measureOffsetFn(2), equals(0));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(75));
|
||||
expect(series.measureOffsetFn(3), equals(0));
|
||||
});
|
||||
});
|
||||
|
||||
group('preprocess weight pattern', () {
|
||||
test('with grouped bars', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarRendererConfig(
|
||||
groupingType: BarGroupingType.grouped, weightPattern: [3, 2, 1]));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
// Verify that bar group weights are proportional to the sum of the used
|
||||
// segments of weightPattern. The weightPattern should be distributed
|
||||
// amongst bars that share the same domain value.
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(2));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.5 + 1 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 6));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
});
|
||||
|
||||
test('with grouped stacked bars', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarRendererConfig(
|
||||
groupingType: BarGroupingType.groupedStacked,
|
||||
weightPattern: [2, 1]));
|
||||
|
||||
renderer.preprocessSeries(groupedStackedSeriesList);
|
||||
|
||||
// Verify that bar group weights are proportional to the sum of the used
|
||||
// segments of weightPattern. The weightPattern should be distributed
|
||||
// amongst bars that share the same domain and series category values.
|
||||
|
||||
expect(groupedStackedSeriesList.length, equals(6));
|
||||
|
||||
// Validate Desktop A series.
|
||||
var series = groupedStackedSeriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(2 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('A'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(10));
|
||||
expect(element.measureOffsetPlusMeasure, equals(15));
|
||||
expect(series.measureOffsetFn(0), equals(10));
|
||||
|
||||
// Validate Tablet A series.
|
||||
series = groupedStackedSeriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(2 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('A'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
|
||||
// Validate Mobile A series.
|
||||
series = groupedStackedSeriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(2 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('A'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
|
||||
// Validate Desktop B series.
|
||||
series = groupedStackedSeriesList[3];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(2 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('B'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(10));
|
||||
expect(element.measureOffsetPlusMeasure, equals(15));
|
||||
expect(series.measureOffsetFn(0), equals(10));
|
||||
|
||||
// Validate Tablet B series.
|
||||
series = groupedStackedSeriesList[4];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(2 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('B'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
|
||||
// Validate Mobile B series.
|
||||
series = groupedStackedSeriesList[5];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(2));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(2 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('B'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
});
|
||||
|
||||
test('with stacked bars - weightPattern not used', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarRendererConfig(
|
||||
groupingType: BarGroupingType.stacked, weightPattern: [2, 1]));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
// Verify that weightPattern is not used, since stacked bars have only a
|
||||
// single group per domain value.
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(10));
|
||||
expect(element.measureOffsetPlusMeasure, equals(15));
|
||||
expect(series.measureOffsetFn(0), equals(10));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
});
|
||||
});
|
||||
|
||||
group('null measure', () {
|
||||
test('only include null in draw if animating from a non null measure', () {
|
||||
// Helper to create series list for this test only.
|
||||
List<MutableSeries<String>> _createSeriesList(List<MyRow> data) {
|
||||
final domainAxis = new MockAxis<dynamic>();
|
||||
when(domainAxis.rangeBand).thenReturn(100.0);
|
||||
when(domainAxis.getLocation('MyCampaign1')).thenReturn(20.0);
|
||||
when(domainAxis.getLocation('MyCampaign2')).thenReturn(40.0);
|
||||
when(domainAxis.getLocation('MyCampaign3')).thenReturn(60.0);
|
||||
when(domainAxis.getLocation('MyOtherCampaign')).thenReturn(80.0);
|
||||
final measureAxis = new MockAxis<num>();
|
||||
when(measureAxis.getLocation(0)).thenReturn(0.0);
|
||||
when(measureAxis.getLocation(5)).thenReturn(5.0);
|
||||
when(measureAxis.getLocation(75)).thenReturn(75.0);
|
||||
when(measureAxis.getLocation(100)).thenReturn(100.0);
|
||||
|
||||
final color = new Color.fromHex(code: '#000000');
|
||||
|
||||
final series = new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (_, __) => 0,
|
||||
colorFn: (_, __) => color,
|
||||
fillColorFn: (_, __) => color,
|
||||
dashPatternFn: (_, __) => [1],
|
||||
data: data))
|
||||
..setAttr(domainAxisKey, domainAxis)
|
||||
..setAttr(measureAxisKey, measureAxis);
|
||||
|
||||
return [series];
|
||||
}
|
||||
|
||||
final canvas = new MockCanvas();
|
||||
|
||||
final myDataWithNull = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', null),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
final seriesListWithNull = _createSeriesList(myDataWithNull);
|
||||
|
||||
final myDataWithMeasures = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 0),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
final seriesListWithMeasures = _createSeriesList(myDataWithMeasures);
|
||||
|
||||
final renderer = makeFakeRenderer(
|
||||
config: new BarRendererConfig(groupingType: BarGroupingType.grouped));
|
||||
|
||||
// Verify that only 3 bars are drawn for an initial draw with null data.
|
||||
renderer.preprocessSeries(seriesListWithNull);
|
||||
renderer.update(seriesListWithNull, true);
|
||||
renderer.paintBarCallCount = 0;
|
||||
renderer.paint(canvas, 0.5);
|
||||
expect(renderer.paintBarCallCount, equals(3));
|
||||
|
||||
// On animation complete, verify that only 3 bars are drawn.
|
||||
renderer.paintBarCallCount = 0;
|
||||
renderer.paint(canvas, 1.0);
|
||||
expect(renderer.paintBarCallCount, equals(3));
|
||||
|
||||
// Change series list where there are measures on all values, verify all
|
||||
// 4 bars were drawn
|
||||
renderer.preprocessSeries(seriesListWithMeasures);
|
||||
renderer.update(seriesListWithMeasures, true);
|
||||
renderer.paintBarCallCount = 0;
|
||||
renderer.paint(canvas, 0.5);
|
||||
expect(renderer.paintBarCallCount, equals(4));
|
||||
|
||||
// Change series to one with null measures, verifies all 4 bars drawn
|
||||
renderer.preprocessSeries(seriesListWithNull);
|
||||
renderer.update(seriesListWithNull, true);
|
||||
renderer.paintBarCallCount = 0;
|
||||
renderer.paint(canvas, 0.5);
|
||||
expect(renderer.paintBarCallCount, equals(4));
|
||||
|
||||
// On animation complete, verify that only 3 bars are drawn.
|
||||
renderer.paintBarCallCount = 0;
|
||||
renderer.paint(canvas, 1.0);
|
||||
expect(renderer.paintBarCallCount, equals(3));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,653 @@
|
||||
// Copyright 2018 the Charts project authors. Please see the AUTHORS file
|
||||
// for details.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import 'dart:math' show Point, Rectangle;
|
||||
import 'package:charts_common/src/chart/bar/bar_target_line_renderer.dart';
|
||||
import 'package:charts_common/src/chart/bar/bar_target_line_renderer_config.dart';
|
||||
import 'package:charts_common/src/chart/bar/base_bar_renderer.dart';
|
||||
import 'package:charts_common/src/chart/bar/base_bar_renderer_config.dart';
|
||||
import 'package:charts_common/src/chart/cartesian/cartesian_chart.dart';
|
||||
import 'package:charts_common/src/chart/cartesian/axis/axis.dart';
|
||||
import 'package:charts_common/src/chart/common/chart_canvas.dart';
|
||||
import 'package:charts_common/src/chart/common/chart_context.dart';
|
||||
import 'package:charts_common/src/chart/common/processed_series.dart'
|
||||
show MutableSeries;
|
||||
import 'package:charts_common/src/common/color.dart';
|
||||
import 'package:charts_common/src/data/series.dart' show Series;
|
||||
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
/// Datum/Row for the chart.
|
||||
class MyRow {
|
||||
final String campaign;
|
||||
final int clickCount;
|
||||
MyRow(this.campaign, this.clickCount);
|
||||
}
|
||||
|
||||
class MockAxis<D> extends Mock implements Axis<D> {}
|
||||
|
||||
class MockCanvas extends Mock implements ChartCanvas {
|
||||
final drawLinePointsList = <List<Point>>[];
|
||||
|
||||
void drawLine(
|
||||
{List<Point> points,
|
||||
Rectangle<num> clipBounds,
|
||||
Color fill,
|
||||
Color stroke,
|
||||
bool roundEndCaps,
|
||||
double strokeWidthPx,
|
||||
List<int> dashPattern}) {
|
||||
drawLinePointsList.add(points);
|
||||
}
|
||||
}
|
||||
|
||||
class MockContext extends Mock implements ChartContext {}
|
||||
|
||||
class MockChart extends Mock implements CartesianChart {}
|
||||
|
||||
void main() {
|
||||
BarTargetLineRenderer renderer;
|
||||
List<MutableSeries<String>> seriesList;
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Convenience methods for creating mocks.
|
||||
/////////////////////////////////////////
|
||||
_configureBaseRenderer(BaseBarRenderer renderer, bool vertical) {
|
||||
final context = new MockContext();
|
||||
when(context.chartContainerIsRtl).thenReturn(false);
|
||||
when(context.isRtl).thenReturn(false);
|
||||
final verticalChart = new MockChart();
|
||||
when(verticalChart.vertical).thenReturn(vertical);
|
||||
when(verticalChart.context).thenReturn(context);
|
||||
renderer.onAttach(verticalChart);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
BarTargetLineRenderer makeRenderer({BarTargetLineRendererConfig config}) {
|
||||
final renderer = new BarTargetLineRenderer(config: config);
|
||||
_configureBaseRenderer(renderer, true);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
var myFakeDesktopData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
var myFakeTabletData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
var myFakeMobileData = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 25),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
|
||||
seriesList = [
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeDesktopData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Tablet',
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeTabletData)),
|
||||
new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Mobile',
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (MyRow row, _) => 0,
|
||||
data: myFakeMobileData))
|
||||
];
|
||||
});
|
||||
|
||||
group('preprocess', () {
|
||||
test('with grouped bar target lines', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarTargetLineRendererConfig(
|
||||
groupingType: BarGroupingType.grouped));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(2));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(2 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
});
|
||||
|
||||
test('with stacked bar target lines', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarTargetLineRendererConfig(
|
||||
groupingType: BarGroupingType.stacked));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(10));
|
||||
expect(element.measureOffsetPlusMeasure, equals(15));
|
||||
expect(series.measureOffsetFn(0), equals(10));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
});
|
||||
|
||||
test('with stacked bar target lines containing zero and null', () {
|
||||
// Set up some nulls and zeros in the data.
|
||||
seriesList[2].data[0] = new MyRow('MyCampaign1', null);
|
||||
seriesList[2].data[2] = new MyRow('MyCampaign3', 0);
|
||||
|
||||
seriesList[1].data[1] = new MyRow('MyCampaign2', null);
|
||||
seriesList[1].data[3] = new MyRow('MyOtherCampaign', 0);
|
||||
|
||||
seriesList[0].data[2] = new MyRow('MyCampaign3', 0);
|
||||
|
||||
renderer = makeRenderer(
|
||||
config: new BarTargetLineRendererConfig(
|
||||
groupingType: BarGroupingType.stacked));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.measureOffset, equals(25));
|
||||
expect(element.measureOffsetPlusMeasure, equals(50));
|
||||
expect(series.measureOffsetFn(1), equals(25));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.measureOffset, equals(100));
|
||||
expect(element.measureOffsetPlusMeasure, equals(100));
|
||||
expect(series.measureOffsetFn(2), equals(100));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.measureOffset, equals(75));
|
||||
expect(element.measureOffsetPlusMeasure, equals(150));
|
||||
expect(series.measureOffsetFn(3), equals(75));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.measureOffset, equals(25));
|
||||
expect(element.measureOffsetPlusMeasure, equals(25));
|
||||
expect(series.measureOffsetFn(1), equals(25));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(100));
|
||||
expect(series.measureOffsetFn(2), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.measureOffset, equals(75));
|
||||
expect(element.measureOffsetPlusMeasure, equals(75));
|
||||
expect(series.measureOffsetFn(3), equals(75));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(0));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(25));
|
||||
expect(series.measureOffsetFn(1), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(0));
|
||||
expect(series.measureOffsetFn(2), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(75));
|
||||
expect(series.measureOffsetFn(3), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
});
|
||||
});
|
||||
|
||||
test('with stroke width target lines', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarTargetLineRendererConfig(
|
||||
groupingType: BarGroupingType.grouped, strokeWidthPx: 5.0));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[1];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[2];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
|
||||
element = elementsList[3];
|
||||
expect(element.strokeWidthPx, equals(5));
|
||||
});
|
||||
|
||||
group('preprocess with weight pattern', () {
|
||||
test('with grouped bar target lines', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarTargetLineRendererConfig(
|
||||
groupingType: BarGroupingType.grouped, weightPattern: [3, 2, 1]));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
// Verify that bar group weights are proportional to the sum of the used
|
||||
// segments of weightPattern. The weightPattern should be distributed
|
||||
// amongst bars that share the same domain value.
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(1));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.5));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 3));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(2));
|
||||
expect(series.getAttr(barGroupCountKey), equals(3));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.5 + 1 / 3));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1 / 6));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(null));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
});
|
||||
|
||||
test('with stacked bar target lines - weightPattern not used', () {
|
||||
renderer = makeRenderer(
|
||||
config: new BarTargetLineRendererConfig(
|
||||
groupingType: BarGroupingType.stacked, weightPattern: [2, 1]));
|
||||
|
||||
renderer.preprocessSeries(seriesList);
|
||||
|
||||
// Verify that weightPattern is not used, since stacked bars have only a
|
||||
// single group per domain value.
|
||||
|
||||
expect(seriesList.length, equals(3));
|
||||
|
||||
// Validate Desktop series.
|
||||
var series = seriesList[0];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
var elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
var element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(2));
|
||||
expect(element.measureOffset, equals(10));
|
||||
expect(element.measureOffsetPlusMeasure, equals(15));
|
||||
expect(series.measureOffsetFn(0), equals(10));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Tablet series.
|
||||
series = seriesList[1];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(1));
|
||||
expect(element.measureOffset, equals(5));
|
||||
expect(element.measureOffsetPlusMeasure, equals(10));
|
||||
expect(series.measureOffsetFn(0), equals(5));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
|
||||
// Validate Mobile series.
|
||||
series = seriesList[2];
|
||||
expect(series.getAttr(barGroupIndexKey), equals(0));
|
||||
expect(series.getAttr(barGroupCountKey), equals(1));
|
||||
expect(series.getAttr(previousBarGroupWeightKey), equals(0.0));
|
||||
expect(series.getAttr(barGroupWeightKey), equals(1));
|
||||
expect(series.getAttr(stackKeyKey), equals('__defaultKey__'));
|
||||
|
||||
elementsList = series.getAttr(barElementsKey);
|
||||
expect(elementsList.length, equals(4));
|
||||
|
||||
element = elementsList[0];
|
||||
expect(element.barStackIndex, equals(0));
|
||||
expect(element.measureOffset, equals(0));
|
||||
expect(element.measureOffsetPlusMeasure, equals(5));
|
||||
expect(series.measureOffsetFn(0), equals(0));
|
||||
expect(element.strokeWidthPx, equals(3));
|
||||
});
|
||||
});
|
||||
|
||||
group('null measure', () {
|
||||
test('only include null in draw if animating from a non null measure', () {
|
||||
// Helper to create series list for this test only.
|
||||
List<MutableSeries<String>> _createSeriesList(List<MyRow> data) {
|
||||
final domainAxis = new MockAxis<dynamic>();
|
||||
when(domainAxis.rangeBand).thenReturn(100.0);
|
||||
when(domainAxis.getLocation('MyCampaign1')).thenReturn(20.0);
|
||||
when(domainAxis.getLocation('MyCampaign2')).thenReturn(40.0);
|
||||
when(domainAxis.getLocation('MyCampaign3')).thenReturn(60.0);
|
||||
when(domainAxis.getLocation('MyOtherCampaign')).thenReturn(80.0);
|
||||
final measureAxis = new MockAxis<num>();
|
||||
when(measureAxis.getLocation(0)).thenReturn(0.0);
|
||||
when(measureAxis.getLocation(5)).thenReturn(5.0);
|
||||
when(measureAxis.getLocation(75)).thenReturn(75.0);
|
||||
when(measureAxis.getLocation(100)).thenReturn(100.0);
|
||||
|
||||
final color = new Color.fromHex(code: '#000000');
|
||||
|
||||
final series = new MutableSeries<String>(new Series<MyRow, String>(
|
||||
id: 'Desktop',
|
||||
domainFn: (MyRow row, _) => row.campaign,
|
||||
measureFn: (MyRow row, _) => row.clickCount,
|
||||
measureOffsetFn: (_, __) => 0,
|
||||
colorFn: (_, __) => color,
|
||||
fillColorFn: (_, __) => color,
|
||||
dashPatternFn: (_, __) => [1],
|
||||
data: data))
|
||||
..setAttr(domainAxisKey, domainAxis)
|
||||
..setAttr(measureAxisKey, measureAxis);
|
||||
|
||||
return [series];
|
||||
}
|
||||
|
||||
final canvas = new MockCanvas();
|
||||
|
||||
final myDataWithNull = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', null),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
final seriesListWithNull = _createSeriesList(myDataWithNull);
|
||||
|
||||
final myDataWithMeasures = [
|
||||
new MyRow('MyCampaign1', 5),
|
||||
new MyRow('MyCampaign2', 0),
|
||||
new MyRow('MyCampaign3', 100),
|
||||
new MyRow('MyOtherCampaign', 75),
|
||||
];
|
||||
final seriesListWithMeasures = _createSeriesList(myDataWithMeasures);
|
||||
|
||||
renderer = makeRenderer(
|
||||
config: new BarTargetLineRendererConfig(
|
||||
groupingType: BarGroupingType.grouped));
|
||||
|
||||
// Verify that only 3 lines are drawn for an initial draw with null data.
|
||||
renderer.preprocessSeries(seriesListWithNull);
|
||||
renderer.update(seriesListWithNull, true);
|
||||
canvas.drawLinePointsList.clear();
|
||||
renderer.paint(canvas, 0.5);
|
||||
expect(canvas.drawLinePointsList, hasLength(3));
|
||||
|
||||
// On animation complete, verify that only 3 lines are drawn.
|
||||
canvas.drawLinePointsList.clear();
|
||||
renderer.paint(canvas, 1.0);
|
||||
expect(canvas.drawLinePointsList, hasLength(3));
|
||||
|
||||
// Change series list where there are measures on all values, verify all
|
||||
// 4 lines were drawn
|
||||
renderer.preprocessSeries(seriesListWithMeasures);
|
||||
renderer.update(seriesListWithMeasures, true);
|
||||
canvas.drawLinePointsList.clear();
|
||||
renderer.paint(canvas, 0.5);
|
||||
expect(canvas.drawLinePointsList, hasLength(4));
|
||||
|
||||
// Change series to one with null measures, verifies all 4 lines drawn
|
||||
renderer.preprocessSeries(seriesListWithNull);
|
||||
renderer.update(seriesListWithNull, true);
|
||||
canvas.drawLinePointsList.clear();
|
||||
renderer.paint(canvas, 0.5);
|
||||
expect(canvas.drawLinePointsList, hasLength(4));
|
||||
|
||||
// On animation complete, verify that only 3 lines are drawn.
|
||||
canvas.drawLinePointsList.clear();
|
||||
renderer.paint(canvas, 1.0);
|
||||
expect(canvas.drawLinePointsList, hasLength(3));
|
||||
});
|
||||
});
|
||||
}
|
||||
1428
web/charts/common/test/chart/bar/renderer_nearest_detail_test.dart
Normal file
1428
web/charts/common/test/chart/bar/renderer_nearest_detail_test.dart
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user