diff options
Diffstat (limited to 'debian/missing-sources/epoch/tests/unit')
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') |