summaryrefslogtreecommitdiffstats
path: root/debian/missing-sources/epoch/tests/unit
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:26:01 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:26:01 +0000
commitef03469fec14f1f0358b690934fc173d744f4e7d (patch)
tree8be439d7b2f1d7c8283b745919b9e66481a950e7 /debian/missing-sources/epoch/tests/unit
parentAdding upstream version 5.6.0. (diff)
downloadknot-resolver-debian/5.6.0-1.tar.xz
knot-resolver-debian/5.6.0-1.zip
Adding debian version 5.6.0-1.debian/5.6.0-1debian
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/charts.coffee573
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/copy.coffee47
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/css.coffee85
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/d3.coffee40
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/events.coffee111
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/format.coffee68
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/is.coffee88
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/util.coffee92
-rw-r--r--debian/missing-sources/epoch/tests/unit/data/array_format.coffee106
-rw-r--r--debian/missing-sources/epoch/tests/unit/data/chart.coffee121
-rw-r--r--debian/missing-sources/epoch/tests/unit/data/keyvalue_format.coffee101
-rw-r--r--debian/missing-sources/epoch/tests/unit/data/tuple_format.coffee76
-rw-r--r--debian/missing-sources/epoch/tests/unit/init.coffee55
-rw-r--r--debian/missing-sources/epoch/tests/unit/time.coffee67
-rw-r--r--debian/missing-sources/epoch/tests/unit/time/line.coffee15
15 files changed, 1645 insertions, 0 deletions
diff --git a/debian/missing-sources/epoch/tests/unit/core/charts.coffee b/debian/missing-sources/epoch/tests/unit/core/charts.coffee
new file mode 100644
index 0000000..0f0bb9c
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/charts.coffee
@@ -0,0 +1,573 @@
+sinon = require 'sinon'
+
+describe 'Epoch.Chart', ->
+ [defaultWidth, defaultHeight] = [320, 240]
+
+ describe 'Base', ->
+ [testDivWidth, testDivHeight] = [800, 200]
+ [resizeDivWidth, resizeDivHeight] = [200, 200]
+
+ before (done) ->
+ d3.select(doc.body).append('div').attr('id', 'testDiv').style
+ width: "#{testDivWidth}px"
+ height: "#{testDivHeight}px"
+
+ d3.select(doc.body).append('div').attr('id', 'resizeDiv').style
+ width: "#{resizeDivWidth}px"
+ height: "#{resizeDivHeight}px"
+
+ done()
+
+ after (done) ->
+ d3.select('#testDiv').remove()
+ d3.select('#resizeDiv').remove()
+ done()
+
+ describe 'constructor', ->
+ it 'should set default dimensions', ->
+ c = new Epoch.Chart.Base()
+ assert.equal c.width, defaultWidth, 'Did not set default width'
+ assert.equal c.height, defaultHeight, 'Did not set default height'
+
+ it 'should allow dimensions to be set via options', ->
+ [width, height] = [500, 780]
+ c = new Epoch.Chart.Base({ width: width, height: height })
+ assert.equal c.width, width, "Did not set width to #{width}"
+ assert.equal c.height, height, "Did not set height to #{height}"
+
+ it 'should use the dimensions of the given element when applicable', ->
+ c = new Epoch.Chart.Base({ el: '#testDiv' })
+ assert.equal c.width, testDivWidth, "Did not set width to that of the div"
+ assert.equal c.height, testDivHeight, "Did not set height to that of the div"
+
+ it 'should set default data to an empty array', ->
+ c = new Epoch.Chart.Base()
+ assert.isArray c.data
+ assert.equal c.data.length, 0
+
+ it 'should set data when given as an option', ->
+ data = [
+ {label: 'A', values: [{x: 0, y: 0}]},
+ {label: 'B', values: [{x: 1, y: 1}]}
+ ]
+ c = new Epoch.Chart.Base({ data: data })
+ assert.sameMembers(c.data, data)
+
+ describe 'setData', ->
+ data = [
+ {label: 'A', values: [{x: 10, y: 20}]},
+ {label: 'B', values: [{x: 10, y: 20}]},
+ {label: 'C', values: [{x: 10, y: 20}]}
+ ]
+ classNames = [
+ ['layer', 'category1', 'a'],
+ ['layer', 'category2', 'b'],
+ ['layer', 'category3', 'c']
+ ]
+ chart = null
+
+ before (done) ->
+ (chart = new Epoch.Chart.Base()).setData(data)
+ done()
+
+ it 'should set data correctly', ->
+ assert.sameMembers chart.data, data
+ for i in [0...data.length]
+ assert.equal chart.data[i].label, data[i].label
+ assert.equal chart.data[i].values[0], data[i].values[0]
+
+ it 'should add the correct categories and class names', ->
+ for i in [0...data.length]
+ className = chart.data[i].className
+ for name in classNames[i]
+ assert (className.indexOf(name) > -1), "Missing class '#{name}'"
+
+ describe 'draw', ->
+ it "should trigger the 'draw' event", (done) ->
+ errorCallback = ->
+ assert 'false', "The 'draw' event was never triggered"
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+ chart = new Epoch.Chart.Base()
+ chart.on 'draw', ->
+ clearTimeout(timeout)
+ done()
+ chart.draw()
+
+ describe 'update', ->
+ it 'should call draw by default', (done) ->
+ errorCallback = ->
+ assert false, "update did not call draw by default."
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+ chart = new Epoch.Chart.Base()
+ chart.on 'draw', ->
+ clearTimeout(timeout)
+ done()
+ chart.update([])
+
+ it 'should not call draw when instructed', (done) ->
+ chart = new Epoch.Chart.Base()
+ chart.on 'draw', ->
+ assert false, "Update incorrectly called draw."
+ done()
+ chart.update([], false)
+ done()
+
+ describe 'extent', ->
+ data = [
+ {values: [
+ {x: -1, y: 10},
+ {x: 2, y: 20},
+ {x: 4, y: 50},
+ {x: 8, y: 9900}
+ ]},
+ {values: [
+ {x: 1, y: 170},
+ {x: 7, y: -2380},
+ {x: 19, y: 90},
+ {x: 33, y: 17}
+ ]}
+ ]
+
+ [xMin, xMax] = [-1, 33]
+ [yMin, yMax] = [-2380, 9900]
+
+ chart = null
+
+ before (done) ->
+ chart = new Epoch.Chart.Base({ data: data })
+ done()
+
+ it 'should find the correct extent given a y-comparitor', ->
+ [min, max] = chart.extent (d) -> d.y
+ assert.equal min, yMin, "Incorrect minimum y"
+ assert.equal max, yMax, "Incorrect maximum y"
+
+ it 'should find the correct extent give an x-comparitor', ->
+ [min, max] = chart.extent (d) -> d.x
+ assert.equal min, xMin, "Incorrect minimum x"
+ assert.equal max, xMax, "Incorrect maximum x"
+
+ describe 'option', ->
+ it 'should return all options for the chart when called with no arguments', ->
+ options = { a: 20, b: 30, c: { d: 40 } }
+ chart = new Epoch.Chart.Base options
+ assert.isObject chart.option()
+ assert.deepEqual chart.option(), options
+
+ it 'should return a single value when given a key', ->
+ options = { a: 20, b: 30 }
+ chart = new Epoch.Chart.Base options
+ assert.equal chart.option('a'), options.a
+ assert.equal chart.option('b'), options.b
+ assert.isUndefined chart.option('c')
+
+ it 'should return a deep value when given a hierarchical key', ->
+ options =
+ a:
+ b: 20
+ c:
+ d: 30
+ chart = new Epoch.Chart.Base options
+ assert.equal chart.option('a.b'), options.a.b
+ assert.equal chart.option('a.c.d'), options.a.c.d
+
+ it 'should set an option given a string and a value', ->
+ chart = new Epoch.Chart.Base()
+ [key, value] = ['a', 'hello world']
+ chart.option(key, value)
+ assert.equal chart.option(key), value
+
+ it 'should set a deep value when given a hierarchical key', ->
+ chart = new Epoch.Chart.Base()
+
+ map =
+ 'a.b': 'deep'
+ 'a.c.d': 'deeper'
+ 'b': 'shallow'
+
+ for key, value of map
+ chart.option(key, value)
+ assert.equal chart.option(key), value
+
+ it 'should set all options given an object', ->
+ original = { a: 20, b: { c: 30 } }
+ newOptions = { a: 15, d: { e: 10, f: 30 } }
+ chart = new Epoch.Chart.Base()
+ chart.option(newOptions)
+ assert.deepEqual chart.option(), newOptions
+
+ it 'should trigger an event when an option is changed', (done) ->
+ [key, value] = ['a', 20]
+ eventName = "option:#{key}"
+
+ errorCallback = ->
+ assert false, "Setting an option did not trigger the appropriate event: #{eventName}"
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+
+ chart = new Epoch.Chart.Base()
+ chart.on eventName, ->
+ clearTimeout(timeout)
+ done()
+ chart.option(key, value)
+
+ it 'should resize the containing element when the width option is changed', ->
+ newWidth = resizeDivWidth + 20
+ chart = new Epoch.Chart.Base({ el: '#resizeDiv' })
+ chart.option('width', newWidth)
+ assert.equal d3.select('#resizeDiv').width(), newWidth
+
+ it 'should resize the containing element when the height option is changed', ->
+ newHeight = resizeDivHeight + 20
+ chart = new Epoch.Chart.Base({ el: '#resizeDiv' })
+ chart.option('height', newHeight)
+ assert.equal d3.select('#resizeDiv').height(), newHeight
+
+ describe '_getScaleDomain', ->
+ chart = null
+
+ beforeEach ->
+ chart = new Epoch.Chart.Base
+ data: [ layerWithRange(-2030, 5050) ]
+
+ it 'returns a given array', ->
+ assert.deepEqual(chart._getScaleDomain([0,1]), [0,1])
+
+ it 'returns @options.range if it is an array', ->
+ chart.options.range = [-100, 100]
+ assert.equal chart._getScaleDomain(), chart.options.range
+
+ it 'returns @options.range.left if it is an array', ->
+ chart.options.range = {left: [-100, 100]}
+ assert.equal chart._getScaleDomain(), chart.options.range.left
+
+ it 'returns @options.range.right if it is an array', ->
+ chart.options.range = {right: [-100, 100]}
+ assert.equal chart._getScaleDomain(), chart.options.range.right
+
+ it 'returns the extent of the data', ->
+ assert.deepEqual chart._getScaleDomain(), chart.extent((d) -> d.y)
+
+ describe 'with range grouped layers', ->
+ beforeEach ->
+ chart = new Epoch.Chart.Base
+ data: [
+ layerWithRange(0, 10, 'left'),
+ layerWithRange(-5000, 5000, 'right'),
+ layerWithRange(-10, -5, 'left')
+ ]
+
+ it 'returns the extent of the layers with the given range label', ->
+ assert.deepEqual chart._getScaleDomain('left'), [-10, 10]
+
+ it 'returns the extent of the data if the label is invalid', ->
+ assert.deepEqual chart._getScaleDomain('foobar'), chart.extent((d) -> d.y)
+
+ describe 'layers', ->
+ [chart, eventChart] = [null, null]
+ labels = ['A', 'B', 'C']
+ data = [
+ { label: 'A', data: [{x: 0, y: 0}] },
+ { label: 'B', data: [{x: 1, y: 1}] },
+ { label: 'C', data: [{x: 2, y: 2}] }
+ ]
+ data2 = [
+ { label: 'A', data: [{x: 0, y: 0}] }
+ ]
+
+ before (done) ->
+ chart = new Epoch.Chart.Base
+ el: doc.createElement('div')
+ data: data
+ eventChart = new Epoch.Chart.Base
+ el: doc.createElement('div')
+ data: data2
+ done()
+
+ describe '_findLayer', ->
+ it 'should find layers given a label', ->
+ for label in labels
+ layer = chart._findLayer(label)
+ assert.equal label, layer.label, "Could not find layer with label #{label}"
+
+ it 'should find layers given an index', ->
+ for i in [0...data.length]
+ layer = chart._findLayer(i)
+ assert.equal labels[i], layer.label, "Could not find layer with index #{i}"
+
+ it 'should return null if given an invalid label', ->
+ assert.isNull (chart._findLayer 'D')
+ assert.isNull (chart._findLayer 'not a thing')
+
+ it 'should return null if given an index that is out of bounds', ->
+ assert.isNull (chart._findLayer -1)
+ assert.isNull (chart._findLayer 5)
+
+ describe 'hideLayer', ->
+ it 'should hide a visible layer', ->
+ chart.hideLayer('A')
+ assert.isFalse chart._findLayer('A').visible
+
+ it 'should keep a hidden layer hidden', ->
+ assert.isFalse chart._findLayer('A').visible
+ chart.hideLayer('A')
+ assert.isFalse chart._findLayer('A').visible
+
+ it 'should trigger layer:hidden when a layer is hidden', (done) ->
+ errorCallback = ->
+ assert false, "layer:hidden was not triggered"
+ done()
+ timeout = setTimeout errorCallback, 1000
+ eventChart.on 'layer:hidden', ->
+ clearTimeout timeout
+ done()
+ eventChart.hideLayer('A')
+
+ describe 'showLayer', ->
+ it 'should have keep a visible layer visible', ->
+ assert.isTrue chart._findLayer('B').visible
+ chart.showLayer('B')
+ assert.isTrue chart._findLayer('B').visible
+
+ it 'should make a hidden layer visible', ->
+ assert.isFalse chart._findLayer('A').visible
+ chart.showLayer('A')
+ assert.isTrue chart._findLayer('A').visible
+
+ it 'should trigger layer:shown when a layer is shown', (done) ->
+ errorCallback = ->
+ assert false, "layer:shown was not triggered"
+ done()
+ timeout = setTimeout errorCallback, 1000
+ eventChart.on 'layer:shown', ->
+ clearTimeout timeout
+ done()
+ eventChart.showLayer('A')
+
+ describe 'toggleLayer', ->
+ it 'should hide a visible layer', ->
+ chart.hideLayer('A')
+ chart.toggleLayer('A')
+ assert.isTrue chart._findLayer('A').visible
+
+ it 'should show a hidden layer', ->
+ chart.showLayer('B')
+ chart.toggleLayer('B')
+ assert.isFalse chart._findLayer('B').visible
+
+ describe 'isLayerVisible', ->
+ it 'should report true if a layer is visible', ->
+ chart.showLayer('A')
+ assert.isTrue chart.isLayerVisible('A')
+
+ it 'should report false if a layer is not visible', ->
+ chart.hideLayer('A')
+ assert.isFalse chart.isLayerVisible('B')
+
+ describe 'getVisibleLayers', ->
+ it 'should only return visible layers', ->
+ chart.showLayer('A')
+ chart.showLayer('B')
+ chart.hideLayer('C')
+ visible = chart.getVisibleLayers()
+ assert.equal visible.length, 2
+ assert.equal visible[0].label, 'A'
+ assert.equal visible[1].label, 'B'
+
+ describe 'SVG', ->
+ [containerWidth, containerHeight] = [1000, 280]
+ container = null
+
+ before (done) ->
+ container = doc.createElement('DIV')
+ container.id = 'svg-container'
+ doc.body.appendChild(container)
+ d3.select('#svg-container').style
+ 'width': "#{containerWidth}px"
+ 'height': "#{containerHeight}px"
+ done()
+
+ after (done) ->
+ doc.body.removeChild(container)
+ done()
+
+ describe 'constructor', ->
+ it 'should create a new SVG when not given an element', ->
+ chart = new Epoch.Chart.SVG()
+ assert.ok chart.svg, "SVG not created"
+
+ it 'should set the default width and height of the SVG', ->
+ chart = new Epoch.Chart.SVG()
+ assert.equal chart.svg.attr('width'), defaultWidth, "Default width not set"
+ assert.equal chart.svg.attr('height'), defaultHeight, "Default height not set"
+
+ it 'should set custom dimensions for the SVG via options', ->
+ [customWidth, customHeight] = [500, 600]
+ chart = new Epoch.Chart.SVG({ width: customWidth, height: customHeight })
+ assert.equal chart.svg.attr('width'), customWidth, "Custom width not set"
+ assert.equal chart.svg.attr('height'), customHeight, "Custom height not set"
+
+ it 'should set the container dimensions for the SVG', ->
+ chart = new Epoch.Chart.SVG({ el: '#svg-container' })
+ assert.equal chart.svg.attr('width'), containerWidth
+ assert.equal chart.svg.attr('height'), containerHeight
+
+ describe 'dimensionsChanged', ->
+ [width, height, chart] = [200, 100, null]
+
+ before (done) ->
+ d3.select(doc.body).append('div').attr('id', 'svgResize').style
+ width: width + 'px'
+ height: height + 'px'
+ chart = new Epoch.Chart.SVG { el: '#svgResize' }
+ done()
+
+ after (done) ->
+ d3.select('#svgResize').remove()
+ done()
+
+ it 'should resize the SVG element when the width option is changed', ->
+ newWidth = width + 500
+ chart.option 'width', newWidth
+ assert.equal chart.svg.attr('width'), newWidth
+
+ it 'should resize the SVG element when the height option is changed', ->
+ newHeight = height + 500
+ chart.option 'height', newHeight
+ assert.equal chart.svg.attr('height'), newHeight
+
+ describe 'Canvas', ->
+ [containerWidth, containerHeight] = [1000, 280]
+ container = null
+ container_id = 'canvas-container'
+ containedChart = null
+
+ before (done) ->
+ container = doc.createElement('DIV')
+ container.id = container_id
+ doc.body.appendChild(container)
+ d3.select('#' + container_id).style
+ 'width': "#{containerWidth}px"
+ 'height': "#{containerHeight}px"
+
+ containedChart = new Epoch.Chart.Canvas
+ el: '#' + container_id
+ pixelRatio: 1
+
+ done()
+
+ after (done) ->
+ doc.body.removeChild(container)
+ done()
+
+ describe 'constructor', ->
+ it 'should correctly detect the pixelRatio', ->
+ chart = new Epoch.Chart.Canvas()
+ assert.equal chart.pixelRatio, 2
+
+ it 'should allow the pixelRatio to be explicitly overriden', ->
+ customPixelRatio = 4.2
+ chart = new Epoch.Chart.Canvas({ pixelRatio: customPixelRatio })
+ assert.equal chart.pixelRatio, customPixelRatio
+
+ it 'should create a child canvas', ->
+ chart = new Epoch.Chart.Canvas()
+ assert.ok chart.canvas, "Did not create canvas"
+ assert.equal chart.canvas.node().tagName.toLowerCase(), 'canvas', 'Did not create a canvas node'
+
+ it 'should append the child canvas to the containing element', ->
+ assert.equal containedChart.canvas.node().parentNode.id, container_id
+
+ it 'should set the default dimensions for the canvas', ->
+ chart = new Epoch.Chart.Canvas({ pixelRatio: 1 })
+ assert.equal chart.canvas.attr('width'), defaultWidth
+ assert.equal chart.canvas.attr('height'), defaultHeight
+
+ it 'should allow custom dimensions for the canvas', ->
+ [customWidth, customHeight] = [999, 888]
+ chart = new Epoch.Chart.Canvas
+ width: customWidth
+ height: customHeight
+ pixelRatio: 1
+ assert.equal chart.canvas.attr('width'), customWidth
+ assert.equal chart.canvas.attr('height'), customHeight
+
+ it 'should set container dimensions for the canvas', ->
+ assert.equal containedChart.canvas.attr('width'), containerWidth
+ assert.equal containedChart.canvas.attr('height'), containerHeight
+
+ it 'should fetch a graphics context from the canvas', ->
+ assert.ok containedChart.ctx, "Did not fetch graphics context from canvas"
+
+ it 'should take pixel ratio into account when setting canvas dimension attributes', ->
+ pixelRatio = 3
+ chart = new Epoch.Chart.Canvas({ pixelRatio: pixelRatio })
+ assert.equal chart.canvas.attr('width'), defaultWidth * pixelRatio
+ assert.equal chart.canvas.attr('height'), defaultHeight * pixelRatio
+
+ it 'should not take pixel ratio into account when setting canvas dimension styles', ->
+ chart = new Epoch.Chart.Canvas({ pixelRatio: 2 })
+ assert.equal +chart.canvas.style('width').replace('px', ''), defaultWidth
+ assert.equal +chart.canvas.style('height').replace('px', ''), defaultHeight
+
+ describe 'getWidth', ->
+ it 'should take pixel ratio into account', ->
+ pixelRatio = 2
+ chart = new Epoch.Chart.Canvas({ pixelRatio: pixelRatio })
+ assert.equal chart.getWidth(), pixelRatio * defaultWidth
+
+ describe 'getHeight', ->
+ it 'should take pixel ratio into account', ->
+ pixelRatio = 2
+ chart = new Epoch.Chart.Canvas({ pixelRatio: pixelRatio })
+ assert.equal chart.getHeight(), pixelRatio * defaultHeight
+
+ describe 'dimensionsChanged', ->
+ [width, height, chart, pixelRatio] = [200, 100, null, 2]
+
+ before (done) ->
+ d3.select(doc.body).append('div').attr('id', 'canvasResize').style
+ width: width + 'px'
+ height: height + 'px'
+ chart = new Epoch.Chart.Canvas { el: '#canvasResize', pixelRatio: pixelRatio }
+ done()
+
+ after (done) ->
+ d3.select('#canvasResize').remove()
+ done()
+
+ it 'should resize the canvas element when the width option is changed', ->
+ newWidth = width + 500
+ chart.option 'width', newWidth
+ assert.equal chart.canvas.attr('width'), pixelRatio * newWidth
+ assert.equal chart.canvas.width(), newWidth
+
+ it 'should resize the canvas element when the height option is changed', ->
+ newHeight = height + 500
+ chart.option 'height', newHeight
+ assert.equal chart.canvas.attr('height'), pixelRatio * newHeight
+ assert.equal chart.canvas.height(), newHeight
+
+ describe 'redraw', ->
+ chart = null
+ drawSpy = null
+ purgeSpy = null
+
+ before ->
+ chart = new Epoch.Chart.Canvas()
+
+ beforeEach ->
+ drawSpy = sinon.spy chart, 'draw'
+ purgeSpy = sinon.spy Epoch.QueryCSS, 'purge'
+
+ afterEach ->
+ chart.draw.restore()
+ Epoch.QueryCSS.purge.restore()
+
+ it 'should purge QueryCSS cache and redraw the canvas based chart with new styles', ->
+ chart.redraw()
+
+ assert drawSpy.calledOnce
+ assert purgeSpy.calledOnce
diff --git a/debian/missing-sources/epoch/tests/unit/core/copy.coffee b/debian/missing-sources/epoch/tests/unit/core/copy.coffee
new file mode 100644
index 0000000..2043241
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/copy.coffee
@@ -0,0 +1,47 @@
+describe 'Epoch.Util', ->
+ describe 'copy', ->
+ it 'should correctly create a shallow copy', ->
+ object =
+ a: 20
+ b: 'hello'
+
+ copy = Epoch.Util.copy(object)
+
+ assert.equal copy.a, object.a
+ assert.equal copy.b, object.b
+
+ it 'should not recursively copy objects', ->
+ object =
+ a:
+ foo: 'bar'
+
+ copy = Epoch.Util.copy(object)
+ object.a.foo = 'baz'
+ assert.equal object.a.foo, copy.a.foo
+
+ describe 'defaults', ->
+ it 'should set default values when keys are missing', ->
+ options = {a: 'foo', b: 'bar'}
+ defaults = {c: 'baz'}
+ result = Epoch.Util.defaults(options, defaults)
+ assert.equal result.c, defaults.c
+
+ it 'should not set default values when keys are present', ->
+ options = { a: 'foo', b: 'bar' }
+ defaults = { a: 'wow', b: 'neat' }
+ result = Epoch.Util.defaults(options, defaults)
+ assert.equal result.a, options.a
+ assert.equal result.b, options.b
+
+ it 'should recursively set defaults from sub objects', ->
+ options =
+ a:
+ b: 'foo'
+ defaults =
+ a:
+ b: ''
+ c: 'bar'
+ result = Epoch.Util.defaults(options, defaults)
+
+ assert.equal result.a.b, options.a.b
+ assert.equal result.a.c, defaults.a.c
diff --git a/debian/missing-sources/epoch/tests/unit/core/css.coffee b/debian/missing-sources/epoch/tests/unit/core/css.coffee
new file mode 100644
index 0000000..00cce68
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/css.coffee
@@ -0,0 +1,85 @@
+describe 'Epoch.QueryCSS', ->
+ styleMap =
+ '#container rect':
+ 'fill': 'blue'
+ 'stroke': 'red'
+ 'stroke-width': '5px'
+ '#container rect.a':
+ 'fill': 'green'
+ 'stroke': 'yellow'
+ 'stroke-width': '1px'
+ 'rect#byid':
+ 'fill': 'purple'
+ 'stroke': '#94105A'
+ 'stroke-width': '15px'
+ 'body.alt-color rect#byid':
+ 'fill': '#abcdef1'
+ 'stroke': '#48419A'
+ 'stroke-width': '2em'
+
+ [container, svg, styleTag] = [null, null, null]
+
+ makeStyleSheet = ->
+ cssStatements = []
+ for selector, rules of styleMap
+ cssStatements.push (selector + "{" + ("#{k}: #{v}" for k, v of rules).join(';') + "}")
+ css = cssStatements.join('\n')
+ styleTag = addStyleSheet(css)
+
+ makeContainer = ->
+ container = d3.select(doc.body).append('div')
+ .attr('id', 'container')
+ svg = container.append('svg')
+ .attr('width', 10)
+ .attr('height', 10)
+
+ assertStyles = (object, selector) ->
+ unless object?
+ assert(false, "Object contains no styles")
+
+ unless (mapping = styleMap[selector])?
+ assert(false, "Could not find styles with selector: #{selector}")
+
+ for key, value of mapping
+ assert.equal object[key], value, "Style mismatch on rule '#{key}'"
+
+ before (done) ->
+ makeStyleSheet()
+ makeContainer()
+ done()
+
+ after (done) ->
+ doc.head.removeChild(styleTag)
+ doc.body.removeChild(container.node())
+ done()
+
+ describe 'getStyles', ->
+ it 'should find styles for an svg element', ->
+ styles = Epoch.QueryCSS.getStyles('rect', container)
+ assertStyles styles, '#container rect'
+
+ it 'should find styles using a specific class name', ->
+ styles = Epoch.QueryCSS.getStyles('rect.a', container)
+ assertStyles styles, '#container rect.a'
+
+ it 'should find styles using an id', ->
+ styles = Epoch.QueryCSS.getStyles('rect#byid', container)
+ assertStyles styles, 'rect#byid'
+
+ describe 'purge', ->
+ before (done) ->
+ d3.select(doc.body).attr('class', 'alt-color')
+ done()
+
+ after (done) ->
+ d3.select(doc.body).attr('class', null)
+ done()
+
+ it 'should find cached styles before a purge', ->
+ styles = Epoch.QueryCSS.getStyles('rect#byid', container)
+ assertStyles styles, 'rect#byid'
+
+ it 'should find new styles after purging the cache', ->
+ Epoch.QueryCSS.purge()
+ styles = Epoch.QueryCSS.getStyles('rect#byid', container)
+ assertStyles styles, 'body.alt-color rect#byid'
diff --git a/debian/missing-sources/epoch/tests/unit/core/d3.coffee b/debian/missing-sources/epoch/tests/unit/core/d3.coffee
new file mode 100644
index 0000000..1b65c55
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/d3.coffee
@@ -0,0 +1,40 @@
+describe 'd3.selection', ->
+ [width, height] = [345, 543, null]
+ [element, id] = [null, 'd3-element']
+
+ before (done) ->
+ element = doc.createElement('DIV')
+ element.id = id
+ doc.body.appendChild(element)
+ d3.select('#' + id).style
+ 'width': width + "px"
+ 'height': height + "px"
+ done()
+
+ describe 'width', ->
+ it 'should return the width of an element', ->
+ assert.equal d3.select('#' + id).width(), width
+
+ it 'should set the width of an element given a number', ->
+ widthNumber = 50
+ d3.select('#'+id).width(widthNumber)
+ assert.equal d3.select('#'+id).width(), widthNumber
+
+ it 'should set the width of an element given a css pixel length', ->
+ widthString = '500px'
+ d3.select('#'+id).width(widthString)
+ assert.equal d3.select('#'+id).width(), +widthString.replace('px', '')
+
+ describe 'height', ->
+ it 'should return the height of an element', ->
+ assert.equal d3.select('#' + id).height(), height
+
+ it 'should set the height of an element given a number', ->
+ heightNumber = 75
+ d3.select('#'+id).height(heightNumber)
+ assert.equal d3.select('#'+id).height(), heightNumber
+
+ it 'should set the height of an element given a css pixel length', ->
+ heightString = '343px'
+ d3.select('#'+id).height(heightString)
+ assert.equal d3.select('#'+id).height(), +heightString.replace('px', '')
diff --git a/debian/missing-sources/epoch/tests/unit/core/events.coffee b/debian/missing-sources/epoch/tests/unit/core/events.coffee
new file mode 100644
index 0000000..38d9356
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/events.coffee
@@ -0,0 +1,111 @@
+describe 'Epoch.Events', ->
+ eventsObject = null
+
+ before (done) ->
+ eventsObject = new Epoch.Events()
+ done()
+
+ it 'should execute callbacks when events are triggered', (done) ->
+ errorCallback = ->
+ assert false, 'Event callback never executed'
+ done()
+ timeout = setTimeout errorCallback, 1000
+ eventsObject.on 'event', ->
+ clearTimeout(timeout)
+ done()
+ eventsObject.trigger 'event'
+
+ it 'should not execute callbacks that have been removed', (done) ->
+ errorCallback = ->
+ assert false, 'Event callback still executed'
+ done()
+ eventsObject.on 'example', errorCallback
+ eventsObject.off 'example', errorCallback
+ eventsObject.trigger 'example'
+ done()
+
+ it 'should execute all callbacks associated with an event name', (done) ->
+ total = 4
+
+ errorCallback = ->
+ assert false, 'Not all callbacks were executed'
+ done()
+ timeout = setTimeout errorCallback, 1000
+
+ makeCallback = -> ->
+ total--
+ if total == 0
+ clearTimeout(timeout)
+ done()
+ eventsObject.on('multi', makeCallback()) for i in [0...total]
+ eventsObject.trigger 'multi'
+
+ it 'should remove all callbacks when using .off([String])', (done) ->
+ makeCallback = -> ->
+ assert false, "A callback was still executed"
+ done()
+ eventsObject.on('multi2', makeCallback()) for i in [0...4]
+ eventsObject.off('multi2')
+ eventsObject.trigger('multi2')
+ setTimeout (-> done()), 200
+
+ it 'should execute methods on the object when using .on([String], [String])', (done) ->
+ errorCallback = ->
+ assert false, 'Trigger did not call the appropriate method.'
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+
+ eventsObject.method = ->
+ clearTimeout(timeout)
+ done()
+
+ eventsObject.on 'method-event', 'method'
+ eventsObject.trigger 'method-event'
+
+ it 'should register all events when executing .onAll([Object])', (done) ->
+ errorCallback = ->
+ assert false, 'Not all events were triggered.'
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+
+ eventNames = ['multi:a', 'multi:b', 'multi:c', 'multi:d']
+ total = 0
+
+ eventCallback = ->
+ total += 1
+ if total == eventNames.length
+ clearTimeout(timeout)
+ done()
+
+ eventMap = {}
+ eventMap[name] = eventCallback for name in eventNames
+
+ eventsObject.onAll(eventMap)
+ eventsObject.trigger(name) for name in eventNames
+
+
+ it 'should remove all events when executing .offAll([Array])', ->
+ eventCallback = ->
+ assert false, 'A removed callback was still triggered.'
+
+ eventNames = ['multi-off:a', 'multi-off:b', 'multi-off:c', 'multi-off:d']
+ eventMap = {}
+ eventMap[name] = eventCallback for name in eventNames
+
+ eventsObject.onAll(eventMap)
+ eventsObject.offAll(eventNames)
+ eventsObject.trigger(name) for name in eventNames
+
+
+ it 'should remove specific event callbacks when executing .offAll([Object])', (done) ->
+ makeEventCallback = -> ->
+ assert false, 'A removed callback was still triggered.'
+
+ eventNames = ['multi-off:a', 'multi-off:b', 'multi-off:c', 'multi-off:d']
+ eventMap = {}
+ eventMap[name] = makeEventCallback() for name in eventNames
+
+ eventsObject.onAll(eventMap)
+ eventsObject.offAll(eventMap)
+ eventsObject.trigger(name) for name in eventNames
+ setTimeout (-> done()), 200
diff --git a/debian/missing-sources/epoch/tests/unit/core/format.coffee b/debian/missing-sources/epoch/tests/unit/core/format.coffee
new file mode 100644
index 0000000..a645b49
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/format.coffee
@@ -0,0 +1,68 @@
+describe 'Epoch.Util', ->
+ describe 'formatSI', ->
+ it 'should produce the same number for integers < 1000', ->
+ number = 678
+ assert.equal Epoch.Util.formatSI(number), number
+
+ it 'should only set a fixed decimal for integers when instructed', ->
+ number = 20
+ assert.equal Epoch.Util.formatSI(number), number
+ assert.equal Epoch.Util.formatSI(number, 1, true), "#{number}.0"
+
+ it 'should set the appropriate number of fixed digits', ->
+ number = 3.1415
+ for i in [1..5]
+ match = Epoch.Util.formatSI(number, i).split('.')[1]
+ assert.isNotNull match
+ assert.isString match
+ assert.equal match.length, i
+
+ it 'should set the appropriate postfix based on the number\'s order of magnitude', ->
+ for i, postfix of ['K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
+ number = Math.pow(10, ((i|0)+1)*3)
+ assert.equal Epoch.Util.formatSI(number), "1 #{postfix}"
+
+
+ describe 'formatBytes', ->
+ it 'should postfix numbers < 1024 with "B"', ->
+ number = 512
+ assert.equal Epoch.Util.formatBytes(number), "#{number} B"
+
+ it 'should only set a fixed decimal for integers when instructed', ->
+ assert.equal Epoch.Util.formatBytes(128), '128 B'
+ assert.equal Epoch.Util.formatBytes(128, 1, true), '128.0 B'
+ assert.equal Epoch.Util.formatBytes(1024), '1 KB'
+ assert.equal Epoch.Util.formatBytes(1024, 1, true), '1.0 KB'
+
+ it 'should set the appropriate number of fixed digits', ->
+ number = 3.1415
+ for i in [1..5]
+ fixed = Epoch.Util.formatBytes(number, i).replace(/\sB$/, '')
+ assert.isString fixed
+ match = fixed.split('.')[1]
+ assert.isNotNull match
+ assert.equal match.length, i
+
+ it 'should set the appropriate postfix based on the number\'s order of magnitude', ->
+ for i, postfix of ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+ number = Math.pow(1024, (i|0)+1)
+ regexp = new RegExp(" #{postfix}$")
+ assert.isNotNull Epoch.Util.formatBytes(number).match(regexp)
+
+
+describe 'Epoch.Formats', ->
+ describe 'regular', ->
+ it 'should return what it was given', ->
+ assert.equal Epoch.Formats.regular(10), 10
+ assert.equal Epoch.Formats.regular("hello"), "hello"
+
+ describe 'percent', ->
+ it 'should return a percent given a number', ->
+ assert.equal Epoch.Formats.percent(0.1), '10.0%'
+ assert.equal Epoch.Formats.percent(0.5), '50.0%'
+ assert.equal Epoch.Formats.percent(1), '100.0%'
+ assert.equal Epoch.Formats.percent(23.245), '2324.5%'
+
+ describe 'seconds', ->
+ it 'should return a well formatted date given a timestamp', ->
+ assert.match Epoch.Formats.seconds(1404385979), /\d{2}:\d{2}:\d{2} AM|PM/
diff --git a/debian/missing-sources/epoch/tests/unit/core/is.coffee b/debian/missing-sources/epoch/tests/unit/core/is.coffee
new file mode 100644
index 0000000..af08eb2
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/is.coffee
@@ -0,0 +1,88 @@
+describe 'Epoch.Util', ->
+ describe 'isArray', ->
+ it 'should return true if given an array', ->
+ assert.ok Epoch.isArray([])
+ assert.ok Epoch.isArray([1, 2, 3])
+
+ it 'should return false if not given an array', ->
+ assert.notOk Epoch.isArray(2)
+ assert.notOk Epoch.isArray("hello")
+ assert.notOk Epoch.isArray({})
+
+ describe 'isObject', ->
+ it 'should return true if given an flat object', ->
+ assert.ok Epoch.isObject({})
+
+ it 'should return false if given a number object', ->
+ assert.notOk Epoch.isObject(new Number())
+
+ it 'should return false if given a non-object', ->
+ assert.notOk Epoch.isObject([])
+ assert.notOk Epoch.isObject(2)
+ assert.notOk Epoch.isObject("string")
+
+ describe 'isString', ->
+ it 'should return true if given a string', ->
+ assert.ok Epoch.isString("example")
+ assert.ok Epoch.isString(new String())
+
+ it 'should return false if given a non-string', ->
+ assert.notOk Epoch.isString(2)
+ assert.notOk Epoch.isString([])
+ assert.notOk Epoch.isString({})
+
+ describe 'isFunction', ->
+ it 'should return true if given a function', ->
+ assert.ok Epoch.isFunction(->)
+
+ it 'should return false if given a non-function', ->
+ assert.notOk Epoch.isFunction([])
+ assert.notOk Epoch.isFunction({})
+ assert.notOk Epoch.isFunction(42)
+ assert.notOk Epoch.isFunction("cool")
+
+ describe 'isNumber', ->
+ it 'should return true if given a number', ->
+ assert.ok Epoch.isNumber(new Number())
+
+ it 'should return true if given an integer literal', ->
+ assert.ok Epoch.isNumber(1983)
+
+ it 'should return true if given a floating point literal', ->
+ assert.ok Epoch.isNumber(3.1415)
+
+ it 'should return false if given a non-number', ->
+ assert.notOk Epoch.isNumber(->)
+ assert.notOk Epoch.isNumber([])
+ assert.notOk Epoch.isNumber({})
+ assert.notOk Epoch.isNumber("nan")
+
+ describe 'isElement', ->
+ it 'should return true given an html element', ->
+ p = doc.createElement('P')
+ assert.ok Epoch.isElement(p)
+
+ it 'should return false given a non-element', ->
+ assert.notOk Epoch.isElement(1)
+ assert.notOk Epoch.isElement("1")
+ assert.notOk Epoch.isElement({})
+ assert.notOk Epoch.isElement([])
+ assert.notOk Epoch.isElement(->)
+
+ describe 'isNonEmptyArray', ->
+ it 'should return true given a non-empty array', ->
+ assert.ok Epoch.isNonEmptyArray([1])
+ assert.ok Epoch.isNonEmptyArray([1, 3])
+ assert.ok Epoch.isNonEmptyArray(["foo", 4, "bar"])
+
+ it 'should return false given a non-array', ->
+ assert.notOk Epoch.isNonEmptyArray(2)
+ assert.notOk Epoch.isNonEmptyArray("five")
+ assert.notOk Epoch.isNonEmptyArray({})
+ assert.notOk Epoch.isNonEmptyArray(->)
+
+ it 'should return false given a null value', ->
+ assert.notOk Epoch.isNonEmptyArray(null)
+
+ it 'should return false given an empty array', ->
+ assert.notOk Epoch.isNonEmptyArray([])
diff --git a/debian/missing-sources/epoch/tests/unit/core/util.coffee b/debian/missing-sources/epoch/tests/unit/core/util.coffee
new file mode 100644
index 0000000..e02280c
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/util.coffee
@@ -0,0 +1,92 @@
+describe 'Epoch.Util', ->
+ describe 'trim', ->
+ it 'should return null unless given a string', ->
+ assert.isNotNull Epoch.Util.trim('test string')
+ assert.isNull Epoch.Util.trim(34)
+
+ it 'should trim leading and trailing whitespace', ->
+ assert.equal Epoch.Util.trim("\t\n\r indeed \n\t\t\r"), 'indeed'
+
+ it 'should leave inner whitespace', ->
+ assert.equal Epoch.Util.trim('Hello world'), 'Hello world'
+
+ describe 'dasherize', ->
+ it 'should dasherize regular strings', ->
+ assert.equal Epoch.Util.dasherize('Hello World'), 'hello-world'
+
+ it 'should trim leading and trailing whitespace before dasherizing', ->
+ assert.equal Epoch.Util.dasherize(' Airieee is KewL '), 'airieee-is-kewl'
+
+ describe 'domain', ->
+ testLayers = [
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 40}] }
+ ]
+
+ testLayers2 = [
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 40}] },
+ { values: [{x: 'D', y: 15}, {x: 'E', y: 30}, {x: 'F', y: 90}] }
+ ]
+
+ it 'should find the correct domain of a set of keys and values', ->
+ xDomain = Epoch.Util.domain(testLayers, 'x')
+ assert.sameMembers xDomain, ['A', 'B', 'C']
+ yDomain = Epoch.Util.domain(testLayers, 'y')
+ assert.sameMembers yDomain, [10, 20, 40]
+
+ it 'should find all the values across multiple layers', ->
+ xDomain = Epoch.Util.domain(testLayers2, 'x')
+ assert.sameMembers xDomain, ['A', 'B', 'C', 'D', 'E', 'F']
+ yDomain = Epoch.Util.domain(testLayers2, 'y')
+ assert.sameMembers yDomain, [10, 20, 40, 15, 30, 90]
+
+ describe 'toRGBA', ->
+ it 'should produce the correct rgba style when given an rgba color style', ->
+ assert.equal Epoch.Util.toRGBA('rgba(1, 2, 3, 0.4)', 0.1), 'rgba(1,2,3,0.1)'
+
+ it 'should produce the correct rgba style when given any rgb color style', ->
+ assert.equal Epoch.Util.toRGBA('black', 0.25), 'rgba(0,0,0,0.25)'
+ assert.equal Epoch.Util.toRGBA('#FF0000', 0.9), 'rgba(255,0,0,0.9)'
+ assert.equal Epoch.Util.toRGBA('rgb(10, 20, 40)', 0.99), 'rgba(10,20,40,0.99)'
+
+ describe 'getComputedStyle', ->
+ overrideStyles =
+ 'width': '320px'
+ 'height': '240px'
+ 'background-color': 'blue'
+
+ [style, div] = [null, null]
+
+ before (done) ->
+ style = addStyleSheet('#get-style-div { padding-left: 30px; background: green }')
+ div = doc.createElement('div')
+ div.id = 'get-style-div'
+ doc.body.appendChild(div)
+ d3.select('#get-style-div').style(overrideStyles)
+ done()
+
+ after (done) ->
+ doc.body.removeChild(div)
+ doc.head.removeChild(style)
+ done()
+
+ it 'should find <style> styles', ->
+ styles = Epoch.Util.getComputedStyle(div)
+ assert.equal styles['padding-left'], '30px'
+
+ it 'should find overriden styles', ->
+ styles = Epoch.Util.getComputedStyle(div)
+ for k, v of overrideStyles
+ assert.equal styles[k], v, "ComputedStyles['#{k}'] should be '#{v}'"
+
+ describe 'flatten', ->
+ it 'should flatten a given multi-array', ->
+ multiarray = [[1, 2], 3, [4, 5, 6, [7]]]
+ expected = [1, 2, 3, 4, 5, 6, [7]]
+ assert.deepEqual Epoch.Util.flatten(multiarray), expected
+
+ it 'should throw if given a non-array', ->
+ assert.throws (-> Epoch.Util.flatten null), /only accepts arrays/
+ assert.throws (-> Epoch.Util.flatten 1), /only accepts arrays/
+ assert.throws (-> Epoch.Util.flatten {}), /only accepts arrays/
+ assert.throws (-> Epoch.Util.flatten 'hellooo'), /only accepts arrays/
+ assert.throws (-> Epoch.Util.flatten new Error()), /only accepts arrays/
diff --git a/debian/missing-sources/epoch/tests/unit/data/array_format.coffee b/debian/missing-sources/epoch/tests/unit/data/array_format.coffee
new file mode 100644
index 0000000..a043a1e
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/data/array_format.coffee
@@ -0,0 +1,106 @@
+describe 'Epoch.Data.Format.array', ->
+ startTime = 1000
+
+ it 'should format flat arrays', ->
+ expected = [ {values: [{x: 0, y: 1}, {x: 1, y: 2}, {x: 2, y: 3}]} ]
+ assert.data expected, Epoch.Data.Format.array([1, 2, 3])
+
+ it 'should format multi-dimensional arrays', ->
+ expected = [
+ { values: [{x: 0, y: 1}, {x: 1, y: 2}]},
+ { values: [{x: 0, y: 3}, {x: 1, y: 4}]}
+ ]
+ assert.data expected, Epoch.Data.Format.array([[1, 2], [3, 4]])
+
+ it 'should respect the x option', ->
+ expected = [{values: [{x: 1, y: 1}, {x: 2, y: 2}]}]
+ result = Epoch.Data.Format.array [1, 2], {x: (d, i) -> i+1}
+ assert.data expected, result
+
+ it 'should respect the y option', ->
+ expected = [{values: [{x: 0, y: 2}, {x: 1, y: 4}]}]
+ result = Epoch.Data.Format.array [1, 2], {y: (d) -> d*2}
+ assert.data expected, result
+
+ it 'should format pie chart data with flat arrays', ->
+ input = [20, 30, 40]
+ expected = ({value: v} for v in input)
+ result = Epoch.Data.Format.array input, {type: 'pie'}
+ assert.equal expected.length, result.length, "Result did not have the expected number of layers"
+ for i in [0...expected.length]
+ assert.equal expected[i].value, result[i].value, "Result #{i} did not have the epected value"
+
+ it 'should not format pie chart data with multi-dimensional arrays', ->
+ assert.equal Epoch.Data.Format.array([[1], [2]], {type: 'pie'}).length, 0
+
+ it 'should format real-time plot data with flat arrays', ->
+ input = [1, 2, 3]
+ expected = [{ values: ({time: startTime+parseInt(i), y: v} for i,v of input) }]
+ result = Epoch.Data.Format.array(input, {type: 'time.line', startTime: startTime})
+ assert.timeData expected, result
+
+ it 'should format real-time plot data with multi-dimensional arrays', ->
+ input = [[1, 2], [3, 4]]
+ expected = []
+ for layer in input
+ expected.push {values: ({time: startTime+parseInt(i), y: v} for i, v of layer)}
+ result = Epoch.Data.Format.array(input, {type: 'time.line', startTime: startTime})
+ assert.timeData expected, result
+
+ it 'should format heatmap data with flat arrays', ->
+ input = [{'1': 1, '2': 2}, {'3': 3, '4': 4}]
+ expected = [{values: ({time: startTime+parseInt(i), histogram: h} for i, h of input)}]
+ result = Epoch.Data.Format.array(input, {type: 'time.heatmap', startTime: startTime})
+ assert.data expected, result, ['time', 'heatmap']
+
+ it 'should format heatmap data with multi-dimensional arrays', ->
+ input = [
+ [{'1': 1, '2': 2}, {'3': 3, '4': 4}],
+ [{'5': 5, '6': 6}, {'7': 7, '8': 8}]
+ ]
+ expected = [
+ { values: ({time: startTime+parseInt(i), histogram: h} for i, h of input[0]) },
+ { values: ({time: startTime+parseInt(i), histogram: h} for i, h of input[1]) },
+ ]
+ result = Epoch.Data.Format.array(input, {type: 'time.heatmap', startTime: startTime})
+ assert.data expected, result, ['time', 'heatmap']
+
+ it 'should correctly apply labels if the labels option is present', ->
+ labels = ['alpha', 'beta']
+ result = Epoch.Data.Format.array [[1], [2]], {labels: labels}
+ for i in [0...labels.length]
+ assert.equal labels[i], result[i].label
+
+ it 'should correctly apply labels if the autoLabels option is set', ->
+ labels = ['A', 'B', 'C']
+ result = Epoch.Data.Format.array [[1], [2], [3]], {autoLabels: true}
+ for i in [0...labels.length]
+ assert.equal labels[i], result[i].label
+
+ it 'should prefer the labels option to the autoLabels option if both are set', ->
+ labels = ['alpha', 'beta']
+ result = Epoch.Data.Format.array [[1], [2]], {labels: labels, autoLabels: true}
+ for i in [0...labels.length]
+ assert.equal labels[i], result[i].label
+
+ it 'should produce single series entries correctly', ->
+ result = Epoch.Data.Format.array.entry(2)
+ assert.isArray result
+ assert.equal 1, result.length
+ assert.isObject result[0]
+ assert.equal 0, result[0].x
+ assert.equal 2, result[0].y
+
+ it 'should produce multi-series entries correctly', ->
+ expected = [
+ { x: 0, y: 1 },
+ { x: 0, y: 2 },
+ { x: 0, y: 3 }
+ ]
+ result = Epoch.Data.Format.array.entry([1, 2, 3])
+ assert.isArray result
+ assert.equal 3, result.length
+ for i in [0...expected.length]
+ assert.isObject result[i]
+ assert.equal expected[i].x, result[i].x
+ assert.equal expected[i].y, result[i].y
diff --git a/debian/missing-sources/epoch/tests/unit/data/chart.coffee b/debian/missing-sources/epoch/tests/unit/data/chart.coffee
new file mode 100644
index 0000000..ed115a1
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/data/chart.coffee
@@ -0,0 +1,121 @@
+
+describe 'Epoch.Chart.options', ->
+ it 'should set the type option to "area" for basic area charts', ->
+ assert.equal new Epoch.Chart.Area().options.type, 'area'
+
+ it 'should set the type option to "bar" for basic bar charts', ->
+ assert.equal new Epoch.Chart.Bar().options.type, 'bar'
+
+ it 'should set the type option to "histogram" for basic histogram charts', ->
+ assert.equal new Epoch.Chart.Histogram().options.type, 'histogram'
+
+ it 'should set the type option to "line" for basic line charts', ->
+ assert.equal new Epoch.Chart.Line().options.type, 'line'
+
+ it 'should set the type option to "pie" for basic pie charts', ->
+ assert.equal new Epoch.Chart.Pie().options.type, 'pie'
+
+ it 'should set the type option to "scatter" for basic scatter charts', ->
+ assert.equal new Epoch.Chart.Scatter().options.type, 'scatter'
+
+ it 'should set the type option to "time.area" for real-time area charts', ->
+ assert.equal new Epoch.Time.Area().options.type, 'time.area'
+
+ it 'should set the type option to "time.bar" for real-time bar charts', ->
+ assert.equal new Epoch.Time.Bar().options.type, 'time.bar'
+
+ it 'should set the type option to "time.gauge" for real-time gauge charts', ->
+ assert.equal new Epoch.Time.Gauge().options.type, 'time.gauge'
+
+ it 'should set the type option to "time.heatmap" for real-time heatmap charts', ->
+ assert.equal new Epoch.Time.Heatmap().options.type, 'time.heatmap'
+
+ it 'should set the type option to "time.line" for real-time line charts', ->
+ assert.equal new Epoch.Time.Line().options.type, 'time.line'
+
+describe 'Epoch.Chart._formatData', ->
+ assertBasicData = (klassName, type) ->
+ data = [1, 2, 3, 4]
+ expected = Epoch.data 'array', data, {type: type}
+ chart = new Epoch.Chart[klassName]
+ data: data
+ dataFormat: 'array'
+ assert.data expected, chart.data
+
+ assertTimeData = (klassName, type) ->
+ data = [1, 2, 3, 4]
+ expected = Epoch.data 'array', data, {type: type, time: (d, i) -> parseInt(i)}
+ chart = new Epoch.Time[klassName]
+ data: data
+ dataFormat:
+ name: 'array'
+ options: { time: (d, i) -> parseInt(i) }
+ assert.timeData expected, chart.data
+
+ it 'should correctly detect and format array type data', ->
+ data = [1, 2, 3]
+ expected = Epoch.data 'array', data
+ chart = new Epoch.Chart.Base
+ data: data
+ dataFormat: 'array'
+ assert.data expected, chart.data
+
+ it 'should correctly detect and format tuple type data', ->
+ data = [[1, 1], [2, 4], [3, 78]]
+ expected = Epoch.data 'tuple', data
+ chart = new Epoch.Chart.Base
+ data: data
+ dataFormat: 'tuple'
+ assert.data expected, chart.data
+
+ it 'should correctly detect and format keyvalue type data', ->
+ data = [ {a: 20, b: 30, x: 10}, {a: 40, b: 50, x: 20} ]
+ expected = Epoch.data 'keyvalue', data, ['a', 'b'], { x: (d) -> d.x }
+ chart = new Epoch.Chart.Base
+ data: data
+ dataFormat:
+ name: 'keyvalue'
+ arguments: [['a', 'b']]
+ options: { x: (d, i) -> d.x }
+ assert.data expected, chart.data
+
+ it 'should correctly format area chart data', ->
+ assertBasicData 'Area', 'area'
+
+ it 'should correctly format bar chart data', ->
+ assertBasicData 'Bar', 'bar'
+
+ it 'should correctly format line data', ->
+ assertBasicData 'Line', 'line'
+
+ it 'should correctly format scatter data', ->
+ assertBasicData 'Scatter', 'scatter'
+
+ it 'should correctly format pie data', ->
+ data = [1, 2, 3]
+ expected = data.map (d) -> {value: d}
+ result = (new Epoch.Chart.Pie(data: data, dataFormat: 'array')).data
+ for i in [0...expected.length]
+ assert.equal expected[i].value, result[i].value
+
+ it 'should correctly format histogram data', ->
+ data = (parseInt(Math.random() * 100) for i in [0...100])
+ format = Epoch.data('array', data, { type: 'histogram' })
+ expected = (new Epoch.Chart.Histogram())._prepareData(format)
+ chart = new Epoch.Chart.Histogram({ data: data, dataFormat: 'array' })
+ assert.data expected, chart.data
+
+ it 'should correctly format real-time area data', ->
+ assertTimeData 'Area', 'time.area'
+
+ it 'should correctly format real-time bar data', ->
+ assertTimeData 'Bar', 'time.bar'
+
+ it 'should correctly format real-time heatmap data', ->
+ assertTimeData 'Heatmap', 'time.heatmap'
+
+ it 'should correctly format real-time line data', ->
+ assertTimeData 'Line', 'time.line'
+
+
+
diff --git a/debian/missing-sources/epoch/tests/unit/data/keyvalue_format.coffee b/debian/missing-sources/epoch/tests/unit/data/keyvalue_format.coffee
new file mode 100644
index 0000000..1ac5fcc
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/data/keyvalue_format.coffee
@@ -0,0 +1,101 @@
+describe 'Epoch.Data.Format.keyvalue', ->
+
+ data = [
+ { x: 1, a: 20, b: 30, c: 40, hist: 10, time: 0 },
+ { x: 2, a: 45, b: 83, c: 8, hist: 11, time: 1 },
+ { x: 3, a: 17, b: 72, c: 54, hist: 12, time: 2 },
+ { x: 4, a: 99, b: 19, c: 39, hist: 13, time: 3 }
+ ]
+
+ it 'should format a single series for basic plots', ->
+ expected = [{ values: (data.map (d, i) -> { x: parseInt(i), y: d.a }) }]
+ result = Epoch.Data.Format.keyvalue(data, ['a'])
+ assert.data expected, result
+
+ it 'should format multiple series for basic plots', ->
+ expected = [
+ { values: (data.map (d, i) -> {x: parseInt(i), y: d.a }) },
+ { values: (data.map (d, i) -> {x: parseInt(i), y: d.b }) },
+ { values: (data.map (d, i) -> {x: parseInt(i), y: d.c }) }
+ ]
+ result = Epoch.Data.Format.keyvalue(data, ['a', 'b', 'c'])
+ assert.data expected, result
+
+ it 'should format a single series for real-time plots', ->
+ expected = [
+ { values: (data.map (d, i) -> { time: d.time, y: d.a }) }
+ ]
+ result = Epoch.Data.Format.keyvalue(data, ['a'], { type: 'time.line', time: (d) -> d.time })
+ assert.data expected, result
+
+ it 'should format multiple series for real-time plots', ->
+ expected = [
+ { values: (data.map (d, i) -> { time: d.time, y: d.a }) }
+ { values: (data.map (d, i) -> { time: d.time, y: d.b }) }
+ { values: (data.map (d, i) -> { time: d.time, y: d.c }) }
+ ]
+ result = Epoch.Data.Format.keyvalue(data, ['a', 'b', 'c'], { type: 'time.line', time: (d) -> d.time })
+ assert.data expected, result
+
+ it 'should correctly format heatmap data', ->
+ expected = [
+ { values: (data.map (d, i) -> {time: d.time, histogram: d.hist }) }
+ ]
+ result = Epoch.Data.Format.keyvalue(data, ['hist'], {type: 'time.heatmap', time: ((d) -> d.time) })
+ assert.data expected, result
+
+ it 'should return an empty set for type time.gauge and type pie', ->
+ assert.equal Epoch.Data.Format.keyvalue(data, ['a'], {type: 'pie'}).length, 0
+ assert.equal Epoch.Data.Format.keyvalue(data, ['a'], {type: 'time.gauge'}).length, 0
+
+ it 'should respect the x option', ->
+ expected = [{ values: (data.map (d, i) -> {x: d.x, y: d.a }) }]
+ result = Epoch.Data.Format.keyvalue(data, ['a'], {x: (d) -> d.x})
+ assert.data expected, result
+
+ it 'should respect the y option', ->
+ expected = [{ values: (data.map (d, i) -> {x: parseInt(i), y: d.a + 2 }) }]
+ result = Epoch.Data.Format.keyvalue(data, ['a'], {y: (d) -> d + 2})
+ assert.data expected, result
+
+ it 'should apply key name labels by default', ->
+ labels = ['a', 'b', 'c', 'hist']
+ layers = Epoch.Data.Format.keyvalue(data, ['a', 'b', 'c', 'hist'])
+ for i in [0...labels.length]
+ assert.equal labels[i], layers[i].label
+
+ it 'should override key name labels with given labels', ->
+ labels = ['x', 'y', 'z']
+ layers = Epoch.Data.Format.keyvalue(data, ['a', 'b', 'c'], {labels: labels})
+ for i in [0...labels.length]
+ assert.equal labels[i], layers[i].label
+
+ it 'should apply automatic labels only when labels are not given and key labels are off', ->
+ labels = ['A', 'B']
+ layers = Epoch.Data.Format.keyvalue(data, ['a', 'b'], {keyLabels: false, autoLabels: true})
+ for i in [0...labels.length]
+ assert.equal labels[i], layers[i].label
+
+ it 'should produce single series entries correctly', ->
+ input = data[0]
+ keys = ['a']
+ expected = [{x: 0, y: input.a}]
+ result = Epoch.Data.Format.keyvalue.entry(input, keys)
+ assert.isArray result
+ assert.equal 1, result.length
+ assert.isObject result[0]
+ assert.equal 0, result[0].x
+ assert.equal input.a, result[0].y
+
+ it 'should produce multi-series entries correctly', ->
+ input = data[1]
+ keys = ['a', 'b', 'c']
+ options = {x: 'x'}
+ expected = ({x: input.x, y: input[key]} for key in keys)
+ result = Epoch.Data.Format.keyvalue.entry(input, keys, options)
+ assert.isArray result
+ assert.equal expected.length, result.length
+ for i in [0...expected.length]
+ assert.isObject result[i]
+ assert.equal expected[i].x, result[i].x
+ assert.equal expected[i].y, result[i].y
diff --git a/debian/missing-sources/epoch/tests/unit/data/tuple_format.coffee b/debian/missing-sources/epoch/tests/unit/data/tuple_format.coffee
new file mode 100644
index 0000000..a55f559
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/data/tuple_format.coffee
@@ -0,0 +1,76 @@
+describe 'Epoch.Data.Format.tuple', ->
+ it 'should format flat tuple arrays', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d) -> {x: d[0], y: d[1]})}]
+ result = Epoch.Data.Format.tuple(input)
+ assert.data expected, result
+
+ it 'should format nested layers of tuple arrays', ->
+ input = [
+ [ [1, 2], [3, 4] ],
+ [ [5, 6], [7, 8] ]
+ ]
+ expected = input.map (series) ->
+ {values: series.map((d) -> {x: d[0], y: d[1]})}
+ result = Epoch.Data.Format.tuple(input)
+ assert.data expected, result
+
+ it 'should respect the x option', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d, i) -> {x: i, y: d[1]})}]
+ result = Epoch.Data.Format.tuple(input, {x: (d, i) -> i})
+ assert.data expected, result
+
+ it 'should respect the y option', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d, i) -> {x: d[0], y: i})}]
+ result = Epoch.Data.Format.tuple(input, {y: (d, i) -> i})
+ assert.data expected, result
+
+ it 'should format flat tuples of real-time data', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d) -> {time: d[0], y: d[1]})}]
+ result = Epoch.Data.Format.tuple(input, {type: 'time.line'})
+ assert.data expected, result
+
+ it 'should format nested layers of real-time tuple data', ->
+ input = [
+ [ [1, 2], [3, 4] ],
+ [ [5, 6], [7, 8] ]
+ ]
+ expected = input.map (series) ->
+ {values: series.map((d) -> {time: d[0], y: d[1]})}
+ result = Epoch.Data.Format.tuple(input, {type: 'time.line'})
+ assert.data expected, result
+
+ it 'should respect the time option', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d, i) -> {time: i, y: d[1]})}]
+ result = Epoch.Data.Format.tuple(input, {type: 'time.line', time: (d, i) -> i})
+ assert.data expected, result
+
+ it 'should ignore heatmap, pie, and gauge charts', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ assert.equal 0, Epoch.Data.Format.tuple(input, {type: 'time.heatmap'}).length
+ assert.equal 0, Epoch.Data.Format.tuple(input, {type: 'time.gauge'}).length
+ assert.equal 0, Epoch.Data.Format.tuple(input, {type: 'pie'}).length
+
+ it 'should produce single series entries correctly', ->
+ input = [5, 6]
+ result = Epoch.Data.Format.tuple.entry(input)
+ assert.isArray result
+ assert.equal 1, result.length
+ assert.isObject result[0]
+ assert.equal input[0], result[0].x
+ assert.equal input[1], result[0].y
+
+ it 'should produce multi-series entries correctly', ->
+ input = [[5, -10], [4, 8], [2, 3]]
+ expected = ({x: d[0], y: d[1]} for d in input)
+ result = Epoch.Data.Format.tuple.entry(input)
+ assert.isArray result
+ assert.equal expected.length, result.length
+ for i in [0...expected.length]
+ assert.isObject result[i]
+ assert.equal expected[i].x, result[i].x
+ assert.equal expected[i].y, result[i].y
diff --git a/debian/missing-sources/epoch/tests/unit/init.coffee b/debian/missing-sources/epoch/tests/unit/init.coffee
new file mode 100644
index 0000000..aa8edd2
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/init.coffee
@@ -0,0 +1,55 @@
+process.env.TZ = "America/Los_Angeles"
+
+jsdom = require('jsdom')
+global.assert = require('chai').assert
+url = require('url')
+
+html = "<html><head></head><body></body></html>"
+
+exec = require('child_process').exec
+exec 'pwd', (err, out) -> console.log out
+
+before (done) ->
+ jsdom.env
+ html: html
+ scripts: ["http://d3js.org/d3.v3.min.js", "./dist/js/epoch.js"]
+ done: (errors, window) ->
+ global.Epoch = window.Epoch
+ # Override get context to use a test context by default
+ global.Epoch.Util.getContext = -> new window.Epoch.TestContext()
+ global.d3 = window.d3
+ global.doc = window.document
+ # Set this to "retina" so we can test canvas based charts
+ window.devicePixelRatio = 2
+ done()
+
+global.addStyleSheet = (css) ->
+ head = doc.head
+ style = doc.createElement('style')
+ style.type = 'text/css'
+ style.appendChild(doc.createTextNode(css))
+ head.appendChild(style)
+ style
+
+global.layerWithRange = (min, max, range) ->
+ layer = { values: [{time: 0, y: min}, {time: 1, y: max}] }
+ layer.range = range if range?
+ layer
+
+#
+# Helper assertion methods for data format testing
+#
+assert.data = (expected, result, checkAttributes) ->
+ checkAttributes ?= ['x', 'y']
+ assert.equal expected.length, result.length
+ for i, layer of expected
+ resultLayer = result[i]
+ msg = "Result layer #{i} does not have expected number of values."
+ assert.equal layer.values.length, resultLayer.values.length, msg
+ for j in [0...layer.values.length]
+ for k in checkAttributes
+ msg = "Layer #{i} data point #{j} does not have the expected value for key #{k}"
+ assert.equal layer.values[j][k], resultLayer.values[j][k], msg
+
+assert.timeData = (expected, result) ->
+ assert.data(expected, result, ['time', 'y'])
diff --git a/debian/missing-sources/epoch/tests/unit/time.coffee b/debian/missing-sources/epoch/tests/unit/time.coffee
new file mode 100644
index 0000000..48593a2
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/time.coffee
@@ -0,0 +1,67 @@
+sinon = require 'sinon'
+
+describe 'Epoch.Time.Plot', ->
+ chart = null
+
+ beforeEach ->
+ chart = new Epoch.Time.Plot(data: [layerWithRange(0, 100)])
+
+ describe 'y', ->
+ scaleDomain = [-524, 2324]
+ beforeEach -> sinon.stub(chart, '_getScaleDomain').returns(scaleDomain)
+ afterEach -> chart._getScaleDomain.restore()
+
+ it 'should get the scale domain from the given domain', ->
+ y = chart.y('a')
+ assert.ok chart._getScaleDomain.calledWith('a')
+ assert.deepEqual y.domain(), scaleDomain
+
+ describe 'ySvg', ->
+ scaleDomain = [3004, 10000000]
+ beforeEach -> sinon.stub(chart, '_getScaleDomain').returns(scaleDomain)
+ afterEach -> chart._getScaleDomain.restore()
+
+ it 'should get the scale domain from the given domain', ->
+ y = chart.ySvg('a')
+ assert.ok chart._getScaleDomain.calledWith('a')
+ assert.deepEqual y.domain(), scaleDomain
+
+ describe 'ySvgLeft', ->
+ beforeEach -> sinon.spy(chart, 'ySvg')
+ afterEach -> chart.ySvg.restore()
+
+ it 'should use the left range when present', ->
+ chart.options.range = { left: 'apples' }
+ chart.ySvgLeft()
+ assert.ok chart.ySvg.calledWith('apples')
+
+ it 'should not use the left range when missing', ->
+ chart.ySvgLeft()
+ assert.ok chart.ySvg.calledOnce
+
+ describe 'ySvgRight', ->
+ beforeEach -> sinon.spy(chart, 'ySvg')
+ afterEach -> chart.ySvg.restore()
+
+ it 'should use the right range when present', ->
+ chart.options.range = { right: 'oranges' }
+ chart.ySvgRight()
+ assert.ok chart.ySvg.calledWith('oranges')
+
+ it 'should not use the right range when missing', ->
+ chart.ySvgRight()
+ assert.ok chart.ySvg.calledOnce
+
+ describe 'leftAxis', ->
+ beforeEach -> sinon.spy chart, 'ySvgLeft'
+ afterEach -> chart.ySvgLeft.restore()
+ it 'uses the left svg scale', ->
+ chart.leftAxis()
+ assert.ok chart.ySvgLeft.calledOnce
+
+ describe 'rightAxis', ->
+ beforeEach -> sinon.spy chart, 'ySvgRight'
+ afterEach -> chart.ySvgRight.restore()
+ it 'uses the right svg scale', ->
+ chart.rightAxis()
+ assert.ok chart.ySvgRight.calledOnce
diff --git a/debian/missing-sources/epoch/tests/unit/time/line.coffee b/debian/missing-sources/epoch/tests/unit/time/line.coffee
new file mode 100644
index 0000000..fa6c205
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/time/line.coffee
@@ -0,0 +1,15 @@
+sinon = require 'sinon'
+
+describe 'Epoch.Time.Line', ->
+ chart = null
+ beforeEach ->
+ chart = new Epoch.Time.Line
+ data: [{ range: 'foo', values: [{time: 0, y: 10}, {time: 1, y: 30}] }]
+
+ describe 'draw', ->
+ beforeEach -> sinon.spy chart, 'y'
+ afterEach -> chart.y.restore()
+
+ it 'should provide the layer\'s range to the y scale', ->
+ chart.draw()
+ assert.ok chart.y.calledWith('foo')