aboutsummaryrefslogtreecommitdiffhomepage
path: root/public/bower_components/morris.js/spec
diff options
context:
space:
mode:
Diffstat (limited to 'public/bower_components/morris.js/spec')
-rw-r--r--public/bower_components/morris.js/spec/lib/area/area_spec.coffee60
-rw-r--r--public/bower_components/morris.js/spec/lib/bar/bar_spec.coffee127
-rw-r--r--public/bower_components/morris.js/spec/lib/bar/colours.coffee36
-rw-r--r--public/bower_components/morris.js/spec/lib/commas_spec.coffee38
-rw-r--r--public/bower_components/morris.js/spec/lib/donut/donut_spec.coffee76
-rw-r--r--public/bower_components/morris.js/spec/lib/grid/auto_grid_lines_spec.coffee25
-rw-r--r--public/bower_components/morris.js/spec/lib/grid/set_data_spec.coffee208
-rw-r--r--public/bower_components/morris.js/spec/lib/grid/y_label_format_spec.coffee15
-rw-r--r--public/bower_components/morris.js/spec/lib/hover_spec.coffee64
-rw-r--r--public/bower_components/morris.js/spec/lib/label_series_spec.coffee186
-rw-r--r--public/bower_components/morris.js/spec/lib/line/line_spec.coffee211
-rw-r--r--public/bower_components/morris.js/spec/lib/pad_spec.coffee17
-rw-r--r--public/bower_components/morris.js/spec/lib/parse_time_spec.coffee35
-rw-r--r--public/bower_components/morris.js/spec/specs.html34
-rw-r--r--public/bower_components/morris.js/spec/support/placeholder.coffee6
-rw-r--r--public/bower_components/morris.js/spec/viz/examples.js56
-rw-r--r--public/bower_components/morris.js/spec/viz/exemplary/area0.pngbin0 -> 18402 bytes
-rw-r--r--public/bower_components/morris.js/spec/viz/exemplary/bar0.pngbin0 -> 6936 bytes
-rw-r--r--public/bower_components/morris.js/spec/viz/exemplary/line0.pngbin0 -> 22812 bytes
-rw-r--r--public/bower_components/morris.js/spec/viz/exemplary/stacked_bar0.pngbin0 -> 5859 bytes
-rwxr-xr-xpublic/bower_components/morris.js/spec/viz/run.sh32
-rw-r--r--public/bower_components/morris.js/spec/viz/test.html34
-rw-r--r--public/bower_components/morris.js/spec/viz/visual_specs.js66
23 files changed, 1326 insertions, 0 deletions
diff --git a/public/bower_components/morris.js/spec/lib/area/area_spec.coffee b/public/bower_components/morris.js/spec/lib/area/area_spec.coffee
new file mode 100644
index 0000000..fa36b2e
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/area/area_spec.coffee
@@ -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
diff --git a/public/bower_components/morris.js/spec/lib/bar/bar_spec.coffee b/public/bower_components/morris.js/spec/lib/bar/bar_spec.coffee
new file mode 100644
index 0000000..c647c53
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/bar/bar_spec.coffee
@@ -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
+
+
diff --git a/public/bower_components/morris.js/spec/lib/bar/colours.coffee b/public/bower_components/morris.js/spec/lib/bar/colours.coffee
new file mode 100644
index 0000000..ebe5469
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/bar/colours.coffee
@@ -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')
diff --git a/public/bower_components/morris.js/spec/lib/commas_spec.coffee b/public/bower_components/morris.js/spec/lib/commas_spec.coffee
new file mode 100644
index 0000000..9c14887
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/commas_spec.coffee
@@ -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('-')
diff --git a/public/bower_components/morris.js/spec/lib/donut/donut_spec.coffee b/public/bower_components/morris.js/spec/lib/donut/donut_spec.coffee
new file mode 100644
index 0000000..d8313f9
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/donut/donut_spec.coffee
@@ -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
diff --git a/public/bower_components/morris.js/spec/lib/grid/auto_grid_lines_spec.coffee b/public/bower_components/morris.js/spec/lib/grid/auto_grid_lines_spec.coffee
new file mode 100644
index 0000000..2312fe2
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/grid/auto_grid_lines_spec.coffee
@@ -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]
diff --git a/public/bower_components/morris.js/spec/lib/grid/set_data_spec.coffee b/public/bower_components/morris.js/spec/lib/grid/set_data_spec.coffee
new file mode 100644
index 0000000..50450d7
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/grid/set_data_spec.coffee
@@ -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]
diff --git a/public/bower_components/morris.js/spec/lib/grid/y_label_format_spec.coffee b/public/bower_components/morris.js/spec/lib/grid/y_label_format_spec.coffee
new file mode 100644
index 0000000..e074230
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/grid/y_label_format_spec.coffee
@@ -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"
diff --git a/public/bower_components/morris.js/spec/lib/hover_spec.coffee b/public/bower_components/morris.js/spec/lib/hover_spec.coffee
new file mode 100644
index 0000000..868f1a3
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/hover_spec.coffee
@@ -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!')
diff --git a/public/bower_components/morris.js/spec/lib/label_series_spec.coffee b/public/bower_components/morris.js/spec/lib/label_series_spec.coffee
new file mode 100644
index 0000000..2794e73
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/label_series_spec.coffee
@@ -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()]
+ ])
diff --git a/public/bower_components/morris.js/spec/lib/line/line_spec.coffee b/public/bower_components/morris.js/spec/lib/line/line_spec.coffee
new file mode 100644
index 0000000..42e52e8
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/line/line_spec.coffee
@@ -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
diff --git a/public/bower_components/morris.js/spec/lib/pad_spec.coffee b/public/bower_components/morris.js/spec/lib/pad_spec.coffee
new file mode 100644
index 0000000..f81a592
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/pad_spec.coffee
@@ -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") \ No newline at end of file
diff --git a/public/bower_components/morris.js/spec/lib/parse_time_spec.coffee b/public/bower_components/morris.js/spec/lib/parse_time_spec.coffee
new file mode 100644
index 0000000..199aa9d
--- /dev/null
+++ b/public/bower_components/morris.js/spec/lib/parse_time_spec.coffee
@@ -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()) \ No newline at end of file
diff --git a/public/bower_components/morris.js/spec/specs.html b/public/bower_components/morris.js/spec/specs.html
new file mode 100644
index 0000000..28ec092
--- /dev/null
+++ b/public/bower_components/morris.js/spec/specs.html
@@ -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>
diff --git a/public/bower_components/morris.js/spec/support/placeholder.coffee b/public/bower_components/morris.js/spec/support/placeholder.coffee
new file mode 100644
index 0000000..f715035
--- /dev/null
+++ b/public/bower_components/morris.js/spec/support/placeholder.coffee
@@ -0,0 +1,6 @@
+beforeEach ->
+ placeholder = $('<div id="graph" style="width: 600px; height: 400px"></div>')
+ $('#test').append(placeholder)
+
+afterEach ->
+ $('#test').empty()
diff --git a/public/bower_components/morris.js/spec/viz/examples.js b/public/bower_components/morris.js/spec/viz/examples.js
new file mode 100644
index 0000000..0e97de3
--- /dev/null
+++ b/public/bower_components/morris.js/spec/viz/examples.js
@@ -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);
+};
diff --git a/public/bower_components/morris.js/spec/viz/exemplary/area0.png b/public/bower_components/morris.js/spec/viz/exemplary/area0.png
new file mode 100644
index 0000000..67e5f4a
--- /dev/null
+++ b/public/bower_components/morris.js/spec/viz/exemplary/area0.png
Binary files differ
diff --git a/public/bower_components/morris.js/spec/viz/exemplary/bar0.png b/public/bower_components/morris.js/spec/viz/exemplary/bar0.png
new file mode 100644
index 0000000..03f12e0
--- /dev/null
+++ b/public/bower_components/morris.js/spec/viz/exemplary/bar0.png
Binary files differ
diff --git a/public/bower_components/morris.js/spec/viz/exemplary/line0.png b/public/bower_components/morris.js/spec/viz/exemplary/line0.png
new file mode 100644
index 0000000..70f814c
--- /dev/null
+++ b/public/bower_components/morris.js/spec/viz/exemplary/line0.png
Binary files differ
diff --git a/public/bower_components/morris.js/spec/viz/exemplary/stacked_bar0.png b/public/bower_components/morris.js/spec/viz/exemplary/stacked_bar0.png
new file mode 100644
index 0000000..238e05f
--- /dev/null
+++ b/public/bower_components/morris.js/spec/viz/exemplary/stacked_bar0.png
Binary files differ
diff --git a/public/bower_components/morris.js/spec/viz/run.sh b/public/bower_components/morris.js/spec/viz/run.sh
new file mode 100755
index 0000000..ae671d4
--- /dev/null
+++ b/public/bower_components/morris.js/spec/viz/run.sh
@@ -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
diff --git a/public/bower_components/morris.js/spec/viz/test.html b/public/bower_components/morris.js/spec/viz/test.html
new file mode 100644
index 0000000..28db054
--- /dev/null
+++ b/public/bower_components/morris.js/spec/viz/test.html
@@ -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>
diff --git a/public/bower_components/morris.js/spec/viz/visual_specs.js b/public/bower_components/morris.js/spec/viz/visual_specs.js
new file mode 100644
index 0000000..20dc666
--- /dev/null
+++ b/public/bower_components/morris.js/spec/viz/visual_specs.js
@@ -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();