mirror of
https://github.com/cwinfo/powerdns-admin.git
synced 2025-06-15 04:26:05 +00:00
Initial commit
This commit is contained in:
@ -0,0 +1,60 @@
|
||||
describe 'Morris.Area', ->
|
||||
|
||||
describe 'svg structure', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: '2012 Q1', y: 1}, {x: '2012 Q2', y: 1}]
|
||||
lineColors: [ '#0b62a4', '#7a92a3']
|
||||
gridLineColor: '#aaa'
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['Y']
|
||||
|
||||
it 'should contain a line path for each line', ->
|
||||
chart = Morris.Area $.extend {}, defaults
|
||||
$('#graph').find("path[stroke='#0b62a4']").size().should.equal 1
|
||||
|
||||
it 'should contain a path with stroke-width 0 for each line', ->
|
||||
chart = Morris.Area $.extend {}, defaults
|
||||
$('#graph').find("path[stroke='#0b62a4']").size().should.equal 1
|
||||
|
||||
it 'should contain 5 grid lines', ->
|
||||
chart = Morris.Area $.extend {}, defaults
|
||||
$('#graph').find("path[stroke='#aaaaaa']").size().should.equal 5
|
||||
|
||||
it 'should contain 9 text elements', ->
|
||||
chart = Morris.Area $.extend {}, defaults
|
||||
$('#graph').find("text").size().should.equal 9
|
||||
|
||||
describe 'svg attributes', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: '2012 Q1', y: 1}, {x: '2012 Q2', y: 1}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['Y']
|
||||
lineColors: [ '#0b62a4', '#7a92a3']
|
||||
lineWidth: 3
|
||||
pointWidths: [5]
|
||||
pointStrokeColors: ['#ffffff']
|
||||
gridLineColor: '#aaa'
|
||||
gridStrokeWidth: 0.5
|
||||
gridTextColor: '#888'
|
||||
gridTextSize: 12
|
||||
|
||||
it 'should not be cumulative if behaveLikeLine', ->
|
||||
chart = Morris.Area $.extend {}, defaults, behaveLikeLine: true
|
||||
chart.cumulative.should.equal false
|
||||
|
||||
it 'should have a line with transparent fill if behaveLikeLine', ->
|
||||
chart = Morris.Area $.extend {}, defaults, behaveLikeLine: true
|
||||
$('#graph').find("path[fill-opacity='0.8']").size().should.equal 1
|
||||
|
||||
it 'should not have a line with transparent fill', ->
|
||||
chart = Morris.Area $.extend {}, defaults
|
||||
$('#graph').find("path[fill-opacity='0.8']").size().should.equal 0
|
||||
|
||||
it 'should have a line with the fill of a modified line color', ->
|
||||
chart = Morris.Area $.extend {}, defaults
|
||||
$('#graph').find("path[fill='#0b62a4']").size().should.equal 0
|
||||
$('#graph').find("path[fill='#7a92a3']").size().should.equal 0
|
127
app/static/global/plugins/morris/spec/lib/bar/bar_spec.coffee
Normal file
127
app/static/global/plugins/morris/spec/lib/bar/bar_spec.coffee
Normal file
@ -0,0 +1,127 @@
|
||||
describe 'Morris.Bar', ->
|
||||
describe 'when using vertical grid', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: 'foo', y: 2, z: 3}, {x: 'bar', y: 4, z: 6}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z']
|
||||
labels: ['Y', 'Z']
|
||||
barColors: [ '#0b62a4', '#7a92a3']
|
||||
gridLineColor: '#aaa'
|
||||
gridStrokeWidth: 0.5
|
||||
gridTextColor: '#888'
|
||||
gridTextSize: 12
|
||||
verticalGridCondition: (index) -> index % 2
|
||||
verticalGridColor: '#888888'
|
||||
verticalGridOpacity: '0.2'
|
||||
|
||||
describe 'svg structure', ->
|
||||
it 'should contain extra rectangles for vertical grid', ->
|
||||
$('#graph').css('height', '250px').css('width', '800px')
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("rect").size().should.equal 6
|
||||
|
||||
describe 'svg attributes', ->
|
||||
it 'should have to bars with verticalGrid.color', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("rect[fill='#{defaults.verticalGridColor}']").size().should.equal 2
|
||||
it 'should have to bars with verticalGrid.color', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("rect[fill-opacity='#{defaults.verticalGridOpacity}']").size().should.equal 2
|
||||
|
||||
describe 'svg structure', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: 'foo', y: 2, z: 3}, {x: 'bar', y: 4, z: 6}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z']
|
||||
labels: ['Y', 'Z']
|
||||
|
||||
it 'should contain a rect for each bar', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("rect").size().should.equal 4
|
||||
|
||||
it 'should contain 5 grid lines', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("path").size().should.equal 5
|
||||
|
||||
it 'should contain 7 text elements', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("text").size().should.equal 7
|
||||
|
||||
describe 'svg attributes', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: 'foo', y: 2, z: 3}, {x: 'bar', y: 4, z: 6}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z']
|
||||
labels: ['Y', 'Z']
|
||||
barColors: [ '#0b62a4', '#7a92a3']
|
||||
gridLineColor: '#aaa'
|
||||
gridStrokeWidth: 0.5
|
||||
gridTextColor: '#888'
|
||||
gridTextSize: 12
|
||||
|
||||
it 'should have a bar with the first default color', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("rect[fill='#0b62a4']").size().should.equal 2
|
||||
|
||||
it 'should have a bar with no stroke', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("rect[stroke='none']").size().should.equal 4
|
||||
|
||||
it 'should have text with configured fill color', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("text[fill='#888888']").size().should.equal 7
|
||||
|
||||
it 'should have text with configured font size', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("text[font-size='12px']").size().should.equal 7
|
||||
|
||||
describe 'when setting bar radius', ->
|
||||
describe 'svg structure', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: 'foo', y: 2, z: 3}, {x: 'bar', y: 4, z: 6}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z']
|
||||
labels: ['Y', 'Z']
|
||||
barRadius: [5, 5, 0, 0]
|
||||
|
||||
it 'should contain a path for each bar', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("path").size().should.equal 9
|
||||
|
||||
it 'should use rects if radius is too big', ->
|
||||
delete defaults.barStyle
|
||||
chart = Morris.Bar $.extend {}, defaults,
|
||||
barRadius: [300, 300, 0, 0]
|
||||
$('#graph').find("rect").size().should.equal 4
|
||||
|
||||
describe 'barSize option', ->
|
||||
describe 'svg attributes', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
barSize: 20
|
||||
data: [
|
||||
{x: '2011 Q1', y: 3, z: 2, a: 3}
|
||||
{x: '2011 Q2', y: 2, z: null, a: 1}
|
||||
{x: '2011 Q3', y: 0, z: 2, a: 4}
|
||||
{x: '2011 Q4', y: 2, z: 4, a: 3}
|
||||
],
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z', 'a']
|
||||
labels: ['Y', 'Z', 'A']
|
||||
|
||||
it 'should calc the width if too narrow for barSize', ->
|
||||
$('#graph').width('200px')
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("rect").filter((i) ->
|
||||
parseFloat($(@).attr('width'), 10) < 10
|
||||
).size().should.equal 11
|
||||
|
||||
it 'should set width to @options.barSize if possible', ->
|
||||
chart = Morris.Bar $.extend {}, defaults
|
||||
$('#graph').find("rect[width='#{defaults.barSize}']").size().should.equal 11
|
||||
|
||||
|
36
app/static/global/plugins/morris/spec/lib/bar/colours.coffee
Normal file
36
app/static/global/plugins/morris/spec/lib/bar/colours.coffee
Normal file
@ -0,0 +1,36 @@
|
||||
describe 'Morris.Bar#colorFor', ->
|
||||
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: 'foo', y: 2, z: 3}, {x: 'bar', y: 4, z: 6}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z']
|
||||
labels: ['Y', 'Z']
|
||||
|
||||
it 'should fetch colours from an array', ->
|
||||
chart = Morris.Bar $.extend {}, defaults, barColors: ['#f00', '#0f0', '#00f']
|
||||
chart.colorFor(chart.data[0], 0, 'bar').should.equal '#f00'
|
||||
chart.colorFor(chart.data[0], 0, 'hover').should.equal '#f00'
|
||||
chart.colorFor(chart.data[0], 1, 'bar').should.equal '#0f0'
|
||||
chart.colorFor(chart.data[0], 1, 'hover').should.equal '#0f0'
|
||||
chart.colorFor(chart.data[0], 2, 'bar').should.equal '#00f'
|
||||
chart.colorFor(chart.data[0], 2, 'hover').should.equal '#00f'
|
||||
chart.colorFor(chart.data[0], 3, 'bar').should.equal '#f00'
|
||||
chart.colorFor(chart.data[0], 4, 'hover').should.equal '#0f0'
|
||||
|
||||
it 'should defer to a callback', ->
|
||||
stub = sinon.stub().returns '#f00'
|
||||
chart = Morris.Bar $.extend {}, defaults, barColors: stub
|
||||
stub.reset()
|
||||
|
||||
chart.colorFor(chart.data[0], 0, 'bar')
|
||||
stub.should.have.been.calledWith(
|
||||
{x:0, y:2, label:'foo'},
|
||||
{index:0, key:'y', label:'Y'},
|
||||
'bar')
|
||||
|
||||
chart.colorFor(chart.data[0], 1, 'hover')
|
||||
stub.should.have.been.calledWith(
|
||||
{x:0, y:3, label:'foo'},
|
||||
{index:1, key:'z', label:'Z'},
|
||||
'hover')
|
38
app/static/global/plugins/morris/spec/lib/commas_spec.coffee
Normal file
38
app/static/global/plugins/morris/spec/lib/commas_spec.coffee
Normal file
@ -0,0 +1,38 @@
|
||||
describe '#commas', ->
|
||||
|
||||
it 'should insert commas into long numbers', ->
|
||||
# zero
|
||||
Morris.commas(0).should.equal("0")
|
||||
|
||||
# positive integers
|
||||
Morris.commas(1).should.equal("1")
|
||||
Morris.commas(12).should.equal("12")
|
||||
Morris.commas(123).should.equal("123")
|
||||
Morris.commas(1234).should.equal("1,234")
|
||||
Morris.commas(12345).should.equal("12,345")
|
||||
Morris.commas(123456).should.equal("123,456")
|
||||
Morris.commas(1234567).should.equal("1,234,567")
|
||||
|
||||
# negative integers
|
||||
Morris.commas(-1).should.equal("-1")
|
||||
Morris.commas(-12).should.equal("-12")
|
||||
Morris.commas(-123).should.equal("-123")
|
||||
Morris.commas(-1234).should.equal("-1,234")
|
||||
Morris.commas(-12345).should.equal("-12,345")
|
||||
Morris.commas(-123456).should.equal("-123,456")
|
||||
Morris.commas(-1234567).should.equal("-1,234,567")
|
||||
|
||||
# positive decimals
|
||||
Morris.commas(1.2).should.equal("1.2")
|
||||
Morris.commas(12.34).should.equal("12.34")
|
||||
Morris.commas(123.456).should.equal("123.456")
|
||||
Morris.commas(1234.56).should.equal("1,234.56")
|
||||
|
||||
# negative decimals
|
||||
Morris.commas(-1.2).should.equal("-1.2")
|
||||
Morris.commas(-12.34).should.equal("-12.34")
|
||||
Morris.commas(-123.456).should.equal("-123.456")
|
||||
Morris.commas(-1234.56).should.equal("-1,234.56")
|
||||
|
||||
# null
|
||||
Morris.commas(null).should.equal('-')
|
@ -0,0 +1,76 @@
|
||||
describe 'Morris.Donut', ->
|
||||
|
||||
describe 'svg structure', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [ {label: 'Jam', value: 25 },
|
||||
{label: 'Frosted', value: 40 },
|
||||
{label: 'Custard', value: 25 },
|
||||
{label: 'Sugar', value: 10 } ]
|
||||
formatter: (y) -> "#{y}%"
|
||||
|
||||
it 'should contain 2 paths for each segment', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("path").size().should.equal 8
|
||||
|
||||
it 'should contain 2 text elements for the label', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("text").size().should.equal 2
|
||||
|
||||
describe 'svg attributes', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [ {label: 'Jam', value: 25 },
|
||||
{label: 'Frosted', value: 40 },
|
||||
{label: 'Custard', value: 25 },
|
||||
{label: 'Sugar', value: 10 } ]
|
||||
formatter: (y) -> "#{y}%"
|
||||
colors: [ '#0B62A4', '#3980B5', '#679DC6', '#95BBD7']
|
||||
|
||||
it 'should have a label with font size 15', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("text[font-size='15px']").size().should.equal 1
|
||||
|
||||
it 'should have a label with font size 14', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("text[font-size='14px']").size().should.equal 1
|
||||
|
||||
it 'should have a label with font-weight 800', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("text[font-weight='800']").size().should.equal 1
|
||||
|
||||
it 'should have 1 paths with fill of first color', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("path[fill='#0b62a4']").size().should.equal 1
|
||||
|
||||
it 'should have 1 paths with stroke of first color', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("path[stroke='#0b62a4']").size().should.equal 1
|
||||
|
||||
it 'should have a path with white stroke', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("path[stroke='#ffffff']").size().should.equal 4
|
||||
|
||||
it 'should have a path with stroke-width 3', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("path[stroke-width='3']").size().should.equal 4
|
||||
|
||||
it 'should have a path with stroke-width 2', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("path[stroke-width='2']").size().should.equal 4
|
||||
|
||||
describe 'setData', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [ {label: 'One', value: 25 }, {label: "Two", value: 30} ]
|
||||
colors: ['#ff0000', '#00ff00', '#0000ff']
|
||||
|
||||
it 'should update the chart', ->
|
||||
chart = Morris.Donut $.extend {}, defaults
|
||||
$('#graph').find("path[stroke='#0000ff']").size().should.equal 0
|
||||
chart.setData [
|
||||
{ label: 'One', value: 25 }
|
||||
{ label: 'Two', value: 30 }
|
||||
{ label: 'Three', value: 35 }
|
||||
]
|
||||
$('#graph').find("path[stroke='#0000ff']").size().should.equal 1
|
@ -0,0 +1,25 @@
|
||||
describe 'Morris.Grid#autoGridLines', ->
|
||||
|
||||
beforeEach ->
|
||||
@subject = Morris.Grid.prototype.autoGridLines
|
||||
|
||||
it 'should draw at fixed intervals', ->
|
||||
@subject(0, 4, 5).should.deep.equal [0, 1, 2, 3, 4]
|
||||
@subject(0, 400, 5).should.deep.equal [0, 100, 200, 300, 400]
|
||||
|
||||
it 'should pick intervals that show significant numbers', ->
|
||||
@subject(102, 499, 5).should.deep.equal [100, 200, 300, 400, 500]
|
||||
|
||||
it 'should draw zero when it falls within [ymin..ymax]', ->
|
||||
@subject(-100, 300, 5).should.deep.equal [-100, 0, 100, 200, 300]
|
||||
@subject(-50, 350, 5).should.deep.equal [-125, 0, 125, 250, 375]
|
||||
@subject(-400, 400, 5).should.deep.equal [-400, -200, 0, 200, 400]
|
||||
@subject(100, 500, 5).should.deep.equal [100, 200, 300, 400, 500]
|
||||
@subject(-500, -100, 5).should.deep.equal [-500, -400, -300, -200, -100]
|
||||
|
||||
it 'should generate decimal labels to 2 significant figures', ->
|
||||
@subject(0, 1, 5).should.deep.equal [0, 0.25, 0.5, 0.75, 1]
|
||||
@subject(0.1, 0.5, 5).should.deep.equal [0.1, 0.2, 0.3, 0.4, 0.5]
|
||||
|
||||
it 'should use integer intervals for intervals larger than 1', ->
|
||||
@subject(0, 9, 5).should.deep.equal [0, 3, 6, 9, 12]
|
@ -0,0 +1,208 @@
|
||||
describe 'Morris.Grid#setData', ->
|
||||
|
||||
it 'should not alter user-supplied data', ->
|
||||
my_data = [{x: 1, y: 1}, {x: 2, y: 2}]
|
||||
expected_data = [{x: 1, y: 1}, {x: 2, y: 2}]
|
||||
Morris.Line
|
||||
element: 'graph'
|
||||
data: my_data
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['dontcare']
|
||||
my_data.should.deep.equal expected_data
|
||||
|
||||
describe 'ymin/ymax', ->
|
||||
beforeEach ->
|
||||
@defaults =
|
||||
element: 'graph'
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z']
|
||||
labels: ['y', 'z']
|
||||
|
||||
it 'should use a user-specified minimum and maximum value', ->
|
||||
line = Morris.Line $.extend @defaults,
|
||||
data: [{x: 1, y: 1}]
|
||||
ymin: 10
|
||||
ymax: 20
|
||||
line.ymin.should.equal 10
|
||||
line.ymax.should.equal 20
|
||||
|
||||
describe 'auto', ->
|
||||
|
||||
it 'should automatically calculate the minimum and maximum value', ->
|
||||
line = Morris.Line $.extend @defaults,
|
||||
data: [{x: 1, y: 10}, {x: 2, y: 15}, {x: 3, y: null}, {x: 4}]
|
||||
ymin: 'auto'
|
||||
ymax: 'auto'
|
||||
line.ymin.should.equal 10
|
||||
line.ymax.should.equal 15
|
||||
|
||||
it 'should automatically calculate the minimum and maximum value given no y data', ->
|
||||
line = Morris.Line $.extend @defaults,
|
||||
data: [{x: 1}, {x: 2}, {x: 3}, {x: 4}]
|
||||
ymin: 'auto'
|
||||
ymax: 'auto'
|
||||
line.ymin.should.equal 0
|
||||
line.ymax.should.equal 1
|
||||
|
||||
describe 'auto [n]', ->
|
||||
|
||||
it 'should automatically calculate the minimum and maximum value', ->
|
||||
line = Morris.Line $.extend @defaults,
|
||||
data: [{x: 1, y: 10}, {x: 2, y: 15}, {x: 3, y: null}, {x: 4}]
|
||||
ymin: 'auto 11'
|
||||
ymax: 'auto 13'
|
||||
line.ymin.should.equal 10
|
||||
line.ymax.should.equal 15
|
||||
|
||||
it 'should automatically calculate the minimum and maximum value given no data', ->
|
||||
line = Morris.Line $.extend @defaults,
|
||||
data: [{x: 1}, {x: 2}, {x: 3}, {x: 4}]
|
||||
ymin: 'auto 11'
|
||||
ymax: 'auto 13'
|
||||
line.ymin.should.equal 11
|
||||
line.ymax.should.equal 13
|
||||
|
||||
it 'should use a user-specified minimum and maximum value', ->
|
||||
line = Morris.Line $.extend @defaults,
|
||||
data: [{x: 1, y: 10}, {x: 2, y: 15}, {x: 3, y: null}, {x: 4}]
|
||||
ymin: 'auto 5'
|
||||
ymax: 'auto 20'
|
||||
line.ymin.should.equal 5
|
||||
line.ymax.should.equal 20
|
||||
|
||||
it 'should use a user-specified minimum and maximum value given no data', ->
|
||||
line = Morris.Line $.extend @defaults,
|
||||
data: [{x: 1}, {x: 2}, {x: 3}, {x: 4}]
|
||||
ymin: 'auto 5'
|
||||
ymax: 'auto 20'
|
||||
line.ymin.should.equal 5
|
||||
line.ymax.should.equal 20
|
||||
|
||||
describe 'xmin/xmax', ->
|
||||
|
||||
it 'should calculate the horizontal range', ->
|
||||
line = Morris.Line
|
||||
element: 'graph'
|
||||
data: [{x: 2, y: 2}, {x: 1, y: 1}, {x: 4, y: 4}, {x: 3, y: 3}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
line.xmin.should == 1
|
||||
line.xmax.should == 4
|
||||
|
||||
it "should pad the range if there's only one data point", ->
|
||||
line = Morris.Line
|
||||
element: 'graph'
|
||||
data: [{x: 2, y: 2}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
line.xmin.should == 1
|
||||
line.xmax.should == 3
|
||||
|
||||
describe 'sorting', ->
|
||||
|
||||
it 'should sort data when parseTime is true', ->
|
||||
line = Morris.Line
|
||||
element: 'graph'
|
||||
data: [
|
||||
{x: '2012 Q1', y: 2},
|
||||
{x: '2012 Q3', y: 1},
|
||||
{x: '2012 Q4', y: 4},
|
||||
{x: '2012 Q2', y: 3}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
line.data.map((row) -> row.label).should.deep.equal ['2012 Q1', '2012 Q2', '2012 Q3', '2012 Q4']
|
||||
|
||||
it 'should not sort data when parseTime is false', ->
|
||||
line = Morris.Line
|
||||
element: 'graph'
|
||||
data: [{x: 1, y: 2}, {x: 4, y: 1}, {x: 3, y: 4}, {x: 2, y: 3}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
parseTime: false
|
||||
line.data.map((row) -> row.label).should.deep.equal [1, 4, 3, 2]
|
||||
|
||||
describe 'timestamp data', ->
|
||||
|
||||
it 'should generate default labels for timestamp x-values', ->
|
||||
d = [
|
||||
new Date 2012, 0, 1
|
||||
new Date 2012, 0, 2
|
||||
new Date 2012, 0, 3
|
||||
new Date 2012, 0, 4
|
||||
]
|
||||
line = Morris.Line
|
||||
element: 'graph'
|
||||
data: [
|
||||
{x: d[0].getTime(), y: 2},
|
||||
{x: d[1].getTime(), y: 1},
|
||||
{x: d[2].getTime(), y: 4},
|
||||
{x: d[3].getTime(), y: 3}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
line.data.map((row) -> row.label).should.deep.equal d.map((t) -> t.toString())
|
||||
|
||||
it 'should use a user-supplied formatter for labels', ->
|
||||
line = Morris.Line
|
||||
element: 'graph'
|
||||
data: [
|
||||
{x: new Date(2012, 0, 1).getTime(), y: 2},
|
||||
{x: new Date(2012, 0, 2).getTime(), y: 1},
|
||||
{x: new Date(2012, 0, 3).getTime(), y: 4},
|
||||
{x: new Date(2012, 0, 4).getTime(), y: 3}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
dateFormat: (ts) ->
|
||||
date = new Date(ts)
|
||||
"#{date.getFullYear()}-#{date.getMonth()+1}-#{date.getDate()}"
|
||||
line.data.map((row) -> row.label).should.deep.equal ['2012-1-1', '2012-1-2', '2012-1-3', '2012-1-4']
|
||||
|
||||
it 'should parse y-values in strings', ->
|
||||
line = Morris.Line
|
||||
element: 'graph'
|
||||
data: [{x: 2, y: '12'}, {x: 1, y: '13.5'}, {x: 4, y: '14'}, {x: 3, y: '16'}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
line.ymin.should == 12
|
||||
line.ymax.should == 16
|
||||
line.data.map((row) -> row.y).should.deep.equal [[13.5], [12], [16], [14]]
|
||||
|
||||
it 'should clear the chart when empty data is supplied', ->
|
||||
line = Morris.Line
|
||||
element: 'graph',
|
||||
data: [{x: 2, y: '12'}, {x: 1, y: '13.5'}, {x: 4, y: '14'}, {x: 3, y: '16'}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
line.data.length.should.equal 4
|
||||
line.setData([])
|
||||
line.data.length.should.equal 0
|
||||
line.setData([{x: 2, y: '12'}, {x: 1, y: '13.5'}, {x: 4, y: '14'}, {x: 3, y: '16'}])
|
||||
line.data.length.should.equal 4
|
||||
|
||||
it 'should be able to add data if the chart is initialised with empty data', ->
|
||||
line = Morris.Line
|
||||
element: 'graph',
|
||||
data: []
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
line.data.length.should.equal 0
|
||||
line.setData([{x: 2, y: '12'}, {x: 1, y: '13.5'}, {x: 4, y: '14'}, {x: 3, y: '16'}])
|
||||
line.data.length.should.equal 4
|
||||
|
||||
it 'should automatically choose significant numbers for y-labels', ->
|
||||
line = Morris.Line
|
||||
element: 'graph',
|
||||
data: [{x: 1, y: 0}, {x: 2, y: 3600}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['y']
|
||||
line.grid.should == [0, 1000, 2000, 3000, 4000]
|
@ -0,0 +1,15 @@
|
||||
describe 'Morris.Grid#yLabelFormat', ->
|
||||
|
||||
it 'should use custom formatter for y labels', ->
|
||||
formatter = (label) ->
|
||||
flabel = parseFloat(label) / 1000
|
||||
"#{flabel.toFixed(1)}k"
|
||||
line = Morris.Line
|
||||
element: 'graph'
|
||||
data: [{x: 1, y: 1500}, {x: 2, y: 2500}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['dontcare']
|
||||
preUnits: "$"
|
||||
yLabelFormat: formatter
|
||||
line.yLabelFormat(1500).should.equal "1.5k"
|
64
app/static/global/plugins/morris/spec/lib/hover_spec.coffee
Normal file
64
app/static/global/plugins/morris/spec/lib/hover_spec.coffee
Normal file
@ -0,0 +1,64 @@
|
||||
describe "Morris.Hover", ->
|
||||
|
||||
describe "with dummy content", ->
|
||||
|
||||
beforeEach ->
|
||||
parent = $('<div style="width:200px;height:180px"></div>')
|
||||
.appendTo($('#test'))
|
||||
@hover = new Morris.Hover(parent: parent)
|
||||
@element = $('#test .morris-hover')
|
||||
|
||||
it "should initialise a hidden, empty popup", ->
|
||||
@element.should.exist
|
||||
@element.should.be.hidden
|
||||
@element.should.be.empty
|
||||
|
||||
describe "#show", ->
|
||||
it "should show the popup", ->
|
||||
@hover.show()
|
||||
@element.should.be.visible
|
||||
|
||||
describe "#hide", ->
|
||||
it "should hide the popup", ->
|
||||
@hover.show()
|
||||
@hover.hide()
|
||||
@element.should.be.hidden
|
||||
|
||||
describe "#html", ->
|
||||
it "should replace the contents of the element", ->
|
||||
@hover.html('<div>Foobarbaz</div>')
|
||||
@element.should.have.html('<div>Foobarbaz</div>')
|
||||
|
||||
describe "#moveTo", ->
|
||||
beforeEach ->
|
||||
@hover.html('<div style="width:84px;height:84px"></div>')
|
||||
|
||||
it "should place the popup directly above the given point", ->
|
||||
@hover.moveTo(100, 150)
|
||||
@element.should.have.css('left', '50px')
|
||||
@element.should.have.css('top', '40px')
|
||||
|
||||
it "should place the popup below the given point if it does not fit above", ->
|
||||
@hover.moveTo(100, 50)
|
||||
@element.should.have.css('left', '50px')
|
||||
@element.should.have.css('top', '60px')
|
||||
|
||||
it "should center the popup vertically if it will not fit above or below", ->
|
||||
@hover.moveTo(100, 100)
|
||||
@element.should.have.css('left', '50px')
|
||||
@element.should.have.css('top', '40px')
|
||||
|
||||
it "should center the popup vertically if no y value is supplied", ->
|
||||
@hover.moveTo(100)
|
||||
@element.should.have.css('left', '50px')
|
||||
@element.should.have.css('top', '40px')
|
||||
|
||||
describe "#update", ->
|
||||
it "should update content, show and reposition the popup", ->
|
||||
hover = new Morris.Hover(parent: $('#test'))
|
||||
html = "<div style='width:84px;height:84px'>Hello, Everyone!</div>"
|
||||
hover.update(html, 150, 200)
|
||||
el = $('#test .morris-hover')
|
||||
el.should.have.css('left', '100px')
|
||||
el.should.have.css('top', '90px')
|
||||
el.should.have.text('Hello, Everyone!')
|
@ -0,0 +1,186 @@
|
||||
describe '#labelSeries', ->
|
||||
|
||||
it 'should generate decade intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(1952, 0, 1).getTime(),
|
||||
new Date(2012, 0, 1).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["1960", new Date(1960, 0, 1).getTime()],
|
||||
["1970", new Date(1970, 0, 1).getTime()],
|
||||
["1980", new Date(1980, 0, 1).getTime()],
|
||||
["1990", new Date(1990, 0, 1).getTime()],
|
||||
["2000", new Date(2000, 0, 1).getTime()],
|
||||
["2010", new Date(2010, 0, 1).getTime()]
|
||||
])
|
||||
Morris.labelSeries(
|
||||
new Date(1952, 3, 1).getTime(),
|
||||
new Date(2012, 3, 1).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["1960", new Date(1960, 0, 1).getTime()],
|
||||
["1970", new Date(1970, 0, 1).getTime()],
|
||||
["1980", new Date(1980, 0, 1).getTime()],
|
||||
["1990", new Date(1990, 0, 1).getTime()],
|
||||
["2000", new Date(2000, 0, 1).getTime()],
|
||||
["2010", new Date(2010, 0, 1).getTime()]
|
||||
])
|
||||
|
||||
it 'should generate year intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2007, 0, 1).getTime(),
|
||||
new Date(2012, 0, 1).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["2007", new Date(2007, 0, 1).getTime()],
|
||||
["2008", new Date(2008, 0, 1).getTime()],
|
||||
["2009", new Date(2009, 0, 1).getTime()],
|
||||
["2010", new Date(2010, 0, 1).getTime()],
|
||||
["2011", new Date(2011, 0, 1).getTime()],
|
||||
["2012", new Date(2012, 0, 1).getTime()]
|
||||
])
|
||||
Morris.labelSeries(
|
||||
new Date(2007, 3, 1).getTime(),
|
||||
new Date(2012, 3, 1).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["2008", new Date(2008, 0, 1).getTime()],
|
||||
["2009", new Date(2009, 0, 1).getTime()],
|
||||
["2010", new Date(2010, 0, 1).getTime()],
|
||||
["2011", new Date(2011, 0, 1).getTime()],
|
||||
["2012", new Date(2012, 0, 1).getTime()]
|
||||
])
|
||||
|
||||
it 'should generate month intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 0, 1).getTime(),
|
||||
new Date(2012, 5, 1).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["2012-01", new Date(2012, 0, 1).getTime()],
|
||||
["2012-02", new Date(2012, 1, 1).getTime()],
|
||||
["2012-03", new Date(2012, 2, 1).getTime()],
|
||||
["2012-04", new Date(2012, 3, 1).getTime()],
|
||||
["2012-05", new Date(2012, 4, 1).getTime()],
|
||||
["2012-06", new Date(2012, 5, 1).getTime()]
|
||||
])
|
||||
|
||||
it 'should generate week intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 0, 1).getTime(),
|
||||
new Date(2012, 1, 10).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["2012-01-01", new Date(2012, 0, 1).getTime()],
|
||||
["2012-01-08", new Date(2012, 0, 8).getTime()],
|
||||
["2012-01-15", new Date(2012, 0, 15).getTime()],
|
||||
["2012-01-22", new Date(2012, 0, 22).getTime()],
|
||||
["2012-01-29", new Date(2012, 0, 29).getTime()],
|
||||
["2012-02-05", new Date(2012, 1, 5).getTime()]
|
||||
])
|
||||
|
||||
it 'should generate day intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 0, 1).getTime(),
|
||||
new Date(2012, 0, 6).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["2012-01-01", new Date(2012, 0, 1).getTime()],
|
||||
["2012-01-02", new Date(2012, 0, 2).getTime()],
|
||||
["2012-01-03", new Date(2012, 0, 3).getTime()],
|
||||
["2012-01-04", new Date(2012, 0, 4).getTime()],
|
||||
["2012-01-05", new Date(2012, 0, 5).getTime()],
|
||||
["2012-01-06", new Date(2012, 0, 6).getTime()]
|
||||
])
|
||||
|
||||
it 'should generate hour intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 0, 1, 0).getTime(),
|
||||
new Date(2012, 0, 1, 5).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["00:00", new Date(2012, 0, 1, 0).getTime()],
|
||||
["01:00", new Date(2012, 0, 1, 1).getTime()],
|
||||
["02:00", new Date(2012, 0, 1, 2).getTime()],
|
||||
["03:00", new Date(2012, 0, 1, 3).getTime()],
|
||||
["04:00", new Date(2012, 0, 1, 4).getTime()],
|
||||
["05:00", new Date(2012, 0, 1, 5).getTime()]
|
||||
])
|
||||
|
||||
it 'should generate half-hour intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 0, 1, 0, 0).getTime(),
|
||||
new Date(2012, 0, 1, 2, 30).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["00:00", new Date(2012, 0, 1, 0, 0).getTime()],
|
||||
["00:30", new Date(2012, 0, 1, 0, 30).getTime()],
|
||||
["01:00", new Date(2012, 0, 1, 1, 0).getTime()],
|
||||
["01:30", new Date(2012, 0, 1, 1, 30).getTime()],
|
||||
["02:00", new Date(2012, 0, 1, 2, 0).getTime()],
|
||||
["02:30", new Date(2012, 0, 1, 2, 30).getTime()]
|
||||
])
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 4, 12, 0, 0).getTime(),
|
||||
new Date(2012, 4, 12, 2, 30).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["00:00", new Date(2012, 4, 12, 0, 0).getTime()],
|
||||
["00:30", new Date(2012, 4, 12, 0, 30).getTime()],
|
||||
["01:00", new Date(2012, 4, 12, 1, 0).getTime()],
|
||||
["01:30", new Date(2012, 4, 12, 1, 30).getTime()],
|
||||
["02:00", new Date(2012, 4, 12, 2, 0).getTime()],
|
||||
["02:30", new Date(2012, 4, 12, 2, 30).getTime()]
|
||||
])
|
||||
|
||||
it 'should generate fifteen-minute intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 0, 1, 0, 0).getTime(),
|
||||
new Date(2012, 0, 1, 1, 15).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["00:00", new Date(2012, 0, 1, 0, 0).getTime()],
|
||||
["00:15", new Date(2012, 0, 1, 0, 15).getTime()],
|
||||
["00:30", new Date(2012, 0, 1, 0, 30).getTime()],
|
||||
["00:45", new Date(2012, 0, 1, 0, 45).getTime()],
|
||||
["01:00", new Date(2012, 0, 1, 1, 0).getTime()],
|
||||
["01:15", new Date(2012, 0, 1, 1, 15).getTime()]
|
||||
])
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 4, 12, 0, 0).getTime(),
|
||||
new Date(2012, 4, 12, 1, 15).getTime(),
|
||||
1000
|
||||
).should.deep.equal([
|
||||
["00:00", new Date(2012, 4, 12, 0, 0).getTime()],
|
||||
["00:15", new Date(2012, 4, 12, 0, 15).getTime()],
|
||||
["00:30", new Date(2012, 4, 12, 0, 30).getTime()],
|
||||
["00:45", new Date(2012, 4, 12, 0, 45).getTime()],
|
||||
["01:00", new Date(2012, 4, 12, 1, 0).getTime()],
|
||||
["01:15", new Date(2012, 4, 12, 1, 15).getTime()]
|
||||
])
|
||||
|
||||
it 'should override automatic intervals', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2011, 11, 12).getTime(),
|
||||
new Date(2012, 0, 12).getTime(),
|
||||
1000,
|
||||
"year"
|
||||
).should.deep.equal([
|
||||
["2012", new Date(2012, 0, 1).getTime()]
|
||||
])
|
||||
|
||||
it 'should apply custom formatters', ->
|
||||
Morris.labelSeries(
|
||||
new Date(2012, 0, 1).getTime(),
|
||||
new Date(2012, 0, 6).getTime(),
|
||||
1000,
|
||||
"day",
|
||||
(d) -> "#{d.getMonth()+1}/#{d.getDate()}/#{d.getFullYear()}"
|
||||
).should.deep.equal([
|
||||
["1/1/2012", new Date(2012, 0, 1).getTime()],
|
||||
["1/2/2012", new Date(2012, 0, 2).getTime()],
|
||||
["1/3/2012", new Date(2012, 0, 3).getTime()],
|
||||
["1/4/2012", new Date(2012, 0, 4).getTime()],
|
||||
["1/5/2012", new Date(2012, 0, 5).getTime()],
|
||||
["1/6/2012", new Date(2012, 0, 6).getTime()]
|
||||
])
|
211
app/static/global/plugins/morris/spec/lib/line/line_spec.coffee
Normal file
211
app/static/global/plugins/morris/spec/lib/line/line_spec.coffee
Normal file
@ -0,0 +1,211 @@
|
||||
describe 'Morris.Line', ->
|
||||
|
||||
it 'should raise an error when the placeholder element is not found', ->
|
||||
my_data = [{x: 1, y: 1}, {x: 2, y: 2}]
|
||||
fn = ->
|
||||
Morris.Line(
|
||||
element: "thisplacedoesnotexist"
|
||||
data: my_data
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['dontcare']
|
||||
)
|
||||
fn.should.throw(/Graph container element not found/)
|
||||
|
||||
it 'should make point styles customizable', ->
|
||||
my_data = [{x: 1, y: 1}, {x: 2, y: 2}]
|
||||
red = '#ff0000'
|
||||
blue = '#0000ff'
|
||||
chart = Morris.Line
|
||||
element: 'graph'
|
||||
data: my_data
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['dontcare']
|
||||
pointStrokeColors: [red, blue]
|
||||
pointStrokeWidths: [1, 2]
|
||||
pointFillColors: [null, red]
|
||||
chart.pointStrokeWidthForSeries(0).should.equal 1
|
||||
chart.pointStrokeColorForSeries(0).should.equal red
|
||||
chart.pointStrokeWidthForSeries(1).should.equal 2
|
||||
chart.pointStrokeColorForSeries(1).should.equal blue
|
||||
chart.colorFor(chart.data[0], 0, 'point').should.equal chart.colorFor(chart.data[0], 0, 'line')
|
||||
chart.colorFor(chart.data[1], 1, 'point').should.equal red
|
||||
|
||||
describe 'generating column labels', ->
|
||||
|
||||
it 'should use user-supplied x value strings by default', ->
|
||||
chart = Morris.Line
|
||||
element: 'graph'
|
||||
data: [{x: '2012 Q1', y: 1}, {x: '2012 Q2', y: 1}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['dontcare']
|
||||
chart.data.map((x) -> x.label).should == ['2012 Q1', '2012 Q2']
|
||||
|
||||
it 'should use a default format for timestamp x-values', ->
|
||||
d1 = new Date(2012, 0, 1)
|
||||
d2 = new Date(2012, 0, 2)
|
||||
chart = Morris.Line
|
||||
element: 'graph'
|
||||
data: [{x: d1.getTime(), y: 1}, {x: d2.getTime(), y: 1}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['dontcare']
|
||||
chart.data.map((x) -> x.label).should == [d2.toString(), d1.toString()]
|
||||
|
||||
it 'should use user-defined formatters', ->
|
||||
d = new Date(2012, 0, 1)
|
||||
chart = Morris.Line
|
||||
element: 'graph'
|
||||
data: [{x: d.getTime(), y: 1}, {x: '2012-01-02', y: 1}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['dontcare']
|
||||
dateFormat: (d) ->
|
||||
x = new Date(d)
|
||||
"#{x.getYear()}/#{x.getMonth()+1}/#{x.getDay()}"
|
||||
chart.data.map((x) -> x.label).should == ['2012/1/1', '2012/1/2']
|
||||
|
||||
describe 'rendering lines', ->
|
||||
beforeEach ->
|
||||
@defaults =
|
||||
element: 'graph'
|
||||
data: [{x:0, y:1, z:0}, {x:1, y:0, z:1}, {x:2, y:1, z:0}, {x:3, y:0, z:1}, {x:4, y:1, z:0}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z']
|
||||
labels: ['y', 'z']
|
||||
lineColors: ['#abcdef', '#fedcba']
|
||||
smooth: true
|
||||
|
||||
shouldHavePath = (regex, color = '#abcdef') ->
|
||||
# Matches an SVG path element within the rendered chart.
|
||||
#
|
||||
# Sneakily uses line colors to differentiate between paths within
|
||||
# the chart.
|
||||
$('#graph').find("path[stroke='#{color}']").attr('d').should.match regex
|
||||
|
||||
it 'should generate smooth lines when options.smooth is true', ->
|
||||
Morris.Line @defaults
|
||||
shouldHavePath /M[\d\.]+,[\d\.]+(C[\d\.]+(,[\d\.]+){5}){4}/
|
||||
|
||||
it 'should generate jagged lines when options.smooth is false', ->
|
||||
Morris.Line $.extend(@defaults, smooth: false)
|
||||
shouldHavePath /M[\d\.]+,[\d\.]+(L[\d\.]+,[\d\.]+){4}/
|
||||
|
||||
it 'should generate smooth/jagged lines according to the value for each series when options.smooth is an array', ->
|
||||
Morris.Line $.extend(@defaults, smooth: ['y'])
|
||||
shouldHavePath /M[\d\.]+,[\d\.]+(C[\d\.]+(,[\d\.]+){5}){4}/, '#abcdef'
|
||||
shouldHavePath /M[\d\.]+,[\d\.]+(L[\d\.]+,[\d\.]+){4}/, '#fedcba'
|
||||
|
||||
it 'should ignore undefined values', ->
|
||||
@defaults.data[2].y = undefined
|
||||
Morris.Line @defaults
|
||||
shouldHavePath /M[\d\.]+,[\d\.]+(C[\d\.]+(,[\d\.]+){5}){3}/
|
||||
|
||||
it 'should break the line at null values', ->
|
||||
@defaults.data[2].y = null
|
||||
Morris.Line @defaults
|
||||
shouldHavePath /(M[\d\.]+,[\d\.]+C[\d\.]+(,[\d\.]+){5}){2}/
|
||||
|
||||
it 'should make line width customizable', ->
|
||||
chart = Morris.Line $.extend(@defaults, lineWidth: [1, 2])
|
||||
chart.lineWidthForSeries(0).should.equal 1
|
||||
chart.lineWidthForSeries(1).should.equal 2
|
||||
|
||||
describe '#createPath', ->
|
||||
|
||||
it 'should generate a smooth line', ->
|
||||
testData = [{x: 0, y: 10}, {x: 10, y: 0}, {x: 20, y: 10}]
|
||||
path = Morris.Line.createPath(testData, true, 20)
|
||||
path.should.equal 'M0,10C2.5,7.5,7.5,0,10,0C12.5,0,17.5,7.5,20,10'
|
||||
|
||||
it 'should generate a jagged line', ->
|
||||
testData = [{x: 0, y: 10}, {x: 10, y: 0}, {x: 20, y: 10}]
|
||||
path = Morris.Line.createPath(testData, false, 20)
|
||||
path.should.equal 'M0,10L10,0L20,10'
|
||||
|
||||
it 'should prevent paths from descending below the bottom of the chart', ->
|
||||
testData = [{x: 0, y: 20}, {x: 10, y: 30}, {x: 20, y: 10}]
|
||||
path = Morris.Line.createPath(testData, true, 30)
|
||||
path.should.equal 'M0,20C2.5,22.5,7.5,30,10,30C12.5,28.75,17.5,15,20,10'
|
||||
|
||||
it 'should break the line at null values', ->
|
||||
testData = [{x: 0, y: 10}, {x: 10, y: 0}, {x: 20, y: null}, {x: 30, y: 10}, {x: 40, y: 0}]
|
||||
path = Morris.Line.createPath(testData, true, 20)
|
||||
path.should.equal 'M0,10C2.5,7.5,7.5,2.5,10,0M30,10C32.5,7.5,37.5,2.5,40,0'
|
||||
|
||||
it 'should ignore leading and trailing null values', ->
|
||||
testData = [{x: 0, y: null}, {x: 10, y: 10}, {x: 20, y: 0}, {x: 30, y: 10}, {x: 40, y: null}]
|
||||
path = Morris.Line.createPath(testData, true, 20)
|
||||
path.should.equal 'M10,10C12.5,7.5,17.5,0,20,0C22.5,0,27.5,7.5,30,10'
|
||||
|
||||
describe 'svg structure', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: '2012 Q1', y: 1}, {x: '2012 Q2', y: 1}]
|
||||
lineColors: [ '#0b62a4', '#7a92a3']
|
||||
xkey: 'x'
|
||||
ykeys: ['y']
|
||||
labels: ['dontcare']
|
||||
|
||||
it 'should contain a path that represents the line', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("path[stroke='#0b62a4']").size().should.equal 1
|
||||
|
||||
it 'should contain a circle for each data point', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("circle").size().should.equal 2
|
||||
|
||||
it 'should contain 5 grid lines', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("path[stroke='#aaaaaa']").size().should.equal 5
|
||||
|
||||
it 'should contain 9 text elements', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("text").size().should.equal 9
|
||||
|
||||
describe 'svg attributes', ->
|
||||
defaults =
|
||||
element: 'graph'
|
||||
data: [{x: '2012 Q1', y: 1}, {x: '2012 Q2', y: 1}]
|
||||
xkey: 'x'
|
||||
ykeys: ['y', 'z']
|
||||
labels: ['Y', 'Z']
|
||||
lineColors: [ '#0b62a4', '#7a92a3']
|
||||
lineWidth: 3
|
||||
pointStrokeWidths: [5]
|
||||
pointStrokeColors: ['#ffffff']
|
||||
gridLineColor: '#aaa'
|
||||
gridStrokeWidth: 0.5
|
||||
gridTextColor: '#888'
|
||||
gridTextSize: 12
|
||||
pointSize: [5]
|
||||
|
||||
it 'should have circles with configured fill color', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("circle[fill='#0b62a4']").size().should.equal 2
|
||||
|
||||
it 'should have circles with configured stroke width', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("circle[stroke-width='5']").size().should.equal 2
|
||||
|
||||
it 'should have circles with configured stroke color', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("circle[stroke='#ffffff']").size().should.equal 2
|
||||
|
||||
it 'should have line with configured line width', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("path[stroke-width='3']").size().should.equal 1
|
||||
|
||||
it 'should have text with configured font size', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("text[font-size='12px']").size().should.equal 9
|
||||
|
||||
it 'should have text with configured font size', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("text[fill='#888888']").size().should.equal 9
|
||||
|
||||
it 'should have circle with configured size', ->
|
||||
chart = Morris.Line $.extend {}, defaults
|
||||
$('#graph').find("circle[r='5']").size().should.equal 2
|
17
app/static/global/plugins/morris/spec/lib/pad_spec.coffee
Normal file
17
app/static/global/plugins/morris/spec/lib/pad_spec.coffee
Normal file
@ -0,0 +1,17 @@
|
||||
describe '#pad', ->
|
||||
|
||||
it 'should pad numbers', ->
|
||||
Morris.pad2(0).should.equal("00")
|
||||
Morris.pad2(1).should.equal("01")
|
||||
Morris.pad2(2).should.equal("02")
|
||||
Morris.pad2(3).should.equal("03")
|
||||
Morris.pad2(4).should.equal("04")
|
||||
Morris.pad2(5).should.equal("05")
|
||||
Morris.pad2(6).should.equal("06")
|
||||
Morris.pad2(7).should.equal("07")
|
||||
Morris.pad2(8).should.equal("08")
|
||||
Morris.pad2(9).should.equal("09")
|
||||
Morris.pad2(10).should.equal("10")
|
||||
Morris.pad2(12).should.equal("12")
|
||||
Morris.pad2(34).should.equal("34")
|
||||
Morris.pad2(123).should.equal("123")
|
@ -0,0 +1,35 @@
|
||||
describe '#parseTime', ->
|
||||
|
||||
it 'should parse years', ->
|
||||
Morris.parseDate('2012').should.equal(new Date(2012, 0, 1).getTime())
|
||||
|
||||
it 'should parse quarters', ->
|
||||
Morris.parseDate('2012 Q1').should.equal(new Date(2012, 2, 1).getTime())
|
||||
|
||||
it 'should parse months', ->
|
||||
Morris.parseDate('2012-09').should.equal(new Date(2012, 8, 1).getTime())
|
||||
Morris.parseDate('2012-10').should.equal(new Date(2012, 9, 1).getTime())
|
||||
|
||||
it 'should parse dates', ->
|
||||
Morris.parseDate('2012-09-15').should.equal(new Date(2012, 8, 15).getTime())
|
||||
Morris.parseDate('2012-10-15').should.equal(new Date(2012, 9, 15).getTime())
|
||||
|
||||
it 'should parse times', ->
|
||||
Morris.parseDate("2012-10-15 12:34").should.equal(new Date(2012, 9, 15, 12, 34).getTime())
|
||||
Morris.parseDate("2012-10-15T12:34").should.equal(new Date(2012, 9, 15, 12, 34).getTime())
|
||||
Morris.parseDate("2012-10-15 12:34:55").should.equal(new Date(2012, 9, 15, 12, 34, 55).getTime())
|
||||
Morris.parseDate("2012-10-15T12:34:55").should.equal(new Date(2012, 9, 15, 12, 34, 55).getTime())
|
||||
|
||||
it 'should parse times with timezones', ->
|
||||
Morris.parseDate("2012-10-15T12:34+0100").should.equal(Date.UTC(2012, 9, 15, 11, 34))
|
||||
Morris.parseDate("2012-10-15T12:34+02:00").should.equal(Date.UTC(2012, 9, 15, 10, 34))
|
||||
Morris.parseDate("2012-10-15T12:34-0100").should.equal(Date.UTC(2012, 9, 15, 13, 34))
|
||||
Morris.parseDate("2012-10-15T12:34-02:00").should.equal(Date.UTC(2012, 9, 15, 14, 34))
|
||||
Morris.parseDate("2012-10-15T12:34:55Z").should.equal(Date.UTC(2012, 9, 15, 12, 34, 55))
|
||||
Morris.parseDate("2012-10-15T12:34:55+0600").should.equal(Date.UTC(2012, 9, 15, 6, 34, 55))
|
||||
Morris.parseDate("2012-10-15T12:34:55+04:00").should.equal(Date.UTC(2012, 9, 15, 8, 34, 55))
|
||||
Morris.parseDate("2012-10-15T12:34:55-0600").should.equal(Date.UTC(2012, 9, 15, 18, 34, 55))
|
||||
|
||||
it 'should pass-through timestamps', ->
|
||||
Morris.parseDate(new Date(2012, 9, 15, 12, 34, 55, 123).getTime())
|
||||
.should.equal(new Date(2012, 9, 15, 12, 34, 55, 123).getTime())
|
34
app/static/global/plugins/morris/spec/specs.html
Normal file
34
app/static/global/plugins/morris/spec/specs.html
Normal file
@ -0,0 +1,34 @@
|
||||
<!doctype html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>morris.js tests</title>
|
||||
<link rel="stylesheet" href="../bower_components/mocha/mocha.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="../morris.css" type="text/css" media="screen" />
|
||||
<!-- jQuery packaging changed for 2.1.0, so try to load both paths, one will work. -->
|
||||
<script src="../bower_components/jquery/dist/jquery.js"></script>
|
||||
<script src="../bower_components/jquery/jquery.js"></script>
|
||||
<script type="text/javascript" src="../bower_components/raphael/raphael-min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
|
||||
<script type="text/javascript" src="../bower_components/mocha/mocha.js"></script>
|
||||
<script type="text/javascript" src="../bower_components/chai/chai.js"></script>
|
||||
<script type="text/javascript" src="../bower_components/chai-jquery/chai-jquery.js"></script>
|
||||
<script type="text/javascript" src="../bower_components/sinon/index.js"></script>
|
||||
<script type="text/javascript" src="../bower_components/sinon-chai/lib/sinon-chai.js"></script>
|
||||
<script>
|
||||
mocha.setup('bdd');
|
||||
should = chai.should();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="../morris.js"></script>
|
||||
<script type="text/javascript" src="../build/spec.js"></script>
|
||||
<div id="test" style="width: 400px; height: 200px;"></div>
|
||||
<script>
|
||||
if (navigator.userAgent.indexOf('PhantomJS') < 0) {
|
||||
mocha.run();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,6 @@
|
||||
beforeEach ->
|
||||
placeholder = $('<div id="graph" style="width: 600px; height: 400px"></div>')
|
||||
$('#test').append(placeholder)
|
||||
|
||||
afterEach ->
|
||||
$('#test').empty()
|
56
app/static/global/plugins/morris/spec/viz/examples.js
Normal file
56
app/static/global/plugins/morris/spec/viz/examples.js
Normal file
@ -0,0 +1,56 @@
|
||||
var webpage = require("webpage"),
|
||||
fs = require("fs");
|
||||
|
||||
var html_path = fs.absolute("test.html");
|
||||
var examples = [];
|
||||
|
||||
function run_example(example_index) {
|
||||
if (example_index >= examples.length) {
|
||||
phantom.exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
var example = examples[example_index];
|
||||
var snapshot_index = 0;
|
||||
var page = webpage.create();
|
||||
|
||||
page.viewportSize = { width: 500, height: 300 };
|
||||
page.clipRect = { width: 500, height: 300 };
|
||||
page.onAlert = function (msg) {
|
||||
var e = JSON.parse(msg);
|
||||
if (e.fn == "snapshot") {
|
||||
page.render("output/" + example.name + snapshot_index + ".png");
|
||||
snapshot_index += 1;
|
||||
} else if (e.fn == "mousemove") {
|
||||
page.sendEvent("mousemove", e.x, e.y);
|
||||
}
|
||||
};
|
||||
|
||||
page.open(html_path, function (status) {
|
||||
if (status == "fail") {
|
||||
console.log("Failed to load test page: " + example.name);
|
||||
phantom.exit(1);
|
||||
} else {
|
||||
page.evaluate(example.runner);
|
||||
}
|
||||
page.close();
|
||||
run_example(example_index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
exports.def = function (name, runner) {
|
||||
examples.push({ name: name, runner: runner });
|
||||
};
|
||||
|
||||
exports.run = function () {
|
||||
if (fs.isDirectory("output")) {
|
||||
fs.list("output").forEach(function (path) {
|
||||
if (path != "." && path != "..") {
|
||||
fs.remove("output/" + path);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fs.makeDirectory("output");
|
||||
}
|
||||
run_example(0);
|
||||
};
|
BIN
app/static/global/plugins/morris/spec/viz/exemplary/area0.png
Normal file
BIN
app/static/global/plugins/morris/spec/viz/exemplary/area0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
app/static/global/plugins/morris/spec/viz/exemplary/bar0.png
Normal file
BIN
app/static/global/plugins/morris/spec/viz/exemplary/bar0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
BIN
app/static/global/plugins/morris/spec/viz/exemplary/line0.png
Normal file
BIN
app/static/global/plugins/morris/spec/viz/exemplary/line0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
32
app/static/global/plugins/morris/spec/viz/run.sh
Normal file
32
app/static/global/plugins/morris/spec/viz/run.sh
Normal file
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
# visual_specs.js creates output in output/XXX.png
|
||||
phantomjs visual_specs.js
|
||||
|
||||
# clear out old diffs
|
||||
mkdir -p diff
|
||||
rm -f diff/*
|
||||
|
||||
# generate diffs
|
||||
PASS=1
|
||||
for i in exemplary/*.png
|
||||
do
|
||||
FN=`basename $i`
|
||||
perceptualdiff $i output/$FN -output diff/$FN
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "OK: $FN"
|
||||
else
|
||||
echo "FAIL: $FN"
|
||||
PASS=0
|
||||
fi
|
||||
done
|
||||
|
||||
# pass / fail
|
||||
if [ $PASS -eq 1 ]
|
||||
then
|
||||
echo "Success."
|
||||
else
|
||||
echo "Failed."
|
||||
exit 1
|
||||
fi
|
34
app/static/global/plugins/morris/spec/viz/test.html
Normal file
34
app/static/global/plugins/morris/spec/viz/test.html
Normal file
@ -0,0 +1,34 @@
|
||||
<!doctype html>
|
||||
<head>
|
||||
<!-- jQuery packaging changed for 2.1.0, so try to load both paths, one will work. -->
|
||||
<script src="../../bower_components/jquery/dist/jquery.js"></script>
|
||||
<script src="../../bower_components/jquery/jquery.js"></script>
|
||||
<script src="../../bower_components/raphael/raphael-min.js"></script>
|
||||
<script src="../../morris.js"></script>
|
||||
<link rel="stylesheet" href="../../morris.css">
|
||||
<style>
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: white;
|
||||
}
|
||||
#chart {
|
||||
width: 500px;
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function bridge(e) {
|
||||
window.alert(JSON.stringify(e));
|
||||
}
|
||||
window.snapshot = function () {
|
||||
bridge({ fn: "snapshot" });
|
||||
};
|
||||
window.mousemove = function (x, y) {
|
||||
bridge({ fn: "mousemove", x: x, y: y });
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="chart"></div>
|
||||
</body>
|
66
app/static/global/plugins/morris/spec/viz/visual_specs.js
Normal file
66
app/static/global/plugins/morris/spec/viz/visual_specs.js
Normal file
@ -0,0 +1,66 @@
|
||||
var examples = require('./examples');
|
||||
|
||||
examples.def('line', function () {
|
||||
Morris.Line({
|
||||
element: 'chart',
|
||||
data: [
|
||||
{ x: 0, y: 10, z: 30 }, { x: 1, y: 20, z: 20 },
|
||||
{ x: 2, y: 30, z: 10 }, { x: 3, y: 30, z: 10 },
|
||||
{ x: 4, y: 20, z: 20 }, { x: 5, y: 10, z: 30 }
|
||||
],
|
||||
xkey: 'x',
|
||||
ykeys: ['y', 'z'],
|
||||
labels: ['y', 'z'],
|
||||
parseTime: false
|
||||
});
|
||||
window.snapshot();
|
||||
});
|
||||
|
||||
examples.def('area', function () {
|
||||
Morris.Area({
|
||||
element: 'chart',
|
||||
data: [
|
||||
{ x: 0, y: 1, z: 1 }, { x: 1, y: 2, z: 1 },
|
||||
{ x: 2, y: 3, z: 1 }, { x: 3, y: 3, z: 1 },
|
||||
{ x: 4, y: 2, z: 1 }, { x: 5, y: 1, z: 1 }
|
||||
],
|
||||
xkey: 'x',
|
||||
ykeys: ['y', 'z'],
|
||||
labels: ['y', 'z'],
|
||||
parseTime: false
|
||||
});
|
||||
window.snapshot();
|
||||
});
|
||||
|
||||
examples.def('bar', function () {
|
||||
Morris.Bar({
|
||||
element: 'chart',
|
||||
data: [
|
||||
{ x: 0, y: 1, z: 3 }, { x: 1, y: 2, z: 2 },
|
||||
{ x: 2, y: 3, z: 1 }, { x: 3, y: 3, z: 1 },
|
||||
{ x: 4, y: 2, z: 2 }, { x: 5, y: 1, z: 3 }
|
||||
],
|
||||
xkey: 'x',
|
||||
ykeys: ['y', 'z'],
|
||||
labels: ['y', 'z']
|
||||
});
|
||||
window.snapshot();
|
||||
});
|
||||
|
||||
examples.def('stacked_bar', function () {
|
||||
Morris.Bar({
|
||||
element: 'chart',
|
||||
data: [
|
||||
{ x: 0, y: 1, z: 1 }, { x: 1, y: 2, z: 1 },
|
||||
{ x: 2, y: 3, z: 1 }, { x: 3, y: 3, z: 1 },
|
||||
{ x: 4, y: 2, z: 1 }, { x: 5, y: 1, z: 1 }
|
||||
],
|
||||
xkey: 'x',
|
||||
ykeys: ['y', 'z'],
|
||||
labels: ['y', 'z'],
|
||||
stacked: true
|
||||
});
|
||||
window.snapshot();
|
||||
});
|
||||
|
||||
examples.run();
|
Reference in New Issue
Block a user