--- /dev/null
+describe('Linear Scale', function() {
+
+ it ('Should register the constructor with the scale service', function() {
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ expect(Constructor).not.toBe(undefined);
+ expect(typeof Constructor).toBe('function');
+ });
+
+ it ('Should have the correct default config', function() {
+ var defaultConfig = Chart.scaleService.getScaleDefaults('linear');
+ expect(defaultConfig).toEqual({
+ display: true,
+ position: "left",
+ gridLines: {
+ show: true,
+ color: "rgba(0, 0, 0, 0.1)",
+ lineWidth: 1,
+ drawOnChartArea: true,
+ drawTicks: true, // draw ticks extending towards the label
+ zeroLineWidth: 1,
+ zeroLineColor: "rgba(0,0,0,0.25)",
+ },
+ reverse: false,
+ beginAtZero: false,
+ override: null,
+ labels: {
+ show: true,
+ mirror: false,
+ padding: 10,
+ template: "<%=value.toLocaleString()%>",
+ fontSize: 12,
+ fontStyle: "normal",
+ fontColor: "#666",
+ fontFamily: "Helvetica Neue"
+ }
+ });
+ });
+
+ it ('Should correctly determine the max & min data values', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, -5, 78, -100]
+ }, {
+ yAxisID: 'second scale',
+ data: [-1000, 1000],
+ }, {
+ yAxisID: scaleID,
+ data: [150]
+ }
+ ]
+ };
+
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var scale = new Constructor({
+ ctx: {},
+ options: Chart.scaleService.getScaleDefaults('linear'), // use default config for scale
+ data: mockData,
+ id: scaleID
+ });
+
+ expect(scale).not.toEqual(undefined); // must construct
+ expect(scale.min).toBe(undefined); // not yet set
+ expect(scale.max).toBe(undefined);
+
+ scale.calculateRange();
+ expect(scale.min).toBe(-100);
+ expect(scale.max).toBe(150);
+ });
+
+ it ('Should correctly determine the max & min for scatter data', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ xAxisID: scaleID, // for the horizontal scale
+ yAxisID: scaleID,
+ data: [{x: 10, y: 100}, {x: -10, y: 0}, {x: 0, y: 0}, {x: 99, y: 7}]
+ }]
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var verticalScale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ verticalScale.calculateRange();
+ expect(verticalScale.min).toBe(0);
+ expect(verticalScale.max).toBe(100);
+
+ var horizontalConfig = Chart.helpers.clone(config);
+ horizontalConfig.position = 'bottom';
+ var horizontalScale = new Constructor({
+ ctx: {},
+ options: horizontalConfig,
+ data: mockData,
+ id: scaleID,
+ });
+
+ horizontalScale.calculateRange();
+ expect(horizontalScale.min).toBe(-10);
+ expect(horizontalScale.max).toBe(99);
+ });
+
+ it ('Should correctly determine the min and max data values when stacked mode is turned on', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, -5, 78, -100]
+ }, {
+ yAxisID: 'second scale',
+ data: [-1000, 1000],
+ }, {
+ yAxisID: scaleID,
+ data: [150, 0, 0, -100, -10, 9]
+ }
+ ]
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ config.stacked = true; // enable scale stacked mode
+
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var scale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ scale.calculateRange();
+ expect(scale.min).toBe(-105);
+ expect(scale.max).toBe(160);
+ });
+
+ it ('Should ensure that the scale has a max and min that are not equal', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: []
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var scale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ scale.calculateRange();
+ expect(scale.min).toBe(-1);
+ expect(scale.max).toBe(1);
+ });
+
+ it ('Should generate tick marks', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ },
+ ]
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var scale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ scale.calculateRange();
+
+ expect(scale.ticks).toBe(undefined); // not set
+
+ // Large enough to be unimportant
+ var maxWidth = 400;
+ var maxHeight = 400;
+ scale.generateTicks(maxWidth, maxHeight);
+
+ // Counts down because the lines are drawn top to bottom
+ expect(scale.ticks).toEqual([80, 70, 60, 50, 40, 30, 20, 10, 0]);
+ expect(scale.start).toBe(0);
+ expect(scale.end).toBe(80);
+ });
+
+ it ('Should generate tick marks in the correct order in reversed mode', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ },
+ ]
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ config.reverse = true;
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var scale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ scale.calculateRange();
+
+ expect(scale.ticks).toBe(undefined); // not set
+
+ // Large enough to be unimportant
+ var maxWidth = 400;
+ var maxHeight = 400;
+ scale.generateTicks(maxWidth, maxHeight);
+
+ // Reverse mode makes this count up
+ expect(scale.ticks).toEqual([0, 10, 20, 30, 40, 50, 60, 70, 80]);
+ expect(scale.start).toBe(80);
+ expect(scale.end).toBe(0);
+ });
+
+ it ('Should generate tick marks using the user supplied options', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ },
+ ]
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ config.override = {
+ steps: 10,
+ start: 0,
+ stepWidth: 10
+ };
+
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var scale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ scale.calculateRange();
+
+ // Large enough to be unimportant
+ var maxWidth = 400;
+ var maxHeight = 400;
+ scale.generateTicks(maxWidth, maxHeight);
+
+ expect(scale.ticks).toEqual([100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0]);
+ expect(scale.start).toBe(0);
+ expect(scale.end).toBe(100);
+ });
+
+ it ('Should build labels using the default template', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ },
+ ]
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var scale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ scale.calculateRange();
+
+ // Large enough to be unimportant
+ var maxWidth = 400;
+ var maxHeight = 400;
+ scale.generateTicks(maxWidth, maxHeight);
+
+ // Generate labels
+ scale.buildLabels();
+
+ expect(scale.labels).toEqual(['80', '70', '60', '50', '40', '30', '20', '10', '0']);
+ });
+
+ it ('Should build labels using the user supplied callback', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ },
+ ]
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ config.labels.userCallback = function(value, index) {
+ return index.toString();
+ };
+
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var scale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ scale.calculateRange();
+
+ // Large enough to be unimportant
+ var maxWidth = 400;
+ var maxHeight = 400;
+ scale.generateTicks(maxWidth, maxHeight);
+
+ // Generate labels
+ scale.buildLabels();
+
+ // Just the index
+ expect(scale.labels).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8']);
+ });
+
+ it ('Should get the correct pixel value for a point', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ xAxisID: scaleID, // for the horizontal scale
+ yAxisID: scaleID,
+ data: []
+ }]
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
+ var Constructor = Chart.scaleService.getScaleConstructor('linear');
+ var verticalScale = new Constructor({
+ ctx: {},
+ options: config,
+ data: mockData,
+ id: scaleID
+ });
+
+ verticalScale.calculateRange();
+ verticalScale.generateTicks(50, 100);
+
+ // Fake out positioning of the scale service
+ verticalScale.left = 0;
+ verticalScale.top = 0;
+ verticalScale.right = 50;
+ verticalScale.bottom = 110;
+ verticalScale.paddingTop = 5;
+ verticalScale.paddingBottom = 5;
+ verticalScale.width = 50;
+ verticalScale.height = 110;
+
+ expect(verticalScale.getPointPixelForValue(1, 0, 0)).toBe(5); // top + paddingTop
+ expect(verticalScale.getPointPixelForValue(-1, 0, 0)).toBe(105); // bottom - paddingBottom
+ expect(verticalScale.getPointPixelForValue(0, 0, 0)).toBe(55); // halfway
+
+ var horizontalConfig = Chart.helpers.clone(config);
+ horizontalConfig.position = 'bottom';
+ var horizontalScale = new Constructor({
+ ctx: {},
+ options: horizontalConfig,
+ data: mockData,
+ id: scaleID,
+ });
+
+ horizontalScale.calculateRange();
+ horizontalScale.generateTicks(100, 50);
+
+ // Fake out positioning of the scale service
+ horizontalScale.left = 0;
+ horizontalScale.top = 0;
+ horizontalScale.right = 110;
+ horizontalScale.bottom = 50;
+ horizontalScale.paddingLeft = 5;
+ horizontalScale.paddingRight = 5;
+ horizontalScale.width = 110;
+ horizontalScale.height = 50;
+
+ // Range expands to [-2, 2] due to nicenum algorithm
+ expect(horizontalScale.getPointPixelForValue(2, 0, 0)).toBe(105); // right - paddingRight
+ expect(horizontalScale.getPointPixelForValue(-2, 0, 0)).toBe(5); // left + paddingLeft
+ expect(horizontalScale.getPointPixelForValue(0, 0, 0)).toBe(55); // halfway
+ });
+});
\ No newline at end of file