From e6e215a0e493ed9e7eb30da8e6ce82f05a6907cf Mon Sep 17 00:00:00 2001 From: Cassie Date: Mon, 10 Aug 2015 13:50:22 -0700 Subject: [PATCH 001/160] key, pzi limits, entities nearest, disable interactions super test --- .../tests/interactions/key_zoom_pointer.js | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 quicktests/overlaying/tests/interactions/key_zoom_pointer.js diff --git a/quicktests/overlaying/tests/interactions/key_zoom_pointer.js b/quicktests/overlaying/tests/interactions/key_zoom_pointer.js new file mode 100644 index 0000000000..94916dedda --- /dev/null +++ b/quicktests/overlaying/tests/interactions/key_zoom_pointer.js @@ -0,0 +1,90 @@ +function makeData() { + "use strict"; + return [makeRandomData(30), makeRandomData(30)]; +} + +function run(svg, data, Plottable) { + "use strict"; + + var xScaleSquare = new Plottable.Scales.Linear(); + var xScaleTriangle = new Plottable.Scales.ModifiedLog(); + var yScale = new Plottable.Scales.Linear(); + var xAxisSquare = new Plottable.Axes.Numeric(xScaleSquare, "bottom"); + var xAxisTriangle = new Plottable.Axes.Numeric(xScaleTriangle, "top"); + var yAxis = new Plottable.Axes.Numeric(yScale, "left"); + + var dsSquare = new Plottable.Dataset(data[0], { shape: "square" }); + var dsTriangle = new Plottable.Dataset(data[1], { shape: "triangle" }); + + var squareLabel = new Plottable.Components.Label("Square Data Points", 0); + var triangleLabel = new Plottable.Components.Label("Triangle Data Points", 0); + var titleLabel = new Plottable.Components.Label("Press 'P' to panzoom", 0); + + var symbolAccessor = function (d, i, ds) { + if (ds.metadata()['shape'] === "square") { + return Plottable.SymbolFactories.square(); + } else { + return Plottable.SymbolFactories.triangleUp(); + } + }; + + var plotSquare = new Plottable.Plots.Scatter() + .addDataset(dsSquare) + .x(function (d) { return d.x ; }, xScaleSquare) + .y(function (d) { return d.y - 1; }, yScale) + .size(20) + .symbol(symbolAccessor); + + var plotTriangle = new Plottable.Plots.Scatter() + .addDataset(dsTriangle) + .x(function (d) { return d.x * 10 ; }, xScaleTriangle) + .y(function (d) { return d.y; }, yScale) + .attr("fill", "#aaaaaa") + .size(20) + .symbol(symbolAccessor) + .deferredRendering(true); + + var plotGroup = new Plottable.Components.Group([plotSquare, plotTriangle]); + + var chart = new Plottable.Components.Table([ + [null, titleLabel], + [null, triangleLabel], + [null, xAxisTriangle], + [yAxis, plotGroup], + [null, xAxisSquare], + [null, squareLabel]]); + + chart.renderTo(svg); + + var pointer = new Plottable.Interactions.Pointer(); + var pointer_callback = function(p) { + plotSquare.entities().forEach(function(entity) { + entity.selection.attr("fill", "#5279C7"); + }); + var entity = plotSquare.entityNearest(p); + entity.selection.attr("fill", "red"); + }; + pointer.onPointerMove(pointer_callback); + pointer.attachTo(plotSquare); + + var pzi = new Plottable.Interactions.PanZoom(); + pzi.xScales([xScaleTriangle, xScaleSquare]); + pzi.maxDomainExtent(xScaleSquare, 1.5); + pzi.minDomainExtent(xScaleSquare, .5); + pzi.attachTo(plotGroup); + pzi.enabled(false); + + + var key = new Plottable.Interactions.Key(); + key.onKeyPress(80, function(keycode) { + pzi.enabled(true); + pointer.offPointerMove(pointer_callback); + }); + key.onKeyRelease(80, function(keycode) { + pzi.enabled(false); + pointer.onPointerMove(pointer_callback); + + }); + key.attachTo(plotGroup); + +} From 21d4b15a0d8ddebe324ae6988ea66479fa83b110 Mon Sep 17 00:00:00 2001 From: Cassie Date: Fri, 14 Aug 2015 15:59:27 -0700 Subject: [PATCH 002/160] update formatters and mondrian --- .../overlaying/tests/functional/formatter.js | 26 +++++++++---------- .../tests/realistic/numeric_grid.js | 13 ++++++++++ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/quicktests/overlaying/tests/functional/formatter.js b/quicktests/overlaying/tests/functional/formatter.js index b7dde1fe62..61cfc0565c 100644 --- a/quicktests/overlaying/tests/functional/formatter.js +++ b/quicktests/overlaying/tests/functional/formatter.js @@ -42,32 +42,32 @@ function run(svg, data, Plottable) { bigTable.renderTo(svg); function useIdentityFormatter() { - xAxis.formatter(Plottable.Formatters.identity()); + xAxis.formatter(Plottable.Formatters.identity(2.1)); yAxis.formatter(Plottable.Formatters.identity()); } function useGeneralFormatter() { - xAxis.formatter(Plottable.Formatters.general(2)); - yAxis.formatter(Plottable.Formatters.general(2)); + xAxis.formatter(Plottable.Formatters.general(7)); + yAxis.formatter(Plottable.Formatters.general(3)); } function useFixedFormatter() { - xAxis.formatter(Plottable.Formatters.fixed(2)); - yAxis.formatter(Plottable.Formatters.fixed(2)); + xAxis.formatter(Plottable.Formatters.fixed(2.00)); + yAxis.formatter(Plottable.Formatters.fixed(7.00)); } function useCurrencyFormatter() { - xAxis.formatter(Plottable.Formatters.currency(2, "$", true)); - yAxis.formatter(Plottable.Formatters.currency(2, "$", true)); + xAxis.formatter(Plottable.Formatters.currency(3, "$", true)); + yAxis.formatter(Plottable.Formatters.currency(3, "$", true)); } function usePercentageFormatter() { - xAxis.formatter(Plottable.Formatters.percentage(2)); - yAxis.formatter(Plottable.Formatters.percentage(2)); + xAxis.formatter(Plottable.Formatters.percentage(12.3 - 11.3)); + yAxis.formatter(Plottable.Formatters.percentage(2.5 + 1.5)); } function useSIFormatter() { - xAxis.formatter(Plottable.Formatters.siSuffix(2)); - yAxis.formatter(Plottable.Formatters.siSuffix(2)); + xAxis.formatter(Plottable.Formatters.siSuffix(7)); + yAxis.formatter(Plottable.Formatters.siSuffix(14)); } function useCustomFormatter() { - xAxis.formatter(custFormatter); - yAxis.formatter(custFormatter); + xAxis.formatter(Plottable.Formatters.shortScale(3)); + yAxis.formatter(Plottable.Formatters.shortScale(0)); } new Plottable.Interactions.Click().onClick(useIdentityFormatter).attachTo(IdTitle); diff --git a/quicktests/overlaying/tests/realistic/numeric_grid.js b/quicktests/overlaying/tests/realistic/numeric_grid.js index 747ddead58..a5ebb356f5 100644 --- a/quicktests/overlaying/tests/realistic/numeric_grid.js +++ b/quicktests/overlaying/tests/realistic/numeric_grid.js @@ -26,8 +26,21 @@ function run(svg, data, Plottable) { .x2(function(d){ return d.x2; }, xScale) .y2(function(d) { return d.y2; }, yScale) .attr("fill", function(d) { return d.fill; }) + .attr("opacity", .5) .attr("stroke", function(){ return "#000000"; }) .attr("stroke-width", function(){ return 4; }); plot.renderTo(svg); + + var hover = new Plottable.Interactions.Pointer(); + hover.onPointerMove(function(p){ + plot.entities().forEach(function(entity) { + entity.selection.attr("opacity", .5); + }); + var xRange = {min: p.x, max: p.x}; + var yRange = {min: p.y, max: p.y}; + var entities = plot.entitiesIn(xRange, yRange); + entities[0].selection.attr("opacity", 1); + }) + .attachTo(plot); } From a13d7181945ff74b0cf30e30323d523a495bf93f Mon Sep 17 00:00:00 2001 From: Cassie Date: Fri, 14 Aug 2015 16:05:42 -0700 Subject: [PATCH 003/160] guidelines --- .../tests/interactions/guidelines.js | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 quicktests/overlaying/tests/interactions/guidelines.js diff --git a/quicktests/overlaying/tests/interactions/guidelines.js b/quicktests/overlaying/tests/interactions/guidelines.js new file mode 100644 index 0000000000..b383892354 --- /dev/null +++ b/quicktests/overlaying/tests/interactions/guidelines.js @@ -0,0 +1,77 @@ +function makeData() { + "use strict"; + var makeGridData = function(x, y){ + var d = []; + for(var i = 0; i < x; i++){ + for(var j = 0; j < y; j++){ + d.push({x: i, x2: i + Math.random(), y: j, y2: j + Math.random()}); + } + } + return d; + } + return makeGridData(10, 10); +} + +function run(svg, data, Plottable) { + var ds = new Plottable.Dataset(data); + + var xScale = new Plottable.Scales.Linear().domain([0, 9.5]); + var yScale = new Plottable.Scales.Linear().domain([0, 9.5]); + + var accessor = function(key){ + return function(d){ + return d[key]; + } + } + + var plot = new Plottable.Plots.Rectangle() + .addDataset(ds) + .x(accessor("x"), xScale) + .y(accessor("y"), yScale) + .x2(accessor("x2")) + .y2(accessor("y2")) + .attr("fill", "#75acC7"); + + var val = 5; + var gllv = new Plottable.Components.GuideLineLayer("vertical"); + gllv.scale(xScale).value(val); + var gllh = new Plottable.Components.GuideLineLayer("horizontal"); + gllh.scale(yScale).value(val); + + var fillArea = function(xRange, yRange, fill){ + plot.entitiesIn(xRange, yRange).forEach(function(entity) { + entity.selection.attr("fill", fill); + }); + }; + + var updateColors = function(point){ + gllh.pixelPosition(point.y); + gllv.pixelPosition(point.x); + var plotLeft = xScale.range()[0]; + var plotRight = xScale.range()[1]; + var plotTop = yScale.range()[0]; + var plotBottom = yScale.range()[1]; + fillArea({min: point.x, max: plotRight}, + {min: point.y, max: plotTop}, + "#75acC7"); + fillArea({min: plotLeft, max: point.x}, + {min: point.y, max: plotTop}, + "#c775ac"); + fillArea({min: plotLeft, max: point.x}, + {min: plotBottom , max: point.y}, + "#acc775"); + fillArea({min: point.x, max: plotRight}, + {min: plotBottom, max: point.y}, + "#c7b975"); + } + + var group = new Plottable.Components.Group([plot, gllh, gllv]) + .renderTo(svg); + updateColors({x: gllv.pixelPosition(), y: gllh.pixelPosition()}); + + var followPlot = new Plottable.Interactions.Pointer() + .onPointerMove(function(point){ + updateColors(point); + }) + .attachTo(plot); +} From a625ab1870c547af051656a64c42195358b0555e Mon Sep 17 00:00:00 2001 From: Cassie Date: Fri, 14 Aug 2015 19:16:10 -0700 Subject: [PATCH 004/160] get rid of errors in numeric grid, add legend select --- .../tests/realistic/legend_select.js | 77 +++++++++++++++++++ .../tests/realistic/numeric_grid.js | 6 +- 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 quicktests/overlaying/tests/realistic/legend_select.js diff --git a/quicktests/overlaying/tests/realistic/legend_select.js b/quicktests/overlaying/tests/realistic/legend_select.js new file mode 100644 index 0000000000..977186f769 --- /dev/null +++ b/quicktests/overlaying/tests/realistic/legend_select.js @@ -0,0 +1,77 @@ +function makeData() { + "use strict"; + var data = {}; + data.blue = makeRandomData(12); + data.red = makeRandomData(12); + data.green = makeRandomData(12); + return data; + +} + +function run(svg, data, Plottable) { + "use strict"; + var title = new Plottable.Components.TitleLabel("Click legend entries to highlight plots", 0); + + var cs = new Plottable.Scales.Color(); + cs.range(["#ff0000", "#009900", "#0000ff"]); + cs.domain(["red", "green", "blue"]); + var legend = new Plottable.Components.Legend(cs); + + var xScale = new Plottable.Scales.Linear(); + var yScale = new Plottable.Scales.Linear(); + + var getX = function(d) { return d.x; }; + var getY = function(d) { return d.y; }; + + var plots = {}; + var plotGroupArray = []; + + var addPlot = function(color){ + var ds = new Plottable.Dataset(data[color]); + plots[color] = new Plottable.Plots.Line() + .addDataset(ds) + .x(getX, xScale) + .y(getY, yScale) + .attr("stroke", color, cs) + .interpolator("step") + plotGroupArray.push(plots[color]); + } + + addPlot("red"); + addPlot("blue"); + addPlot("green"); + + var plotGroup = new Plottable.Components.Group(plotGroupArray); + var table = new Plottable.Components.Table([[title, null], + [plotGroup, legend]]); + table.renderTo(svg); + + var legendInteraction = new Plottable.Interactions.Click(); + legendInteraction.onClick(function(point) { + for(var key in plots) { + plots[key].selections().attr("opacity", .3); + } + var datum = legend.entitiesAt(point)[0].datum; + plots[datum].selections().attr("opacity", 1); + legend.symbolOpacity(function(d) { + if (d === datum) { + return 1; + } + else{ + return .3; + } + }); + }); + legendInteraction.attachTo(legend); + + var plotInteraction = new Plottable.Interactions.Click(); + plotInteraction.onClick(function(point) { + for(var key in plots) { + plots[key].selections().attr("opacity", 1); + } + legend.symbolOpacity(function(d) { + return 1; + }); + }); + plotInteraction.attachTo(plotGroup); +} diff --git a/quicktests/overlaying/tests/realistic/numeric_grid.js b/quicktests/overlaying/tests/realistic/numeric_grid.js index a5ebb356f5..e2b74d223c 100644 --- a/quicktests/overlaying/tests/realistic/numeric_grid.js +++ b/quicktests/overlaying/tests/realistic/numeric_grid.js @@ -35,12 +35,14 @@ function run(svg, data, Plottable) { var hover = new Plottable.Interactions.Pointer(); hover.onPointerMove(function(p){ plot.entities().forEach(function(entity) { - entity.selection.attr("opacity", .5); + entity.selection.attr("opacity", .3); }); var xRange = {min: p.x, max: p.x}; var yRange = {min: p.y, max: p.y}; var entities = plot.entitiesIn(xRange, yRange); - entities[0].selection.attr("opacity", 1); + if (entities.length > 0) { + entities[0].selection.attr("opacity", 1); + } }) .attachTo(plot); } From a67ac6a602f5904b2f41aafe6bf7b3c8d33df29b Mon Sep 17 00:00:00 2001 From: Cassie Date: Tue, 18 Aug 2015 11:29:58 -0700 Subject: [PATCH 005/160] add waterfall, pie entitiesAt, pie labelFormatter --- .../tests/basic/negative_stacked_bar.js | 22 ++---- quicktests/overlaying/tests/basic/pies.js | 61 +++++++++++++++++ .../overlaying/tests/basic/waterfall.js | 67 +++++++++++++++++++ 3 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 quicktests/overlaying/tests/basic/pies.js create mode 100644 quicktests/overlaying/tests/basic/waterfall.js diff --git a/quicktests/overlaying/tests/basic/negative_stacked_bar.js b/quicktests/overlaying/tests/basic/negative_stacked_bar.js index 5ff2daef3f..f0ec50a5d4 100644 --- a/quicktests/overlaying/tests/basic/negative_stacked_bar.js +++ b/quicktests/overlaying/tests/basic/negative_stacked_bar.js @@ -4,17 +4,15 @@ function makeData() { var data1 = [{team: "Team A", earnings: 400000, quarter: "q1"}, {team: "Team A", earnings: -300000, quarter: "q2"}, {team: "Team A", earnings: 600000, quarter: "q3"}, {team: "Team A", earnings: -100000, quarter: "q4"}]; var data2 = [{team: "Team B", earnings: 200000, quarter: "q1"}, {team: "Team B", earnings: 300000, quarter: "q2"}, {team: "Team B", earnings: 500000, quarter: "q3"}, {team: "Team B", earnings: 400000, quarter: "q4"}]; var data3 = [{team: "Team C", earnings: -200000, quarter: "q1"}, {team: "Team C", earnings: 0, quarter: "q2"}, {team: "Team C", earnings: -100000, quarter: "q3"}, {team: "Team C", earnings: 300000, quarter: "q4"}]; - var data4 = [{team: "Team D", earnings: -15000, quarter: "q1"}, {team: "Team D", earnings: -23000, quarter: "q2"}, {team: "Team D", earnings: 200000, quarter: "q3"}, {team: "Team D", earnings: -1300000, quarter: "q4"}]; - var data5 = [{team: "Team E", earnings: 90000, quarter: "q1"}, {team: "Team E", earnings: 170000, quarter: "q2"}, {team: "Team E", earnings: 50000, quarter: "q3"}, {team: "Team E", earnings: 300000, quarter: "q4"}]; - return [data1, data2, data3, data4, data5]; + return [data1, data2, data3]; } function run(svg, data, Plottable) { "use strict"; var xScale1 = new Plottable.Scales.Category(); - var yScale1 = new Plottable.Scales.Linear(); - var xScale2 = new Plottable.Scales.Linear(); + var yScale1 = new Plottable.Scales.ModifiedLog(); + var xScale2 = new Plottable.Scales.ModifiedLog(); var yScale2 = new Plottable.Scales.Category(); var colorScale = new Plottable.Scales.Color(); @@ -24,16 +22,10 @@ function run(svg, data, Plottable) { var xAxis2 = new Plottable.Axes.Numeric(xScale2, "bottom"); var yAxis2 = new Plottable.Axes.Category(yScale2, "left"); - var legend = new Plottable.Components.Legend(colorScale); - legend.xAlignment("center"); - - var title = new Plottable.Components.TitleLabel("Sample Net Earnings by Teams"); - var dataset1 = new Plottable.Dataset(data[0]); var dataset2 = new Plottable.Dataset(data[1]); var dataset3 = new Plottable.Dataset(data[2]); - var dataset4 = new Plottable.Dataset(data[3]); - var dataset5 = new Plottable.Dataset(data[4]); + var verticalPlot = new Plottable.Plots.StackedBar("vertical") .x(function(d) { return d.quarter; }, xScale1) @@ -42,8 +34,6 @@ function run(svg, data, Plottable) { .addDataset(dataset1) .addDataset(dataset2) .addDataset(dataset3) - .addDataset(dataset4) - .addDataset(dataset5) .labelsEnabled(true) .animated(true); @@ -60,8 +50,6 @@ function run(svg, data, Plottable) { .addDataset(dataset1) .addDataset(dataset2) .addDataset(dataset3) - .addDataset(dataset4) - .addDataset(dataset5) .labelsEnabled(true) .animated(true); @@ -80,8 +68,6 @@ function run(svg, data, Plottable) { ]); var finalchart = new Plottable.Components.Table([ - [title], - [legend], [chart1], [chart2] ]); diff --git a/quicktests/overlaying/tests/basic/pies.js b/quicktests/overlaying/tests/basic/pies.js new file mode 100644 index 0000000000..97b066bbd2 --- /dev/null +++ b/quicktests/overlaying/tests/basic/pies.js @@ -0,0 +1,61 @@ +function makeData() { + "use strict"; + var inner = [ + {key: "banana", value: 4}, + {key: "grape", value: 5}, + {key: "raspberry", value: 9}, + {key: "cherry", value: 2}, + {key: "peach", value: 8}, + {key: "apple", value: 6} + ]; + + var outer = [ + {key: "engine", value: 4}, + {key: "post-it note", value: 5}, + {key: "sunflower", value: 9}, + {key: "highlighter", value: 2} + ]; + + return [inner, outer]; +} + +function run(svg, data, Plottable){ + "use strict"; + + var cs = new Plottable.Scales.Color(); + + var innerPie = new Plottable.Plots.Pie(); + innerPie.addDataset(new Plottable.Dataset(data[0])); + innerPie.sectorValue(function(d){ return d.value; }) + .innerRadius(0) + .outerRadius(100) + .labelsEnabled(true) + .attr("opacity", .5) + .attr("fill", function(d){ return d.key; }, cs); + + + + var outerPie = new Plottable.Plots.Pie(); + outerPie.addDataset(new Plottable.Dataset(data[1])); + outerPie.sectorValue(function(d){ return d.value; }) + .innerRadius(100) + .outerRadius(200) + .labelsEnabled(true) + .labelFormatter(function(d){return "Value: " + d }) + .attr("fill", function(d){ return d.key; }, cs); + + var pies = new Plottable.Components.Group([innerPie, outerPie]); + pies.renderTo(svg); + + var pointer = new Plottable.Interactions.Pointer() + .onPointerMove(function(p){ + innerPie.entities().forEach(function(e){ + e.selection.attr("opacity", .5); + }); + var entity = innerPie.entitiesAt(p)[0]; + if(entity){ + entity.selection.attr("opacity", 1); + } + }) + .attachTo(innerPie); +} diff --git a/quicktests/overlaying/tests/basic/waterfall.js b/quicktests/overlaying/tests/basic/waterfall.js new file mode 100644 index 0000000000..641b386654 --- /dev/null +++ b/quicktests/overlaying/tests/basic/waterfall.js @@ -0,0 +1,67 @@ +function makeData() { + "use strict"; + var makeWaterfallData = function(cycles, start_total){ + var data = []; + if(start_total){ + data.push({ + x: "start", + y: start_total, + type: "total" + }); + } + var total = start_total || 0; + for( var i = 0; i < cycles; i++){ + var deltaPos = Math.random() * 10; + var deltaNeg = Math.random() * -5; + total = total + deltaPos + deltaNeg; + data.push({ + x: i.toString() + " N", + y: deltaNeg, + type: "delta" + }); + data.push({ + x: i.toString() + " P", + y: deltaPos, + type: "delta" + }); + data.push({ + x: i.toString() + " T", + y: total, + type: "total" + }); + } + return data; + } + return makeWaterfallData(5, 3); +} + +function run(svg, data, Plottable) { + var xScale = new Plottable.Scales.Category(); + var yScale = new Plottable.Scales.Linear(); + var xAxis = new Plottable.Axes.Category(xScale, "bottom"); + var yAxis = new Plottable.Axes.Numeric(yScale, "left"); + + var waterfall = new Plottable.Plots.Waterfall(); + waterfall.x(function(d) { return d.x; }, xScale); + waterfall.y(function(d) { return d.y; }, yScale); + waterfall.total(function(d) { return d.type === "total" ? true : false; }); + waterfall.connectorsEnabled(true); + waterfall.baselineValue(0); + waterfall.attr("fill", function(d){ + if(d.type === "total"){ + return "#abbabb" + } + else if (d.y > 0){ + return "#09cd2e" + } + else{ + return "#de345c" + } + }) + waterfall.addDataset(new Plottable.Dataset(data)); + + new Plottable.Components.Table([ + [yAxis, waterfall], + [null, xAxis] + ]).renderTo(svg); +} From f8a5e250a94a3fc146687ba89ec8c54b553aa001 Mon Sep 17 00:00:00 2001 From: Cassie Date: Tue, 18 Aug 2015 12:21:40 -0700 Subject: [PATCH 006/160] interpolation more places, entitiesAt rectangle, start dragbox --- .../overlaying/tests/interactions/dragbox.js | 48 +++++++++++++++++++ .../tests/realistic/numeric_grid.js | 4 +- .../overlaying/tests/realistic/stocks.js | 2 + 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 quicktests/overlaying/tests/interactions/dragbox.js diff --git a/quicktests/overlaying/tests/interactions/dragbox.js b/quicktests/overlaying/tests/interactions/dragbox.js new file mode 100644 index 0000000000..a98501d6fe --- /dev/null +++ b/quicktests/overlaying/tests/interactions/dragbox.js @@ -0,0 +1,48 @@ +function makeData() { + "use strict"; + var data = []; + + + for (var i = 0; i < 250; i++) { data.push({ + "x": i, + "y": Math.random(), + "symbol": Math.floor(6 * Math.random()), + "size": Math.floor(4 * Math.random()) + 4 + }); } + return data; + +} + +function run(svg, data, Plottable) { + "use strict"; + + var symbols = [ + Plottable.SymbolFactories.square(), + Plottable.SymbolFactories.circle(), + Plottable.SymbolFactories.cross(), + Plottable.SymbolFactories.diamond(), + Plottable.SymbolFactories.triangleUp(), + Plottable.SymbolFactories.triangleDown() + ]; + + var xScale = new Plottable.Scales.Linear(); + var yScale = new Plottable.Scales.Linear(); + var plot = new Plottable.Plots.Scatter() + .x(function(d) { return d.x; }, xScale) + .y(function(d) { return d.y; }, yScale) + .symbol(function(d) { return symbols[d.symbol];}) + .size(function(d) { return d.size;}) + .addDataset(new Plottable.Dataset(data)); + + var interaction = new Plottable.Interactions.Pointer(); + interaction.onPointerMove(function(p) { + plot.selections().attr("fill", "#5279C7"); + var entities = plot.entitiesAt(p); + if (entities.length > 0) { + entities.map(function(e){e.selection.attr("fill", "red")}); + } + }); + + interaction.attachTo(plot); + plot.renderTo(svg); +} diff --git a/quicktests/overlaying/tests/realistic/numeric_grid.js b/quicktests/overlaying/tests/realistic/numeric_grid.js index e2b74d223c..ba70b68cbc 100644 --- a/quicktests/overlaying/tests/realistic/numeric_grid.js +++ b/quicktests/overlaying/tests/realistic/numeric_grid.js @@ -37,9 +37,7 @@ function run(svg, data, Plottable) { plot.entities().forEach(function(entity) { entity.selection.attr("opacity", .3); }); - var xRange = {min: p.x, max: p.x}; - var yRange = {min: p.y, max: p.y}; - var entities = plot.entitiesIn(xRange, yRange); + var entities = plot.entitiesAt(p); if (entities.length > 0) { entities[0].selection.attr("opacity", 1); } diff --git a/quicktests/overlaying/tests/realistic/stocks.js b/quicktests/overlaying/tests/realistic/stocks.js index e6f7990820..bff0adf37b 100644 --- a/quicktests/overlaying/tests/realistic/stocks.js +++ b/quicktests/overlaying/tests/realistic/stocks.js @@ -69,12 +69,14 @@ function run(svg, data, Plottable) { .addDataset(aaplSource) .x(function(d) { return d.Date; }, xScale) .y(function(d) { return d["Adj Close"]; }, yScaleAAPL) + .interpolator("cardinal") .attr("stroke", function(d, index, dataset) { return dataset.metadata().name; }, colorScale); lineAAPL.autorangeMode("y"); var lineGOOG = new Plottable.Plots.Line().animated(true) .addDataset(googSource) .x(function(d) { return d.Date; }, xScale) .y(function(d) { return d["Adj Close"]; }, yScaleGOOG) + .interpolator("cardinal") .attr("stroke", function(d, index, dataset) { return dataset.metadata().name; }, colorScale); lineGOOG.autorangeMode("y"); From fd077d95727467ea750f5a8e7ce5dc2d131a8415 Mon Sep 17 00:00:00 2001 From: Cassie Date: Tue, 18 Aug 2015 13:25:04 -0700 Subject: [PATCH 007/160] entitiesIn/At for scatter --- .../overlaying/tests/interactions/dragbox.js | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/quicktests/overlaying/tests/interactions/dragbox.js b/quicktests/overlaying/tests/interactions/dragbox.js index a98501d6fe..720d3e9d6c 100644 --- a/quicktests/overlaying/tests/interactions/dragbox.js +++ b/quicktests/overlaying/tests/interactions/dragbox.js @@ -7,7 +7,7 @@ function makeData() { "x": i, "y": Math.random(), "symbol": Math.floor(6 * Math.random()), - "size": Math.floor(4 * Math.random()) + 4 + "size": Math.floor(10 * Math.random()) + 10 }); } return data; @@ -31,18 +31,51 @@ function run(svg, data, Plottable) { .x(function(d) { return d.x; }, xScale) .y(function(d) { return d.y; }, yScale) .symbol(function(d) { return symbols[d.symbol];}) + .attr("fill", "#dddddd") .size(function(d) { return d.size;}) .addDataset(new Plottable.Dataset(data)); - var interaction = new Plottable.Interactions.Pointer(); - interaction.onPointerMove(function(p) { - plot.selections().attr("fill", "#5279C7"); - var entities = plot.entitiesAt(p); - if (entities.length > 0) { - entities.map(function(e){e.selection.attr("fill", "red")}); - } - }); - - interaction.attachTo(plot); - plot.renderTo(svg); + var dragLabel = new Plottable.Components.Label("EntitiesIn", 0); + var clickLabel = new Plottable.Components.Label("EntitiesAt", 0); + + var dblX = new Plottable.Components.XDragBoxLayer() + .onDrag(function(bounds){ + plot.entities().forEach(function(e){ + e.selection.attr("fill", "#dddddd"); + }); + plot.entitiesIn(bounds).forEach(function(e){ + e.selection.attr("fill", "#34be6c"); + }); + }) + .movable(true); + + var hover = new Plottable.Interactions.Pointer() + .onPointerMove(function(p){ + plot.entities().forEach(function(e){ + e.selection.attr("fill", "#dddddd"); + }); + plot.entitiesAt(p).forEach(function(e){ + e.selection.attr("fill", "#be346c"); + }); + }) + .attachTo(plot) + .enabled(false); + + var enableDrag = new Plottable.Interactions.Click() + .onClick(function(p){ + hover.enabled(false); + dblX.enabled(true); + }) + .attachTo(dragLabel); + + var enableClick = new Plottable.Interactions.Click() + .onClick(function(p){ + hover.enabled(true); + dblX.enabled(false); + }) + .attachTo(clickLabel); + + var labels = new Plottable.Components.Table([[dragLabel], [clickLabel]]); + var group = new Plottable.Components.Group([plot, dblX]); + new Plottable.Components.Table([[group], [labels]]).renderTo(svg) } From 759acb5dcc55fef18e20616341c52ed4b2fcc730 Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Wed, 19 Aug 2015 09:43:30 -0700 Subject: [PATCH 008/160] Add stub for DragLineLayer, initial (failing) tests Tests for dragging and get/set-ers. Tests for callbacks and destroy() to be added. --- plottable.d.ts | 12 ++ plottable.js | 26 +++ src/components/dragLineLayer.ts | 18 ++ src/reference.ts | 1 + test/components/dragLineLayerTests.ts | 226 ++++++++++++++++++++++++++ test/testReference.ts | 1 + 6 files changed, 284 insertions(+) create mode 100644 src/components/dragLineLayer.ts create mode 100644 test/components/dragLineLayerTests.ts diff --git a/plottable.d.ts b/plottable.d.ts index ced206c7a9..fc8ab55da6 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -4406,3 +4406,15 @@ declare module Plottable { } } } + + +declare module Plottable { + module Components { + class DragLineLayer extends GuideLineLayer { + detectionRadius(): number; + detectionRadius(r: number): DragLineLayer; + enabled(): boolean; + enabled(enabled: boolean): DragLineLayer; + } + } +} diff --git a/plottable.js b/plottable.js index 7891b43ebb..9c818339d1 100644 --- a/plottable.js +++ b/plottable.js @@ -11464,6 +11464,32 @@ var Plottable; })(Components = Plottable.Components || (Plottable.Components = {})); })(Plottable || (Plottable = {})); +/// +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var Plottable; +(function (Plottable) { + var Components; + (function (Components) { + var DragLineLayer = (function (_super) { + __extends(DragLineLayer, _super); + function DragLineLayer() { + _super.apply(this, arguments); + } + DragLineLayer.prototype.detectionRadius = function (r) { + }; + DragLineLayer.prototype.enabled = function (enabled) { + }; + return DragLineLayer; + })(Components.GuideLineLayer); + Components.DragLineLayer = DragLineLayer; + })(Components = Plottable.Components || (Plottable.Components = {})); +})(Plottable || (Plottable = {})); + /*! SVG Typewriter 0.3.0 (https://github.com/palantir/svg-typewriter) Copyright 2014 Palantir Technologies diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts new file mode 100644 index 0000000000..cebfc451c0 --- /dev/null +++ b/src/components/dragLineLayer.ts @@ -0,0 +1,18 @@ +/// + +module Plottable { +export module Components { + export class DragLineLayer extends GuideLineLayer { + + public detectionRadius(): number; + public detectionRadius(r: number): DragLineLayer; + public detectionRadius(r?: number): any { + } + + public enabled(): boolean; + public enabled(enabled: boolean): DragLineLayer; + public enabled(enabled?: boolean): any { + } + } +} +} diff --git a/src/reference.ts b/src/reference.ts index ba5ebf9a65..fa9cad2c8c 100644 --- a/src/reference.ts +++ b/src/reference.ts @@ -92,3 +92,4 @@ /// /// /// +/// diff --git a/test/components/dragLineLayerTests.ts b/test/components/dragLineLayerTests.ts new file mode 100644 index 0000000000..5fc96c6226 --- /dev/null +++ b/test/components/dragLineLayerTests.ts @@ -0,0 +1,226 @@ +/// + +describe("Interactive Components", () => { + describe("DragLineLayer", () => { + it("get/set detectionRadius()", () => { + let dll = new Plottable.Components.DragLineLayer("vertical"); + assert.strictEqual(dll.detectionRadius(), 3, "defaults to 3"); + let setRadius = 6; + assert.strictEqual(dll.detectionRadius(setRadius), dll, "returns the calling DragLineLayer"); + assert.strictEqual(dll.detectionRadius(), 6, "getter returns the set value"); + // HACKHACK #2614: chai-assert.d.ts has the wrong signature + ( assert).throws(() => dll.detectionRadius(-1), Error, "", "rejects negative values"); + }); + + it("get/set enabled()", () => { + let dll = new Plottable.Components.DragLineLayer("vertical"); + assert.isTrue(dll.enabled(), "defaults to true"); + assert.strictEqual(dll.enabled(false), dll, "setter mode returns the calling DragLineLayer"); + assert.isFalse(dll.enabled(), "successfully set to false"); + }); + + it("shows the correct cursor (vertical)", () => { + let dll = new Plottable.Components.DragLineLayer("vertical"); + let svg = TestMethods.generateSVG(400, 300); + dll.renderTo(svg); + let dragEdge = dll.content().select(".drag-edge"); + let computedStyles = window.getComputedStyle( dragEdge.node()); + assert.strictEqual(computedStyles.cursor, "resize-ew", "shows the resize cursor if enabled"); + dll.enabled(false); + computedStyles = window.getComputedStyle( dragEdge.node()); + assert.strictEqual(computedStyles.cursor, "inherit", "cursor set to \"auto\" if not enabled"); + svg.remove(); + }); + + it("shows the correct cursor (horizontal)", () => { + let dll = new Plottable.Components.DragLineLayer("horizontal"); + let svg = TestMethods.generateSVG(300, 400); + dll.renderTo(svg); + let dragEdge = dll.content().select(".drag-edge"); + let computedStyles = window.getComputedStyle( dragEdge.node()); + assert.strictEqual(computedStyles.cursor, "resize-ns", "shows the resize cursor if enabled"); + dll.enabled(false); + computedStyles = window.getComputedStyle( dragEdge.node()); + assert.strictEqual(computedStyles.cursor, "inherit", "cursor set to \"auto\" if not enabled"); + svg.remove(); + }); + + describe("Dragging (vertical)", () => { + let SVG_WIDTH = 400; + let SVG_HEIGHT = 300; + + it("line can be dragged", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("vertical"); + let startX = SVG_WIDTH / 2; + dll.pixelPosition(startX); + dll.renderTo(svg); + let endX = SVG_WIDTH / 4; + TestMethods.triggerFakeDragSequence( + dll.content(), + { x: startX, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + TestMethods.assertLineAttrs( + dll.content().select(".guide-line"), + { + x1: endX, + y1: 0, + x2: endX, + y2: SVG_HEIGHT + }, + "line was dragged to the final location" + ); + assert.strictEqual(dll.pixelPosition(), endX, "pixelPosition was updated correctly"); + svg.remove(); + }); + + it("line can be dragged if drag starts within detectionRadius()", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("vertical"); + let startX = SVG_WIDTH / 2 + dll.detectionRadius(); + dll.pixelPosition(startX); + dll.renderTo(svg); + let endX = SVG_WIDTH / 4; + TestMethods.triggerFakeDragSequence( + dll.content(), + { x: startX, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + TestMethods.assertLineAttrs( + dll.content().select(".guide-line"), + { + x1: endX, + y1: 0, + x2: endX, + y2: SVG_HEIGHT + }, + "line was dragged to the final location" + ); + assert.strictEqual(dll.pixelPosition(), endX, "pixelPosition was updated correctly"); + svg.remove(); + }); + + it("starting a drag outside the detection radius does nothing", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("vertical"); + let startX = SVG_WIDTH / 2 + 2 * dll.detectionRadius(); + dll.pixelPosition(startX); + dll.renderTo(svg); + let endX = SVG_WIDTH / 4; + TestMethods.triggerFakeDragSequence( + dll.content(), + { x: startX, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + TestMethods.assertLineAttrs( + dll.content().select(".guide-line"), + { + x1: startX, + y1: 0, + x2: startX, + y2: SVG_HEIGHT + }, + "line did not move" + ); + svg.remove(); + }); + + it("can't be dragged if not enabled", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("vertical"); + dll.enabled(false); + let startX = SVG_WIDTH / 2; + dll.pixelPosition(startX); + dll.renderTo(svg); + let endX = SVG_WIDTH / 4; + TestMethods.triggerFakeDragSequence( + dll.content(), + { x: startX, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + TestMethods.assertLineAttrs( + dll.content().select(".guide-line"), + { + x1: startX, + y1: 0, + x2: startX, + y2: SVG_HEIGHT + }, + "line did not move" + ); + svg.remove(); + }); + + it("dragging does not affect the mode (value mode)", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("vertical"); + let scale = new Plottable.Scales.Linear(); + scale.domain([0, 1]); + dll.scale(scale); + + let startValue = 0.5; + dll.value(startValue); + dll.renderTo(svg); + + let startX = scale.scale(startValue); + let endX = SVG_WIDTH / 4; + TestMethods.triggerFakeDragSequence( + dll.content(), + { x: startX, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + let endValue = scale.invert(endX); + assert.strictEqual(dll.value(), endValue, "value was updated correctly"); + + scale.domain([0, 2]); + assert.strictEqual(dll.value(), endValue, "remained in \"value\" mode: value did not change when scale updated"); + svg.remove(); + }); + + it("dragging does not affect the mode (pixel mode)", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("vertical"); + let scale = new Plottable.Scales.Linear(); + scale.domain([0, 1]); + dll.scale(scale); + + let startX = SVG_WIDTH / 2; + dll.pixelPosition(startX); + dll.renderTo(svg); + + let endX = SVG_WIDTH / 4; + TestMethods.triggerFakeDragSequence( + dll.content(), + { x: startX, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + let endValue = scale.invert(endX); + assert.strictEqual(dll.value(), endValue, "value was updated correctly"); + + scale.domain([0, 2]); + assert.strictEqual(dll.pixelPosition(), endX, "remained in \"position\" mode: position did not change when scale updated"); + svg.remove(); + }); + }); + + // it("onDragStart()", () => { + // triggers on start + // passed correct object + // does not trigger if started off line + // }); + + // it("onDrag()", () => { + // triggers on move + // passed correct object + // }); + + // it("onDragEnd()", () => { + // triggers on end + // passed correct object + // }); + + // it("destroy() removes all callbacks and properly disconnects from its Interaction", () => { + // }); + }); +}); diff --git a/test/testReference.ts b/test/testReference.ts index 8d6988c2dc..4a04c255cb 100644 --- a/test/testReference.ts +++ b/test/testReference.ts @@ -83,3 +83,4 @@ /// /// /// +/// From 01ab40b9788f5206966ba53a85e27006f5eb6c8c Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 11:48:09 -0700 Subject: [PATCH 009/160] [refactorRectangle] Hierarchy part 1 --- test/plots/rectanglePlotTests.ts | 753 ++++++++++++++++--------------- 1 file changed, 378 insertions(+), 375 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 3288111fb9..042427e5f0 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -2,445 +2,448 @@ describe("Plots", () => { describe("RectanglePlot", () => { - let SVG_WIDTH = 300; - let SVG_HEIGHT = 300; - let DATA = [ - { x: 0, y: 0, x2: 1, y2: 1 }, - { x: 1, y: 1, x2: 2, y2: 2 }, - { x: 2, y: 2, x2: 3, y2: 3 }, - { x: 3, y: 3, x2: 4, y2: 4 }, - { x: 4, y: 4, x2: 5, y2: 5 } - ]; - let VERIFY_CELLS = (cells: d3.Selection) => { - assert.strictEqual(cells[0].length, 5); - cells.each(function(d: any, i: number) { - let cell = d3.select(this); - assert.closeTo(+cell.attr("height"), 50, 0.5, "Cell height is correct"); - assert.closeTo(+cell.attr("width"), 50, 0.5, "Cell width is correct"); - assert.closeTo(+cell.attr("x"), 25 + 50 * i, 0.5, "Cell x coordinate is correct"); - assert.closeTo(+cell.attr("y"), 25 + 50 * (cells[0].length - i - 1), 0.5, "Cell y coordinate is correct"); - }); - }; - - it("renders correctly", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let rectanglePlot = new Plottable.Plots.Rectangle(); - rectanglePlot.addDataset(new Plottable.Dataset(DATA)); - rectanglePlot.x((d) => d.x, xScale) - .y((d) => d.y, yScale) - .x2((d) => d.x2) - .y2((d) => d.y2) - .renderTo(svg); - VERIFY_CELLS(( rectanglePlot)._renderArea.selectAll("rect")); - svg.remove(); - }); - - it("retrieves the correct entity under a point", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dataset = new Plottable.Dataset(DATA); - let plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(dataset).renderTo(svg); - let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) }); - assert.lengthOf(entities, 1, "found only one entity when querying a point inside the third rectangle"); - assert.strictEqual(entities[0].index, 2, "entity retrieved is at index 2"); - svg.remove(); - }); - - it("retrieves correct entities under a point", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dataset = new Plottable.Dataset([ - { x: 1, y: 1, x2: 3, y2: 3 }, - { x: 4, y: 2, x2: 2, y2: 4 } - ]); - let plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(dataset).renderTo(svg); - let entities = plot.entitiesAt({ x: xScale.scale(2), y: xScale.scale(2) }); - assert.lengthOf(entities, 2, "two entities when querying a point in both"); - assert.strictEqual(entities[0].index, 0, "entity retrieved is at index 0"); - assert.strictEqual(entities[1].index, 1, "entity retrieved is at index 1"); - entities = plot.entitiesAt({ x: xScale.scale(4), y: yScale.scale(4) }); - assert.lengthOf(entities, 1, "found only one entity when querying a point inside the second rectangle"); - assert.strictEqual(entities[0].index, 1, "entity retrieved is at index 1"); - entities = plot.entitiesAt({ x: xScale.scale(1), y: yScale.scale(1) }); - assert.lengthOf(entities, 1, "found only one entity when querying a point inside the first rectangle"); - assert.strictEqual(entities[0].index, 0, "entity retrieved is at index 0"); - svg.remove(); - }); - it("retrieves the entities that intersect with the bounding box", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dataset = new Plottable.Dataset(DATA); - let plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(dataset).renderTo(svg); - - let entities = plot.entitiesIn({ - topLeft: { x: xScale.scale(1.5), y: yScale.scale(2.5) }, - bottomRight: { x: xScale.scale(2.5), y: yScale.scale(1.5) } }); - assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); - assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); - assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); - svg.remove(); - }); + describe("RectanglePlot - basics", () => { - it("retrieves the entities that intersect with the given ranges", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dataset = new Plottable.Dataset(DATA); - let plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(dataset).renderTo(svg); - - let entities = plot.entitiesIn( - {min: xScale.scale(1.5), max: xScale.scale(2.5)}, - {min: yScale.scale(2.5), max: yScale.scale(1.5)}); - assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); - assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); - assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); - svg.remove(); - }); - - it("autorangeMode(\"x\")", () => { - let staggeredData = [ - { y: "A", x: 0, x2: 1 }, - { y: "B", x: 1, x2: 2 } + let SVG_WIDTH = 300; + let SVG_HEIGHT = 300; + let DATA = [ + { x: 0, y: 0, x2: 1, y2: 1 }, + { x: 1, y: 1, x2: 2, y2: 2 }, + { x: 2, y: 2, x2: 3, y2: 3 }, + { x: 3, y: 3, x2: 4, y2: 4 }, + { x: 4, y: 4, x2: 5, y2: 5 } ]; + let VERIFY_CELLS = (cells: d3.Selection) => { + assert.strictEqual(cells[0].length, 5); + cells.each(function(d: any, i: number) { + let cell = d3.select(this); + assert.closeTo(+cell.attr("height"), 50, 0.5, "Cell height is correct"); + assert.closeTo(+cell.attr("width"), 50, 0.5, "Cell width is correct"); + assert.closeTo(+cell.attr("x"), 25 + 50 * i, 0.5, "Cell x coordinate is correct"); + assert.closeTo(+cell.attr("y"), 25 + 50 * (cells[0].length - i - 1), 0.5, "Cell y coordinate is correct"); + }); + }; + + it("renders correctly", () => { + let xScale = new Plottable.Scales.Linear(); + let yScale = new Plottable.Scales.Linear(); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let rectanglePlot = new Plottable.Plots.Rectangle(); + rectanglePlot.addDataset(new Plottable.Dataset(DATA)); + rectanglePlot.x((d) => d.x, xScale) + .y((d) => d.y, yScale) + .x2((d) => d.x2) + .y2((d) => d.y2) + .renderTo(svg); + VERIFY_CELLS(( rectanglePlot)._renderArea.selectAll("rect")); + svg.remove(); + }); - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Category(); - xScale.padProportion(0); + it("retrieves the correct entity under a point", () => { + let xScale = new Plottable.Scales.Linear(); + let yScale = new Plottable.Scales.Linear(); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dataset = new Plottable.Dataset(DATA); + let plot = new Plottable.Plots.Rectangle() + .x((d) => d.x, xScale).x2((d) => d.x2) + .y((d) => d.y, yScale).y2((d) => d.y2); + plot.addDataset(dataset).renderTo(svg); + let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) }); + assert.lengthOf(entities, 1, "found only one entity when querying a point inside the third rectangle"); + assert.strictEqual(entities[0].index, 2, "entity retrieved is at index 2"); + svg.remove(); + }); - let plot = new Plottable.Plots.Rectangle(); - plot.x(function(d) { return d.x; }, xScale); - plot.x2(function(d) { return d.x2; }); - plot.y(function(d) { return d.y; }, yScale); - plot.addDataset(new Plottable.Dataset(staggeredData)); - plot.autorangeMode("x"); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - plot.renderTo(svg); + it("retrieves correct entities under a point", () => { + let xScale = new Plottable.Scales.Linear(); + let yScale = new Plottable.Scales.Linear(); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dataset = new Plottable.Dataset([ + { x: 1, y: 1, x2: 3, y2: 3 }, + { x: 4, y: 2, x2: 2, y2: 4 } + ]); + let plot = new Plottable.Plots.Rectangle() + .x((d) => d.x, xScale).x2((d) => d.x2) + .y((d) => d.y, yScale).y2((d) => d.y2); + plot.addDataset(dataset).renderTo(svg); + let entities = plot.entitiesAt({ x: xScale.scale(2), y: xScale.scale(2) }); + assert.lengthOf(entities, 2, "two entities when querying a point in both"); + assert.strictEqual(entities[0].index, 0, "entity retrieved is at index 0"); + assert.strictEqual(entities[1].index, 1, "entity retrieved is at index 1"); + entities = plot.entitiesAt({ x: xScale.scale(4), y: yScale.scale(4) }); + assert.lengthOf(entities, 1, "found only one entity when querying a point inside the second rectangle"); + assert.strictEqual(entities[0].index, 1, "entity retrieved is at index 1"); + entities = plot.entitiesAt({ x: xScale.scale(1), y: yScale.scale(1) }); + assert.lengthOf(entities, 1, "found only one entity when querying a point inside the first rectangle"); + assert.strictEqual(entities[0].index, 0, "entity retrieved is at index 0"); + svg.remove(); + }); - assert.deepEqual(xScale.domain(), [0, 2], "y domain includes both visible segments"); + it("retrieves the entities that intersect with the bounding box", () => { + let xScale = new Plottable.Scales.Linear(); + let yScale = new Plottable.Scales.Linear(); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dataset = new Plottable.Dataset(DATA); + let plot = new Plottable.Plots.Rectangle() + .x((d) => d.x, xScale).x2((d) => d.x2) + .y((d) => d.y, yScale).y2((d) => d.y2); + plot.addDataset(dataset).renderTo(svg); + + let entities = plot.entitiesIn({ + topLeft: { x: xScale.scale(1.5), y: yScale.scale(2.5) }, + bottomRight: { x: xScale.scale(2.5), y: yScale.scale(1.5) } }); + assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); + assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); + assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); + svg.remove(); + }); - yScale.domain(["A"]); - assert.deepEqual(xScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); + it("retrieves the entities that intersect with the given ranges", () => { + let xScale = new Plottable.Scales.Linear(); + let yScale = new Plottable.Scales.Linear(); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dataset = new Plottable.Dataset(DATA); + let plot = new Plottable.Plots.Rectangle() + .x((d) => d.x, xScale).x2((d) => d.x2) + .y((d) => d.y, yScale).y2((d) => d.y2); + plot.addDataset(dataset).renderTo(svg); + + let entities = plot.entitiesIn( + {min: xScale.scale(1.5), max: xScale.scale(2.5)}, + {min: yScale.scale(2.5), max: yScale.scale(1.5)}); + assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); + assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); + assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); + svg.remove(); + }); - yScale.domain(["B"]); - assert.deepEqual(xScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); + it("autorangeMode(\"x\")", () => { + let staggeredData = [ + { y: "A", x: 0, x2: 1 }, + { y: "B", x: 1, x2: 2 } + ]; - svg.remove(); - }); + let xScale = new Plottable.Scales.Linear(); + let yScale = new Plottable.Scales.Category(); + xScale.padProportion(0); + + let plot = new Plottable.Plots.Rectangle(); + plot.x(function(d) { return d.x; }, xScale); + plot.x2(function(d) { return d.x2; }); + plot.y(function(d) { return d.y; }, yScale); + plot.addDataset(new Plottable.Dataset(staggeredData)); + plot.autorangeMode("x"); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + plot.renderTo(svg); - it("autorangeMode(\"y\")", () => { - let staggeredData = [ - { x: "A", y: 0, y2: 1 }, - { x: "B", y: 1, y2: 2 } - ]; + assert.deepEqual(xScale.domain(), [0, 2], "y domain includes both visible segments"); - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Linear(); - yScale.padProportion(0); + yScale.domain(["A"]); + assert.deepEqual(xScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); - let plot = new Plottable.Plots.Rectangle(); - plot.x(function(d) { return d.x; }, xScale); - plot.y(function(d) { return d.y; }, yScale); - plot.y2(function(d) { return d.y2; }); - plot.addDataset(new Plottable.Dataset(staggeredData)); - plot.autorangeMode("y"); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - plot.renderTo(svg); + yScale.domain(["B"]); + assert.deepEqual(xScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); - assert.deepEqual(yScale.domain(), [0, 2], "y domain includes both visible segments"); + svg.remove(); + }); - xScale.domain(["A"]); - assert.deepEqual(yScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); + it("autorangeMode(\"y\")", () => { + let staggeredData = [ + { x: "A", y: 0, y2: 1 }, + { x: "B", y: 1, y2: 2 } + ]; - xScale.domain(["B"]); - assert.deepEqual(yScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Linear(); + yScale.padProportion(0); + + let plot = new Plottable.Plots.Rectangle(); + plot.x(function(d) { return d.x; }, xScale); + plot.y(function(d) { return d.y; }, yScale); + plot.y2(function(d) { return d.y2; }); + plot.addDataset(new Plottable.Dataset(staggeredData)); + plot.autorangeMode("y"); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + plot.renderTo(svg); - svg.remove(); - }); + assert.deepEqual(yScale.domain(), [0, 2], "y domain includes both visible segments"); - }); + xScale.domain(["A"]); + assert.deepEqual(yScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); - describe("fail safe tests", () => { - it("illegal rectangles don't get displayed", () => { - let svg = TestMethods.generateSVG(); - - let data1 = [ - { x: "A", y: 1, y2: 2, v: 1 }, - { x: "B", y: 2, y2: 3, v: 2 }, - { x: "C", y: 3, y2: NaN, v: 3 }, - { x: "D", y: 4, y2: 5, v: 4 }, - { x: "E", y: 5, y2: 6, v: 5 }, - { x: "F", y: 6, y2: 7, v: 6 } - ]; + xScale.domain(["B"]); + assert.deepEqual(yScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Linear(); - - let plot = new Plottable.Plots.Rectangle(); - plot - .x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .y2((d: any) => d.y2); - plot.addDataset(new Plottable.Dataset(data1)); - - plot.renderTo(svg); - - let rectanglesSelection = plot.selections(); - - assert.strictEqual(rectanglesSelection.size(), 5, - "only 5 rectangles should be displayed"); - - rectanglesSelection.each(function(d: any, i: number) { - let sel = d3.select(this); - assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr("x")), - "x attribute should be valid for rectangle # " + i + ". Currently " + sel.attr("x")); - assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr("y")), - "y attribute should be valid for rectangle # " + i + ". Currently " + sel.attr("y")); - assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr("height")), - "height attribute should be valid for rectangle # " + i + ". Currently " + sel.attr("height")); - assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr("width")), - "width attribute should be valid for rectangle # " + i + ". Currently " + sel.attr("width")); + svg.remove(); }); - - svg.remove(); }); - }); - describe("RectanglePlot - Grids", () => { - let SVG_WIDTH = 400; - let SVG_HEIGHT = 200; - let DATA = [ - {x: "A", y: "U", magnitude: 0}, - {x: "B", y: "U", magnitude: 2}, - {x: "A", y: "V", magnitude: 16}, - {x: "B", y: "V", magnitude: 8}, - ]; - - let VERIFY_CELLS = (cells: any[]) => { - assert.strictEqual(cells.length, 4); - - let cellAU = d3.select(cells[0]); - let cellBU = d3.select(cells[1]); - let cellAV = d3.select(cells[2]); - let cellBV = d3.select(cells[3]); - - assert.strictEqual(cellAU.attr("height"), "100", "cell 'AU' height is correct"); - assert.strictEqual(cellAU.attr("width"), "200", "cell 'AU' width is correct"); - assert.strictEqual(cellAU.attr("x"), "0", "cell 'AU' x coord is correct"); - assert.strictEqual(cellAU.attr("y"), "0", "cell 'AU' y coord is correct"); - assert.strictEqual(cellAU.attr("fill"), "#000000", "cell 'AU' color is correct"); - - assert.strictEqual(cellBU.attr("height"), "100", "cell 'BU' height is correct"); - assert.strictEqual(cellBU.attr("width"), "200", "cell 'BU' width is correct"); - assert.strictEqual(cellBU.attr("x"), "200", "cell 'BU' x coord is correct"); - assert.strictEqual(cellBU.attr("y"), "0", "cell 'BU' y coord is correct"); - assert.strictEqual(cellBU.attr("fill"), "#212121", "cell 'BU' color is correct"); - - assert.strictEqual(cellAV.attr("height"), "100", "cell 'AV' height is correct"); - assert.strictEqual(cellAV.attr("width"), "200", "cell 'AV' width is correct"); - assert.strictEqual(cellAV.attr("x"), "0", "cell 'AV' x coord is correct"); - assert.strictEqual(cellAV.attr("y"), "100", "cell 'AV' y coord is correct"); - assert.strictEqual(cellAV.attr("fill"), "#ffffff", "cell 'AV' color is correct"); - - assert.strictEqual(cellBV.attr("height"), "100", "cell 'BV' height is correct"); - assert.strictEqual(cellBV.attr("width"), "200", "cell 'BV' width is correct"); - assert.strictEqual(cellBV.attr("x"), "200", "cell 'BV' x coord is correct"); - assert.strictEqual(cellBV.attr("y"), "100", "cell 'BV' y coord is correct"); - assert.strictEqual(cellBV.attr("fill"), "#777777", "cell 'BV' color is correct"); - }; - - it("renders correctly", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); - gridPlot.addDataset(new Plottable.Dataset(DATA)) - .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); - VERIFY_CELLS(( gridPlot)._renderArea.selectAll("rect")[0]); - svg.remove(); - }); + describe("RectanglePlot - fail safe tests", () => { + it("illegal rectangles don't get displayed", () => { + let svg = TestMethods.generateSVG(); - it("renders correctly when data is set after construction", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dataset = new Plottable.Dataset(); - let gridPlot = new Plottable.Plots.Rectangle(); - gridPlot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .renderTo(svg); - dataset.data(DATA); - VERIFY_CELLS(( gridPlot)._renderArea.selectAll("rect")[0]); - svg.remove(); - }); + let data1 = [ + { x: "A", y: 1, y2: 2, v: 1 }, + { x: "B", y: 2, y2: 3, v: 2 }, + { x: "C", y: 3, y2: NaN, v: 3 }, + { x: "D", y: 4, y2: 5, v: 4 }, + { x: "E", y: 5, y2: 6, v: 5 }, + { x: "F", y: 6, y2: 7, v: 6 } + ]; - it("renders correctly when there isn't data for every spot", () => { - let CELL_HEIGHT = 50; - let CELL_WIDTH = 100; - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dataset = new Plottable.Dataset(); - let gridPlot = new Plottable.Plots.Rectangle(); - gridPlot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .renderTo(svg); - let data = [ - {x: "A", y: "W", magnitude: 0}, - {x: "B", y: "X", magnitude: 8}, - {x: "C", y: "Y", magnitude: 16}, - {x: "D", y: "Z", magnitude: 24} - ]; - dataset.data(data); - let cells = ( gridPlot)._renderArea.selectAll("rect")[0]; - assert.strictEqual(cells.length, data.length); - for (let i = 0; i < cells.length; i++) { - let cell = d3.select(cells[i]); - assert.strictEqual(cell.attr("x"), String(i * CELL_WIDTH), "Cell x coord is correct"); - assert.strictEqual(cell.attr("y"), String(i * CELL_HEIGHT), "Cell y coord is correct"); - assert.strictEqual(cell.attr("width"), String(CELL_WIDTH), "Cell width is correct"); - assert.strictEqual(cell.attr("height"), String(CELL_HEIGHT), "Cell height is correct"); - } - svg.remove(); - }); + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Linear(); + + let plot = new Plottable.Plots.Rectangle(); + plot + .x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale) + .y2((d: any) => d.y2); + plot.addDataset(new Plottable.Dataset(data1)); + + plot.renderTo(svg); + + let rectanglesSelection = plot.selections(); + + assert.strictEqual(rectanglesSelection.size(), 5, + "only 5 rectangles should be displayed"); + + rectanglesSelection.each(function(d: any, i: number) { + let sel = d3.select(this); + assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr("x")), + "x attribute should be valid for rectangle # " + i + ". Currently " + sel.attr("x")); + assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr("y")), + "y attribute should be valid for rectangle # " + i + ". Currently " + sel.attr("y")); + assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr("height")), + "height attribute should be valid for rectangle # " + i + ". Currently " + sel.attr("height")); + assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr("width")), + "width attribute should be valid for rectangle # " + i + ". Currently " + sel.attr("width")); + }); - it("can invert y axis correctly", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); - gridPlot.addDataset(new Plottable.Dataset(DATA)) - .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .renderTo(svg); - - yScale.domain(["U", "V"]); - - let cells = ( gridPlot)._renderArea.selectAll("rect")[0]; - let cellAU = d3.select(cells[0]); - let cellAV = d3.select(cells[2]); - cellAU.attr("fill", "#000000"); - cellAU.attr("x", "0"); - cellAU.attr("y", "100"); - - cellAV.attr("fill", "#ffffff"); - cellAV.attr("x", "0"); - cellAV.attr("y", "0"); - - yScale.domain(["V", "U"]); - cells = ( gridPlot)._renderArea.selectAll("rect")[0]; - cellAU = d3.select(cells[0]); - cellAV = d3.select(cells[2]); - cellAU.attr("fill", "#000000"); - cellAU.attr("x", "0"); - cellAU.attr("y", "0"); - - cellAV.attr("fill", "#ffffff"); - cellAV.attr("x", "0"); - cellAV.attr("y", "100"); - - svg.remove(); + svg.remove(); + }); }); - describe("selections()", () => { + describe("RectanglePlot - Grids", () => { + let SVG_WIDTH = 400; + let SVG_HEIGHT = 200; + let DATA = [ + {x: "A", y: "U", magnitude: 0}, + {x: "B", y: "U", magnitude: 2}, + {x: "A", y: "V", magnitude: 16}, + {x: "B", y: "V", magnitude: 8}, + ]; - it("retrieves all selections with no args", () => { + let VERIFY_CELLS = (cells: any[]) => { + assert.strictEqual(cells.length, 4); + + let cellAU = d3.select(cells[0]); + let cellBU = d3.select(cells[1]); + let cellAV = d3.select(cells[2]); + let cellBV = d3.select(cells[3]); + + assert.strictEqual(cellAU.attr("height"), "100", "cell 'AU' height is correct"); + assert.strictEqual(cellAU.attr("width"), "200", "cell 'AU' width is correct"); + assert.strictEqual(cellAU.attr("x"), "0", "cell 'AU' x coord is correct"); + assert.strictEqual(cellAU.attr("y"), "0", "cell 'AU' y coord is correct"); + assert.strictEqual(cellAU.attr("fill"), "#000000", "cell 'AU' color is correct"); + + assert.strictEqual(cellBU.attr("height"), "100", "cell 'BU' height is correct"); + assert.strictEqual(cellBU.attr("width"), "200", "cell 'BU' width is correct"); + assert.strictEqual(cellBU.attr("x"), "200", "cell 'BU' x coord is correct"); + assert.strictEqual(cellBU.attr("y"), "0", "cell 'BU' y coord is correct"); + assert.strictEqual(cellBU.attr("fill"), "#212121", "cell 'BU' color is correct"); + + assert.strictEqual(cellAV.attr("height"), "100", "cell 'AV' height is correct"); + assert.strictEqual(cellAV.attr("width"), "200", "cell 'AV' width is correct"); + assert.strictEqual(cellAV.attr("x"), "0", "cell 'AV' x coord is correct"); + assert.strictEqual(cellAV.attr("y"), "100", "cell 'AV' y coord is correct"); + assert.strictEqual(cellAV.attr("fill"), "#ffffff", "cell 'AV' color is correct"); + + assert.strictEqual(cellBV.attr("height"), "100", "cell 'BV' height is correct"); + assert.strictEqual(cellBV.attr("width"), "200", "cell 'BV' width is correct"); + assert.strictEqual(cellBV.attr("x"), "200", "cell 'BV' x coord is correct"); + assert.strictEqual(cellBV.attr("y"), "100", "cell 'BV' y coord is correct"); + assert.strictEqual(cellBV.attr("fill"), "#777777", "cell 'BV' color is correct"); + }; + + it("renders correctly", () => { let xScale = new Plottable.Scales.Category(); let yScale = new Plottable.Scales.Category(); let colorScale = new Plottable.Scales.InterpolatedColor(); colorScale.range(["black", "white"]); let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let gridPlot = new Plottable.Plots.Rectangle(); - let dataset = new Plottable.Dataset(DATA); - gridPlot.addDataset(dataset) + gridPlot.addDataset(new Plottable.Dataset(DATA)) .attr("fill", (d) => d.magnitude, colorScale); gridPlot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale); gridPlot.renderTo(svg); - - let allCells = gridPlot.selections(); - assert.strictEqual(allCells.size(), 4, "all cells retrieved"); - + VERIFY_CELLS(( gridPlot)._renderArea.selectAll("rect")[0]); svg.remove(); }); - it("retrieves correct selections", () => { + it("renders correctly when data is set after construction", () => { let xScale = new Plottable.Scales.Category(); let yScale = new Plottable.Scales.Category(); let colorScale = new Plottable.Scales.InterpolatedColor(); colorScale.range(["black", "white"]); let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dataset = new Plottable.Dataset(); let gridPlot = new Plottable.Plots.Rectangle(); - let dataset = new Plottable.Dataset(DATA); gridPlot.addDataset(dataset) .attr("fill", (d) => d.magnitude, colorScale); gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); - - let allCells = gridPlot.selections([dataset]); - assert.strictEqual(allCells.size(), 4, "all cells retrieved"); - let selectionData = allCells.data(); - assert.includeMembers(selectionData, DATA, "data in selection data"); - + .y((d: any) => d.y, yScale) + .renderTo(svg); + dataset.data(DATA); + VERIFY_CELLS(( gridPlot)._renderArea.selectAll("rect")[0]); svg.remove(); }); - it("skips invalid Datasets", () => { + it("renders correctly when there isn't data for every spot", () => { + let CELL_HEIGHT = 50; + let CELL_WIDTH = 100; let xScale = new Plottable.Scales.Category(); let yScale = new Plottable.Scales.Category(); let colorScale = new Plottable.Scales.InterpolatedColor(); colorScale.range(["black", "white"]); let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dataset = new Plottable.Dataset(); let gridPlot = new Plottable.Plots.Rectangle(); - let dataset = new Plottable.Dataset(DATA); gridPlot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); + .attr("fill", (d) => d.magnitude, colorScale); + gridPlot.x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale) + .renderTo(svg); + let data = [ + {x: "A", y: "W", magnitude: 0}, + {x: "B", y: "X", magnitude: 8}, + {x: "C", y: "Y", magnitude: 16}, + {x: "D", y: "Z", magnitude: 24} + ]; + dataset.data(data); + let cells = ( gridPlot)._renderArea.selectAll("rect")[0]; + assert.strictEqual(cells.length, data.length); + for (let i = 0; i < cells.length; i++) { + let cell = d3.select(cells[i]); + assert.strictEqual(cell.attr("x"), String(i * CELL_WIDTH), "Cell x coord is correct"); + assert.strictEqual(cell.attr("y"), String(i * CELL_HEIGHT), "Cell y coord is correct"); + assert.strictEqual(cell.attr("width"), String(CELL_WIDTH), "Cell width is correct"); + assert.strictEqual(cell.attr("height"), String(CELL_HEIGHT), "Cell height is correct"); + } + svg.remove(); + }); - let dummyDataset = new Plottable.Dataset([]); - let allCells = gridPlot.selections([dataset, dummyDataset]); - assert.strictEqual(allCells.size(), 4, "all cells retrieved"); - let selectionData = allCells.data(); - assert.includeMembers(selectionData, DATA, "data in selection data"); + it("can invert y axis correctly", () => { + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Category(); + let colorScale = new Plottable.Scales.InterpolatedColor(); + colorScale.range(["black", "white"]); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let gridPlot = new Plottable.Plots.Rectangle(); + gridPlot.addDataset(new Plottable.Dataset(DATA)) + .attr("fill", (d) => d.magnitude, colorScale); + gridPlot.x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale) + .renderTo(svg); + + yScale.domain(["U", "V"]); + + let cells = ( gridPlot)._renderArea.selectAll("rect")[0]; + let cellAU = d3.select(cells[0]); + let cellAV = d3.select(cells[2]); + cellAU.attr("fill", "#000000"); + cellAU.attr("x", "0"); + cellAU.attr("y", "100"); + + cellAV.attr("fill", "#ffffff"); + cellAV.attr("x", "0"); + cellAV.attr("y", "0"); + + yScale.domain(["V", "U"]); + cells = ( gridPlot)._renderArea.selectAll("rect")[0]; + cellAU = d3.select(cells[0]); + cellAV = d3.select(cells[2]); + cellAU.attr("fill", "#000000"); + cellAU.attr("x", "0"); + cellAU.attr("y", "0"); + + cellAV.attr("fill", "#ffffff"); + cellAV.attr("x", "0"); + cellAV.attr("y", "100"); svg.remove(); }); + + describe("selections()", () => { + + it("retrieves all selections with no args", () => { + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Category(); + let colorScale = new Plottable.Scales.InterpolatedColor(); + colorScale.range(["black", "white"]); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let gridPlot = new Plottable.Plots.Rectangle(); + let dataset = new Plottable.Dataset(DATA); + gridPlot.addDataset(dataset) + .attr("fill", (d) => d.magnitude, colorScale); + gridPlot.x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale); + gridPlot.renderTo(svg); + + let allCells = gridPlot.selections(); + assert.strictEqual(allCells.size(), 4, "all cells retrieved"); + + svg.remove(); + }); + + it("retrieves correct selections", () => { + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Category(); + let colorScale = new Plottable.Scales.InterpolatedColor(); + colorScale.range(["black", "white"]); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let gridPlot = new Plottable.Plots.Rectangle(); + let dataset = new Plottable.Dataset(DATA); + gridPlot.addDataset(dataset) + .attr("fill", (d) => d.magnitude, colorScale); + gridPlot.x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale); + gridPlot.renderTo(svg); + + let allCells = gridPlot.selections([dataset]); + assert.strictEqual(allCells.size(), 4, "all cells retrieved"); + let selectionData = allCells.data(); + assert.includeMembers(selectionData, DATA, "data in selection data"); + + svg.remove(); + }); + + it("skips invalid Datasets", () => { + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Category(); + let colorScale = new Plottable.Scales.InterpolatedColor(); + colorScale.range(["black", "white"]); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let gridPlot = new Plottable.Plots.Rectangle(); + let dataset = new Plottable.Dataset(DATA); + gridPlot.addDataset(dataset) + .attr("fill", (d) => d.magnitude, colorScale); + gridPlot.x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale); + gridPlot.renderTo(svg); + + let dummyDataset = new Plottable.Dataset([]); + let allCells = gridPlot.selections([dataset, dummyDataset]); + assert.strictEqual(allCells.size(), 4, "all cells retrieved"); + let selectionData = allCells.data(); + assert.includeMembers(selectionData, DATA, "data in selection data"); + + svg.remove(); + }); + }); }); }); }); From 040263da1ff8ebe922c057608c44357f03bcaa0b Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 11:52:31 -0700 Subject: [PATCH 010/160] [refactorRectangle] Hierarchy is alright now --- test/plots/rectanglePlotTests.ts | 138 ++++++++++++++++--------------- 1 file changed, 72 insertions(+), 66 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 042427e5f0..ea58989c6f 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -2,9 +2,7 @@ describe("Plots", () => { describe("RectanglePlot", () => { - describe("RectanglePlot - basics", () => { - let SVG_WIDTH = 300; let SVG_HEIGHT = 300; let DATA = [ @@ -376,73 +374,81 @@ describe("Plots", () => { svg.remove(); }); + }); - describe("selections()", () => { - - it("retrieves all selections with no args", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); - let dataset = new Plottable.Dataset(DATA); - gridPlot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); - - let allCells = gridPlot.selections(); - assert.strictEqual(allCells.size(), 4, "all cells retrieved"); - - svg.remove(); - }); + describe("Rectangle Plot - selections()", () => { + let SVG_WIDTH = 400; + let SVG_HEIGHT = 200; + let DATA = [ + {x: "A", y: "U", magnitude: 0}, + {x: "B", y: "U", magnitude: 2}, + {x: "A", y: "V", magnitude: 16}, + {x: "B", y: "V", magnitude: 8}, + ]; - it("retrieves correct selections", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); - let dataset = new Plottable.Dataset(DATA); - gridPlot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); - - let allCells = gridPlot.selections([dataset]); - assert.strictEqual(allCells.size(), 4, "all cells retrieved"); - let selectionData = allCells.data(); - assert.includeMembers(selectionData, DATA, "data in selection data"); - - svg.remove(); - }); + it("retrieves all selections with no args", () => { + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Category(); + let colorScale = new Plottable.Scales.InterpolatedColor(); + colorScale.range(["black", "white"]); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let gridPlot = new Plottable.Plots.Rectangle(); + let dataset = new Plottable.Dataset(DATA); + gridPlot.addDataset(dataset) + .attr("fill", (d) => d.magnitude, colorScale); + gridPlot.x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale); + gridPlot.renderTo(svg); - it("skips invalid Datasets", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); - let dataset = new Plottable.Dataset(DATA); - gridPlot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); - - let dummyDataset = new Plottable.Dataset([]); - let allCells = gridPlot.selections([dataset, dummyDataset]); - assert.strictEqual(allCells.size(), 4, "all cells retrieved"); - let selectionData = allCells.data(); - assert.includeMembers(selectionData, DATA, "data in selection data"); - - svg.remove(); - }); + let allCells = gridPlot.selections(); + assert.strictEqual(allCells.size(), 4, "all cells retrieved"); + + svg.remove(); + }); + + it("retrieves correct selections", () => { + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Category(); + let colorScale = new Plottable.Scales.InterpolatedColor(); + colorScale.range(["black", "white"]); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let gridPlot = new Plottable.Plots.Rectangle(); + let dataset = new Plottable.Dataset(DATA); + gridPlot.addDataset(dataset) + .attr("fill", (d) => d.magnitude, colorScale); + gridPlot.x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale); + gridPlot.renderTo(svg); + + let allCells = gridPlot.selections([dataset]); + assert.strictEqual(allCells.size(), 4, "all cells retrieved"); + let selectionData = allCells.data(); + assert.includeMembers(selectionData, DATA, "data in selection data"); + + svg.remove(); + }); + + it("skips invalid Datasets", () => { + let xScale = new Plottable.Scales.Category(); + let yScale = new Plottable.Scales.Category(); + let colorScale = new Plottable.Scales.InterpolatedColor(); + colorScale.range(["black", "white"]); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let gridPlot = new Plottable.Plots.Rectangle(); + let dataset = new Plottable.Dataset(DATA); + gridPlot.addDataset(dataset) + .attr("fill", (d) => d.magnitude, colorScale); + gridPlot.x((d: any) => d.x, xScale) + .y((d: any) => d.y, yScale); + gridPlot.renderTo(svg); + + let dummyDataset = new Plottable.Dataset([]); + let allCells = gridPlot.selections([dataset, dummyDataset]); + assert.strictEqual(allCells.size(), 4, "all cells retrieved"); + let selectionData = allCells.data(); + assert.includeMembers(selectionData, DATA, "data in selection data"); + + svg.remove(); }); }); }); From 5daf315eaa36a7b3ed54b855d3291284347c8288 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 11:59:07 -0700 Subject: [PATCH 011/160] [refactorRectangle] extracted autorangeMode into a separate describe --- test/plots/rectanglePlotTests.ts | 40 +++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index ea58989c6f..26a12033a8 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -14,7 +14,7 @@ describe("Plots", () => { ]; let VERIFY_CELLS = (cells: d3.Selection) => { assert.strictEqual(cells[0].length, 5); - cells.each(function(d: any, i: number) { + cells.each(function(d, i) { let cell = d3.select(this); assert.closeTo(+cell.attr("height"), 50, 0.5, "Cell height is correct"); assert.closeTo(+cell.attr("width"), 50, 0.5, "Cell width is correct"); @@ -23,10 +23,19 @@ describe("Plots", () => { }); }; + let svg: d3.Selection; + + beforeEach(() => { + svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + }); + + afterEach(() => { + svg.remove(); + }); + it("renders correctly", () => { let xScale = new Plottable.Scales.Linear(); let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let rectanglePlot = new Plottable.Plots.Rectangle(); rectanglePlot.addDataset(new Plottable.Dataset(DATA)); rectanglePlot.x((d) => d.x, xScale) @@ -35,13 +44,11 @@ describe("Plots", () => { .y2((d) => d.y2) .renderTo(svg); VERIFY_CELLS(( rectanglePlot)._renderArea.selectAll("rect")); - svg.remove(); }); it("retrieves the correct entity under a point", () => { let xScale = new Plottable.Scales.Linear(); let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dataset = new Plottable.Dataset(DATA); let plot = new Plottable.Plots.Rectangle() .x((d) => d.x, xScale).x2((d) => d.x2) @@ -50,13 +57,11 @@ describe("Plots", () => { let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) }); assert.lengthOf(entities, 1, "found only one entity when querying a point inside the third rectangle"); assert.strictEqual(entities[0].index, 2, "entity retrieved is at index 2"); - svg.remove(); }); it("retrieves correct entities under a point", () => { let xScale = new Plottable.Scales.Linear(); let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dataset = new Plottable.Dataset([ { x: 1, y: 1, x2: 3, y2: 3 }, { x: 4, y: 2, x2: 2, y2: 4 } @@ -75,13 +80,11 @@ describe("Plots", () => { entities = plot.entitiesAt({ x: xScale.scale(1), y: yScale.scale(1) }); assert.lengthOf(entities, 1, "found only one entity when querying a point inside the first rectangle"); assert.strictEqual(entities[0].index, 0, "entity retrieved is at index 0"); - svg.remove(); }); it("retrieves the entities that intersect with the bounding box", () => { let xScale = new Plottable.Scales.Linear(); let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dataset = new Plottable.Dataset(DATA); let plot = new Plottable.Plots.Rectangle() .x((d) => d.x, xScale).x2((d) => d.x2) @@ -94,13 +97,11 @@ describe("Plots", () => { assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); - svg.remove(); }); it("retrieves the entities that intersect with the given ranges", () => { let xScale = new Plottable.Scales.Linear(); let yScale = new Plottable.Scales.Linear(); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dataset = new Plottable.Dataset(DATA); let plot = new Plottable.Plots.Rectangle() .x((d) => d.x, xScale).x2((d) => d.x2) @@ -113,6 +114,21 @@ describe("Plots", () => { assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); + }); + + }); + + describe("RectanglePlot - autorangeMode()", () => { + let SVG_WIDTH = 300; + let SVG_HEIGHT = 300; + + let svg: d3.Selection; + + beforeEach(() => { + svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + }); + + afterEach(() => { svg.remove(); }); @@ -132,7 +148,6 @@ describe("Plots", () => { plot.y(function(d) { return d.y; }, yScale); plot.addDataset(new Plottable.Dataset(staggeredData)); plot.autorangeMode("x"); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); plot.renderTo(svg); assert.deepEqual(xScale.domain(), [0, 2], "y domain includes both visible segments"); @@ -143,7 +158,6 @@ describe("Plots", () => { yScale.domain(["B"]); assert.deepEqual(xScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); - svg.remove(); }); it("autorangeMode(\"y\")", () => { @@ -162,7 +176,6 @@ describe("Plots", () => { plot.y2(function(d) { return d.y2; }); plot.addDataset(new Plottable.Dataset(staggeredData)); plot.autorangeMode("y"); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); plot.renderTo(svg); assert.deepEqual(yScale.domain(), [0, 2], "y domain includes both visible segments"); @@ -173,7 +186,6 @@ describe("Plots", () => { xScale.domain(["B"]); assert.deepEqual(yScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); - svg.remove(); }); }); From e0874905ea227dcc75510109e7fdb245a5f9b1bb Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 12:05:38 -0700 Subject: [PATCH 012/160] [refactorRectangle] Factored out common code in the basics of the rectangle plot --- test/plots/rectanglePlotTests.ts | 58 +++++++++++--------------------- 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 26a12033a8..67b7690b0b 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -24,9 +24,17 @@ describe("Plots", () => { }; let svg: d3.Selection; + let xScale: Plottable.Scales.Linear; + let yScale: Plottable.Scales.Linear; + let plot: Plottable.Plots.Rectangle; beforeEach(() => { svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + xScale = new Plottable.Scales.Linear(); + yScale = new Plottable.Scales.Linear(); + plot = new Plottable.Plots.Rectangle() + .x((d) => d.x, xScale).x2((d) => d.x2) + .y((d) => d.y, yScale).y2((d) => d.y2); }); afterEach(() => { @@ -34,42 +42,27 @@ describe("Plots", () => { }); it("renders correctly", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let rectanglePlot = new Plottable.Plots.Rectangle(); - rectanglePlot.addDataset(new Plottable.Dataset(DATA)); - rectanglePlot.x((d) => d.x, xScale) - .y((d) => d.y, yScale) - .x2((d) => d.x2) - .y2((d) => d.y2) - .renderTo(svg); - VERIFY_CELLS(( rectanglePlot)._renderArea.selectAll("rect")); + plot.addDataset(new Plottable.Dataset(DATA)); + plot.renderTo(svg); + VERIFY_CELLS(( plot)._renderArea.selectAll("rect")); }); it("retrieves the correct entity under a point", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let dataset = new Plottable.Dataset(DATA); - let plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(dataset).renderTo(svg); + plot.addDataset(new Plottable.Dataset(DATA)) + plot.renderTo(svg); let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) }); assert.lengthOf(entities, 1, "found only one entity when querying a point inside the third rectangle"); assert.strictEqual(entities[0].index, 2, "entity retrieved is at index 2"); }); it("retrieves correct entities under a point", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); let dataset = new Plottable.Dataset([ { x: 1, y: 1, x2: 3, y2: 3 }, { x: 4, y: 2, x2: 2, y2: 4 } ]); - let plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(dataset).renderTo(svg); + plot.addDataset(dataset) + plot.renderTo(svg); + let entities = plot.entitiesAt({ x: xScale.scale(2), y: xScale.scale(2) }); assert.lengthOf(entities, 2, "two entities when querying a point in both"); assert.strictEqual(entities[0].index, 0, "entity retrieved is at index 0"); @@ -83,13 +76,8 @@ describe("Plots", () => { }); it("retrieves the entities that intersect with the bounding box", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let dataset = new Plottable.Dataset(DATA); - let plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(dataset).renderTo(svg); + plot.addDataset(new Plottable.Dataset(DATA)) + plot.renderTo(svg); let entities = plot.entitiesIn({ topLeft: { x: xScale.scale(1.5), y: yScale.scale(2.5) }, @@ -100,13 +88,8 @@ describe("Plots", () => { }); it("retrieves the entities that intersect with the given ranges", () => { - let xScale = new Plottable.Scales.Linear(); - let yScale = new Plottable.Scales.Linear(); - let dataset = new Plottable.Dataset(DATA); - let plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(dataset).renderTo(svg); + plot.addDataset(new Plottable.Dataset(DATA)) + plot.renderTo(svg); let entities = plot.entitiesIn( {min: xScale.scale(1.5), max: xScale.scale(2.5)}, @@ -115,7 +98,6 @@ describe("Plots", () => { assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); }); - }); describe("RectanglePlot - autorangeMode()", () => { From 0fad9158fb21da96aa77734785d31f0e7e72163a Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 12:10:41 -0700 Subject: [PATCH 013/160] [refactorRectangle] refactored autorangeMode for the rectanglePlot --- test/plots/rectanglePlotTests.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 67b7690b0b..404472e201 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -3,8 +3,6 @@ describe("Plots", () => { describe("RectanglePlot", () => { describe("RectanglePlot - basics", () => { - let SVG_WIDTH = 300; - let SVG_HEIGHT = 300; let DATA = [ { x: 0, y: 0, x2: 1, y2: 1 }, { x: 1, y: 1, x2: 2, y2: 2 }, @@ -29,7 +27,7 @@ describe("Plots", () => { let plot: Plottable.Plots.Rectangle; beforeEach(() => { - svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + svg = TestMethods.generateSVG(300, 300); xScale = new Plottable.Scales.Linear(); yScale = new Plottable.Scales.Linear(); plot = new Plottable.Plots.Rectangle() @@ -44,12 +42,14 @@ describe("Plots", () => { it("renders correctly", () => { plot.addDataset(new Plottable.Dataset(DATA)); plot.renderTo(svg); + VERIFY_CELLS(( plot)._renderArea.selectAll("rect")); }); it("retrieves the correct entity under a point", () => { plot.addDataset(new Plottable.Dataset(DATA)) plot.renderTo(svg); + let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) }); assert.lengthOf(entities, 1, "found only one entity when querying a point inside the third rectangle"); assert.strictEqual(entities[0].index, 2, "entity retrieved is at index 2"); @@ -101,13 +101,10 @@ describe("Plots", () => { }); describe("RectanglePlot - autorangeMode()", () => { - let SVG_WIDTH = 300; - let SVG_HEIGHT = 300; - let svg: d3.Selection; beforeEach(() => { - svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + svg = TestMethods.generateSVG(300, 300); }); afterEach(() => { @@ -125,9 +122,9 @@ describe("Plots", () => { xScale.padProportion(0); let plot = new Plottable.Plots.Rectangle(); - plot.x(function(d) { return d.x; }, xScale); - plot.x2(function(d) { return d.x2; }); - plot.y(function(d) { return d.y; }, yScale); + plot.x((d) => d.x, xScale); + plot.x2((d) => d.x2); + plot.y((d) => d.y, yScale); plot.addDataset(new Plottable.Dataset(staggeredData)); plot.autorangeMode("x"); plot.renderTo(svg); @@ -153,9 +150,9 @@ describe("Plots", () => { yScale.padProportion(0); let plot = new Plottable.Plots.Rectangle(); - plot.x(function(d) { return d.x; }, xScale); - plot.y(function(d) { return d.y; }, yScale); - plot.y2(function(d) { return d.y2; }); + plot.x((d) => d.x, xScale); + plot.y((d) => d.y, yScale); + plot.y2((d) => d.y2); plot.addDataset(new Plottable.Dataset(staggeredData)); plot.autorangeMode("y"); plot.renderTo(svg); From 4b51fe71cfa7d6728d82bafac8d5feeb622910fd Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:08:39 -0700 Subject: [PATCH 014/160] [refactorRectangle] refactored Grid plot part 1 --- test/plots/rectanglePlotTests.ts | 111 +++++++++++++++---------------- 1 file changed, 54 insertions(+), 57 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 404472e201..9b7e48ced2 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -257,53 +257,53 @@ describe("Plots", () => { assert.strictEqual(cellBV.attr("fill"), "#777777", "cell 'BV' color is correct"); }; - it("renders correctly", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); + let svg: d3.Selection; + let xScale: Plottable.Scales.Category; + let yScale: Plottable.Scales.Category; + let colorScale: Plottable.Scales.InterpolatedColor; + + beforeEach(() => { + svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + xScale = new Plottable.Scales.Category(); + yScale = new Plottable.Scales.Category(); + colorScale = new Plottable.Scales.InterpolatedColor(); colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); - gridPlot.addDataset(new Plottable.Dataset(DATA)) + }); + + afterEach(() => { + svg.remove(); + }); + + it("renders correctly", () => { + let plot = new Plottable.Plots.Rectangle(); + plot.addDataset(new Plottable.Dataset(DATA)) .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) + plot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); - VERIFY_CELLS(( gridPlot)._renderArea.selectAll("rect")[0]); - svg.remove(); + plot.renderTo(svg); + VERIFY_CELLS(( plot)._renderArea.selectAll("rect")[0]); }); it("renders correctly when data is set after construction", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dataset = new Plottable.Dataset(); - let gridPlot = new Plottable.Plots.Rectangle(); - gridPlot.addDataset(dataset) + let plot = new Plottable.Plots.Rectangle(); + plot.addDataset(dataset) .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) + plot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale) .renderTo(svg); dataset.data(DATA); - VERIFY_CELLS(( gridPlot)._renderArea.selectAll("rect")[0]); - svg.remove(); + VERIFY_CELLS(( plot)._renderArea.selectAll("rect")[0]); }); it("renders correctly when there isn't data for every spot", () => { let CELL_HEIGHT = 50; let CELL_WIDTH = 100; - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dataset = new Plottable.Dataset(); - let gridPlot = new Plottable.Plots.Rectangle(); - gridPlot.addDataset(dataset) + let plot = new Plottable.Plots.Rectangle(); + plot.addDataset(dataset) .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) + plot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale) .renderTo(svg); let data = [ @@ -313,7 +313,7 @@ describe("Plots", () => { {x: "D", y: "Z", magnitude: 24} ]; dataset.data(data); - let cells = ( gridPlot)._renderArea.selectAll("rect")[0]; + let cells = ( plot)._renderArea.selectAll("rect")[0]; assert.strictEqual(cells.length, data.length); for (let i = 0; i < cells.length; i++) { let cell = d3.select(cells[i]); @@ -322,25 +322,19 @@ describe("Plots", () => { assert.strictEqual(cell.attr("width"), String(CELL_WIDTH), "Cell width is correct"); assert.strictEqual(cell.attr("height"), String(CELL_HEIGHT), "Cell height is correct"); } - svg.remove(); }); it("can invert y axis correctly", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); - gridPlot.addDataset(new Plottable.Dataset(DATA)) + let plot = new Plottable.Plots.Rectangle(); + plot.addDataset(new Plottable.Dataset(DATA)) .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) + plot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale) .renderTo(svg); yScale.domain(["U", "V"]); - let cells = ( gridPlot)._renderArea.selectAll("rect")[0]; + let cells = ( plot)._renderArea.selectAll("rect")[0]; let cellAU = d3.select(cells[0]); let cellAV = d3.select(cells[2]); cellAU.attr("fill", "#000000"); @@ -352,7 +346,7 @@ describe("Plots", () => { cellAV.attr("y", "0"); yScale.domain(["V", "U"]); - cells = ( gridPlot)._renderArea.selectAll("rect")[0]; + cells = ( plot)._renderArea.selectAll("rect")[0]; cellAU = d3.select(cells[0]); cellAV = d3.select(cells[2]); cellAU.attr("fill", "#000000"); @@ -363,10 +357,13 @@ describe("Plots", () => { cellAV.attr("x", "0"); cellAV.attr("y", "100"); - svg.remove(); }); }); + + + + describe("Rectangle Plot - selections()", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 200; @@ -383,15 +380,15 @@ describe("Plots", () => { let colorScale = new Plottable.Scales.InterpolatedColor(); colorScale.range(["black", "white"]); let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); + let plot = new Plottable.Plots.Rectangle(); let dataset = new Plottable.Dataset(DATA); - gridPlot.addDataset(dataset) + plot.addDataset(dataset) .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) + plot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); + plot.renderTo(svg); - let allCells = gridPlot.selections(); + let allCells = plot.selections(); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); svg.remove(); @@ -403,15 +400,15 @@ describe("Plots", () => { let colorScale = new Plottable.Scales.InterpolatedColor(); colorScale.range(["black", "white"]); let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); + let plot = new Plottable.Plots.Rectangle(); let dataset = new Plottable.Dataset(DATA); - gridPlot.addDataset(dataset) + plot.addDataset(dataset) .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) + plot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); + plot.renderTo(svg); - let allCells = gridPlot.selections([dataset]); + let allCells = plot.selections([dataset]); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); let selectionData = allCells.data(); assert.includeMembers(selectionData, DATA, "data in selection data"); @@ -425,16 +422,16 @@ describe("Plots", () => { let colorScale = new Plottable.Scales.InterpolatedColor(); colorScale.range(["black", "white"]); let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let gridPlot = new Plottable.Plots.Rectangle(); + let plot = new Plottable.Plots.Rectangle(); let dataset = new Plottable.Dataset(DATA); - gridPlot.addDataset(dataset) + plot.addDataset(dataset) .attr("fill", (d) => d.magnitude, colorScale); - gridPlot.x((d: any) => d.x, xScale) + plot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale); - gridPlot.renderTo(svg); + plot.renderTo(svg); let dummyDataset = new Plottable.Dataset([]); - let allCells = gridPlot.selections([dataset, dummyDataset]); + let allCells = plot.selections([dataset, dummyDataset]); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); let selectionData = allCells.data(); assert.includeMembers(selectionData, DATA, "data in selection data"); From c5b6bcee7973a2c2bb44d81806ae983dafc4a968 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:13:19 -0700 Subject: [PATCH 015/160] [refactorRectangle] refactored GridPlot part 2 --- test/plots/rectanglePlotTests.ts | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 9b7e48ced2..e6a05f1b4e 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -277,9 +277,9 @@ describe("Plots", () => { it("renders correctly", () => { let plot = new Plottable.Plots.Rectangle(); plot.addDataset(new Plottable.Dataset(DATA)) - .attr("fill", (d) => d.magnitude, colorScale); + plot.attr("fill", (d) => d.magnitude, colorScale); plot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); + plot.y((d: any) => d.y, yScale); plot.renderTo(svg); VERIFY_CELLS(( plot)._renderArea.selectAll("rect")[0]); }); @@ -288,10 +288,10 @@ describe("Plots", () => { let dataset = new Plottable.Dataset(); let plot = new Plottable.Plots.Rectangle(); plot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); + plot.attr("fill", (d) => d.magnitude, colorScale); plot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .renderTo(svg); + plot.y((d: any) => d.y, yScale) + plot.renderTo(svg); dataset.data(DATA); VERIFY_CELLS(( plot)._renderArea.selectAll("rect")[0]); }); @@ -302,10 +302,10 @@ describe("Plots", () => { let dataset = new Plottable.Dataset(); let plot = new Plottable.Plots.Rectangle(); plot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); + plot.attr("fill", (d) => d.magnitude, colorScale); plot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .renderTo(svg); + plot.y((d: any) => d.y, yScale) + plot.renderTo(svg); let data = [ {x: "A", y: "W", magnitude: 0}, {x: "B", y: "X", magnitude: 8}, @@ -327,10 +327,10 @@ describe("Plots", () => { it("can invert y axis correctly", () => { let plot = new Plottable.Plots.Rectangle(); plot.addDataset(new Plottable.Dataset(DATA)) - .attr("fill", (d) => d.magnitude, colorScale); + plot.attr("fill", (d) => d.magnitude, colorScale); plot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .renderTo(svg); + plot.y((d: any) => d.y, yScale) + plot.renderTo(svg); yScale.domain(["U", "V"]); @@ -356,14 +356,9 @@ describe("Plots", () => { cellAV.attr("fill", "#ffffff"); cellAV.attr("x", "0"); cellAV.attr("y", "100"); - }); }); - - - - describe("Rectangle Plot - selections()", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 200; From bce1fa81ad9838086c3a09d1b73e082df5472014 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:24:52 -0700 Subject: [PATCH 016/160] [refactorRectangle] semicolons --- test/plots/rectanglePlotTests.ts | 103 ++++++++++++++----------------- 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index e6a05f1b4e..d243c91751 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -30,9 +30,9 @@ describe("Plots", () => { svg = TestMethods.generateSVG(300, 300); xScale = new Plottable.Scales.Linear(); yScale = new Plottable.Scales.Linear(); - plot = new Plottable.Plots.Rectangle() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); + plot = new Plottable.Plots.Rectangle(); + plot.x((d) => d.x, xScale).x2((d) => d.x2); + plot.y((d) => d.y, yScale).y2((d) => d.y2); }); afterEach(() => { @@ -47,7 +47,7 @@ describe("Plots", () => { }); it("retrieves the correct entity under a point", () => { - plot.addDataset(new Plottable.Dataset(DATA)) + plot.addDataset(new Plottable.Dataset(DATA)); plot.renderTo(svg); let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) }); @@ -60,7 +60,7 @@ describe("Plots", () => { { x: 1, y: 1, x2: 3, y2: 3 }, { x: 4, y: 2, x2: 2, y2: 4 } ]); - plot.addDataset(dataset) + plot.addDataset(dataset); plot.renderTo(svg); let entities = plot.entitiesAt({ x: xScale.scale(2), y: xScale.scale(2) }); @@ -76,7 +76,7 @@ describe("Plots", () => { }); it("retrieves the entities that intersect with the bounding box", () => { - plot.addDataset(new Plottable.Dataset(DATA)) + plot.addDataset(new Plottable.Dataset(DATA)); plot.renderTo(svg); let entities = plot.entitiesIn({ @@ -88,7 +88,7 @@ describe("Plots", () => { }); it("retrieves the entities that intersect with the given ranges", () => { - plot.addDataset(new Plottable.Dataset(DATA)) + plot.addDataset(new Plottable.Dataset(DATA)); plot.renderTo(svg); let entities = plot.entitiesIn( @@ -185,10 +185,9 @@ describe("Plots", () => { let yScale = new Plottable.Scales.Linear(); let plot = new Plottable.Plots.Rectangle(); - plot - .x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .y2((d: any) => d.y2); + plot.x((d: any) => d.x, xScale); + plot.y((d: any) => d.y, yScale); + plot.y2((d: any) => d.y2); plot.addDataset(new Plottable.Dataset(data1)); plot.renderTo(svg); @@ -276,9 +275,9 @@ describe("Plots", () => { it("renders correctly", () => { let plot = new Plottable.Plots.Rectangle(); - plot.addDataset(new Plottable.Dataset(DATA)) + plot.addDataset(new Plottable.Dataset(DATA)); plot.attr("fill", (d) => d.magnitude, colorScale); - plot.x((d: any) => d.x, xScale) + plot.x((d: any) => d.x, xScale); plot.y((d: any) => d.y, yScale); plot.renderTo(svg); VERIFY_CELLS(( plot)._renderArea.selectAll("rect")[0]); @@ -289,8 +288,8 @@ describe("Plots", () => { let plot = new Plottable.Plots.Rectangle(); plot.addDataset(dataset) plot.attr("fill", (d) => d.magnitude, colorScale); - plot.x((d: any) => d.x, xScale) - plot.y((d: any) => d.y, yScale) + plot.x((d: any) => d.x, xScale); + plot.y((d: any) => d.y, yScale); plot.renderTo(svg); dataset.data(DATA); VERIFY_CELLS(( plot)._renderArea.selectAll("rect")[0]); @@ -301,10 +300,10 @@ describe("Plots", () => { let CELL_WIDTH = 100; let dataset = new Plottable.Dataset(); let plot = new Plottable.Plots.Rectangle(); - plot.addDataset(dataset) + plot.addDataset(dataset); plot.attr("fill", (d) => d.magnitude, colorScale); - plot.x((d: any) => d.x, xScale) - plot.y((d: any) => d.y, yScale) + plot.x((d: any) => d.x, xScale); + plot.y((d: any) => d.y, yScale); plot.renderTo(svg); let data = [ {x: "A", y: "W", magnitude: 0}, @@ -326,10 +325,10 @@ describe("Plots", () => { it("can invert y axis correctly", () => { let plot = new Plottable.Plots.Rectangle(); - plot.addDataset(new Plottable.Dataset(DATA)) + plot.addDataset(new Plottable.Dataset(DATA)); plot.attr("fill", (d) => d.magnitude, colorScale); - plot.x((d: any) => d.x, xScale) - plot.y((d: any) => d.y, yScale) + plot.x((d: any) => d.x, xScale); + plot.y((d: any) => d.y, yScale); plot.renderTo(svg); yScale.domain(["U", "V"]); @@ -369,60 +368,52 @@ describe("Plots", () => { {x: "B", y: "V", magnitude: 8}, ]; - it("retrieves all selections with no args", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); + let svg: d3.Selection; + let xScale: Plottable.Scales.Category; + let yScale: Plottable.Scales.Category; + let colorScale: Plottable.Scales.InterpolatedColor; + let plot: Plottable.Plots.Rectangle; + + beforeEach(() => { + svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + xScale = new Plottable.Scales.Category(); + yScale = new Plottable.Scales.Category(); + colorScale = new Plottable.Scales.InterpolatedColor(); colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let plot = new Plottable.Plots.Rectangle(); + + plot = new Plottable.Plots.Rectangle(); + plot.attr("fill", (d) => d.magnitude, colorScale); + plot.x((d: any) => d.x, xScale); + plot.y((d: any) => d.y, yScale); + }); + + afterEach(() => { + svg.remove(); + }); + + it("retrieves all selections with no args", () => { let dataset = new Plottable.Dataset(DATA); - plot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - plot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); + plot.addDataset(dataset); plot.renderTo(svg); let allCells = plot.selections(); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); - - svg.remove(); }); it("retrieves correct selections", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let plot = new Plottable.Plots.Rectangle(); let dataset = new Plottable.Dataset(DATA); - plot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - plot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); + plot.addDataset(dataset); plot.renderTo(svg); let allCells = plot.selections([dataset]); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); let selectionData = allCells.data(); assert.includeMembers(selectionData, DATA, "data in selection data"); - - svg.remove(); }); it("skips invalid Datasets", () => { - let xScale = new Plottable.Scales.Category(); - let yScale = new Plottable.Scales.Category(); - let colorScale = new Plottable.Scales.InterpolatedColor(); - colorScale.range(["black", "white"]); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let plot = new Plottable.Plots.Rectangle(); let dataset = new Plottable.Dataset(DATA); - plot.addDataset(dataset) - .attr("fill", (d) => d.magnitude, colorScale); - plot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale); + plot.addDataset(dataset); plot.renderTo(svg); let dummyDataset = new Plottable.Dataset([]); @@ -430,8 +421,6 @@ describe("Plots", () => { assert.strictEqual(allCells.size(), 4, "all cells retrieved"); let selectionData = allCells.data(); assert.includeMembers(selectionData, DATA, "data in selection data"); - - svg.remove(); }); }); }); From c046942620d0f54da4da929763fdfca960a2c1f3 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:29:55 -0700 Subject: [PATCH 017/160] [refactorRectangle] selections refactor finish --- test/plots/rectanglePlotTests.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index d243c91751..f8002055e3 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -286,7 +286,7 @@ describe("Plots", () => { it("renders correctly when data is set after construction", () => { let dataset = new Plottable.Dataset(); let plot = new Plottable.Plots.Rectangle(); - plot.addDataset(dataset) + plot.addDataset(dataset); plot.attr("fill", (d) => d.magnitude, colorScale); plot.x((d: any) => d.x, xScale); plot.y((d: any) => d.y, yScale); @@ -373,6 +373,7 @@ describe("Plots", () => { let yScale: Plottable.Scales.Category; let colorScale: Plottable.Scales.InterpolatedColor; let plot: Plottable.Plots.Rectangle; + var dataset: Plottable.Dataset; beforeEach(() => { svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); @@ -385,6 +386,10 @@ describe("Plots", () => { plot.attr("fill", (d) => d.magnitude, colorScale); plot.x((d: any) => d.x, xScale); plot.y((d: any) => d.y, yScale); + + dataset = new Plottable.Dataset(DATA); + plot.addDataset(dataset); + plot.renderTo(svg); }); afterEach(() => { @@ -392,19 +397,11 @@ describe("Plots", () => { }); it("retrieves all selections with no args", () => { - let dataset = new Plottable.Dataset(DATA); - plot.addDataset(dataset); - plot.renderTo(svg); - let allCells = plot.selections(); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); }); it("retrieves correct selections", () => { - let dataset = new Plottable.Dataset(DATA); - plot.addDataset(dataset); - plot.renderTo(svg); - let allCells = plot.selections([dataset]); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); let selectionData = allCells.data(); @@ -412,10 +409,6 @@ describe("Plots", () => { }); it("skips invalid Datasets", () => { - let dataset = new Plottable.Dataset(DATA); - plot.addDataset(dataset); - plot.renderTo(svg); - let dummyDataset = new Plottable.Dataset([]); let allCells = plot.selections([dataset, dummyDataset]); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); From 988832683ffb7c8e2dcecd4b3fddf82ffe574cd9 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:30:53 -0700 Subject: [PATCH 018/160] [refactorRectangle] tslint --- test/plots/rectanglePlotTests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index f8002055e3..3b0e71c0c4 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -373,7 +373,7 @@ describe("Plots", () => { let yScale: Plottable.Scales.Category; let colorScale: Plottable.Scales.InterpolatedColor; let plot: Plottable.Plots.Rectangle; - var dataset: Plottable.Dataset; + let dataset: Plottable.Dataset; beforeEach(() => { svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); From 2de2600c81556dd8843051f85839d655fd4ec2b5 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:46:03 -0700 Subject: [PATCH 019/160] [refactorSegment] Hierarchy fix for segment plot --- test/plots/segmentPlotTests.ts | 204 ++++++++++++++++++--------------- 1 file changed, 111 insertions(+), 93 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index a49a577c8a..f811876cce 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -2,116 +2,124 @@ describe("Plots", () => { describe("SegmentPlot", () => { - let svg: d3.Selection; - let xScale: Plottable.Scales.Linear; - let yScale: Plottable.Scales.Linear; - let renderArea: d3.Selection; - let data = [ - { x: 1, y: 1, x2: 4, y2: 4 }, - { x: 2, y: 2, x2: 3, y2: 5 }, - { x: 3, y: 3, x2: 5, y2: 2 } - ]; - - beforeEach(() => { - svg = TestMethods.generateSVG(500, 500); - xScale = new Plottable.Scales.Linear(); - yScale = new Plottable.Scales.Linear(); - }); - it("renders a line properly", () => { - let plot = new Plottable.Plots.Segment(); - plot.x(function(d) { return d.x; }, xScale); - plot.x2(function(d) { return d.x2; }); - plot.y(function(d) { return d.y; }, yScale); - plot.y2(function(d) { return d.y2; }); - plot.addDataset(new Plottable.Dataset([data[0]])).renderTo(svg); - renderArea = ( plot)._renderArea; - let lineSelection = d3.select(renderArea.selectAll("line")[0][0]); - assert.strictEqual(+lineSelection.attr("x1"), 62.5, "x1 is correct"); - assert.strictEqual(+lineSelection.attr("x2"), 437.5, "x2 is correct"); - assert.strictEqual(+lineSelection.attr("y1"), 437.5, "y1 is correct"); - assert.strictEqual(+lineSelection.attr("y2"), 62.5, "y2 is correct"); - svg.remove(); - }); + describe("SegmentPlot - basics", () => { + let svg: d3.Selection; + let xScale: Plottable.Scales.Linear; + let yScale: Plottable.Scales.Linear; + let renderArea: d3.Selection; + let data = [ + { x: 1, y: 1, x2: 4, y2: 4 }, + { x: 2, y: 2, x2: 3, y2: 5 }, + { x: 3, y: 3, x2: 5, y2: 2 } + ]; - it("renders vertical lines when x2 is not set", () => { - let plot = new Plottable.Plots.Segment(); - plot.x(function(d) { return d.x; }, xScale); - plot.y(function(d) { return d.y; }, yScale); - plot.y2(function(d) { return d.y2; }); - plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); - renderArea = ( plot)._renderArea; - renderArea.selectAll("line")[0].forEach((line) => { - let lineSelection = d3.select(line); - assert.strictEqual(lineSelection.attr("x1"), lineSelection.attr("x2"), "line is vertical"); + beforeEach(() => { + svg = TestMethods.generateSVG(500, 500); + xScale = new Plottable.Scales.Linear(); + yScale = new Plottable.Scales.Linear(); }); - svg.remove(); - }); - it("renders horizontal lines when y2 is not set", () => { - let plot = new Plottable.Plots.Segment(); - plot.x(function(d) { return d.x; }, xScale); - plot.x2(function(d) { return d.x2; }); - plot.y(function(d) { return d.y; }, yScale); - plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); - renderArea = ( plot)._renderArea; - renderArea.selectAll("line")[0].forEach((line) => { - let lineSelection = d3.select(line); - assert.strictEqual(lineSelection.attr("y1"), lineSelection.attr("y2"), "line is horizontal"); + it("renders a line properly", () => { + let plot = new Plottable.Plots.Segment(); + plot.x((d) => d.x, xScale); + plot.x2((d) => d.x2); + plot.y((d) => d.y, yScale); + plot.y2((d) => d.y2); + plot.addDataset(new Plottable.Dataset([data[0]])) + plot.renderTo(svg); + renderArea = ( plot)._renderArea; + let lineSelection = d3.select(renderArea.selectAll("line")[0][0]); + assert.strictEqual(+lineSelection.attr("x1"), 62.5, "x1 is correct"); + assert.strictEqual(+lineSelection.attr("x2"), 437.5, "x2 is correct"); + assert.strictEqual(+lineSelection.attr("y1"), 437.5, "y1 is correct"); + assert.strictEqual(+lineSelection.attr("y2"), 62.5, "y2 is correct"); + svg.remove(); }); - svg.remove(); - }); - it("autorangeMode(\"x\")", () => { - let staggeredData = [ - { y: 0, x: 0, x2: 1 }, - { y: 1, x: 1, x2: 2 } - ]; - xScale.padProportion(0); + it("renders vertical lines when x2 is not set", () => { + let plot = new Plottable.Plots.Segment(); + plot.x((d) => d.x, xScale); + plot.y((d) => d.y, yScale); + plot.y2((d) => d.y2); + plot.addDataset(new Plottable.Dataset(data)) + plot.renderTo(svg); + renderArea = ( plot)._renderArea; + renderArea.selectAll("line")[0].forEach((line) => { + let lineSelection = d3.select(line); + assert.strictEqual(lineSelection.attr("x1"), lineSelection.attr("x2"), "line is vertical"); + }); + svg.remove(); + }); - let plot = new Plottable.Plots.Segment(); - plot.x(function(d) { return d.x; }, xScale); - plot.x2(function(d) { return d.x2; }); - plot.y(function(d) { return d.y; }, yScale); - plot.addDataset(new Plottable.Dataset(staggeredData)); - plot.autorangeMode("x"); - plot.renderTo(svg); + it("renders horizontal lines when y2 is not set", () => { + let plot = new Plottable.Plots.Segment(); + plot.x((d) => d.x, xScale); + plot.x2((d) => d.x2); + plot.y((d) => d.y, yScale); + plot.addDataset(new Plottable.Dataset(data)) + plot.renderTo(svg); + renderArea = ( plot)._renderArea; + renderArea.selectAll("line")[0].forEach((line) => { + let lineSelection = d3.select(line); + assert.strictEqual(lineSelection.attr("y1"), lineSelection.attr("y2"), "line is horizontal"); + }); + svg.remove(); + }); - assert.deepEqual(xScale.domain(), [0, 2], "y domain includes both visible segments"); + it("autorangeMode(\"x\")", () => { + let staggeredData = [ + { y: 0, x: 0, x2: 1 }, + { y: 1, x: 1, x2: 2 } + ]; + xScale.padProportion(0); - yScale.domain([-0.5, 0.5]); - assert.deepEqual(xScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); + let plot = new Plottable.Plots.Segment(); + plot.x((d) => d.x, xScale); + plot.x2((d) => d.x2); + plot.y((d) => d.y, yScale); + plot.addDataset(new Plottable.Dataset(staggeredData)); + plot.autorangeMode("x"); - yScale.domain([0.5, 1.5]); - assert.deepEqual(xScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); + plot.renderTo(svg); - svg.remove(); - }); + assert.deepEqual(xScale.domain(), [0, 2], "y domain includes both visible segments"); - it("autorangeMode(\"y\")", () => { - let staggeredData = [ - { x: 0, y: 0, y2: 1 }, - { x: 1, y: 1, y2: 2 } - ]; - yScale.padProportion(0); + yScale.domain([-0.5, 0.5]); + assert.deepEqual(xScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); + + yScale.domain([0.5, 1.5]); + assert.deepEqual(xScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); + + svg.remove(); + }); + + it("autorangeMode(\"y\")", () => { + let staggeredData = [ + { x: 0, y: 0, y2: 1 }, + { x: 1, y: 1, y2: 2 } + ]; + yScale.padProportion(0); - let plot = new Plottable.Plots.Segment(); - plot.x(function(d) { return d.x; }, xScale); - plot.y(function(d) { return d.y; }, yScale); - plot.y2(function(d) { return d.y2; }); - plot.addDataset(new Plottable.Dataset(staggeredData)); - plot.autorangeMode("y"); - plot.renderTo(svg); + let plot = new Plottable.Plots.Segment(); + plot.x((d) => d.x, xScale); + plot.y((d) => d.y, yScale); + plot.y2((d) => d.y2); + plot.addDataset(new Plottable.Dataset(staggeredData)); + plot.autorangeMode("y"); - assert.deepEqual(yScale.domain(), [0, 2], "y domain includes both visible segments"); + plot.renderTo(svg); - xScale.domain([-0.5, 0.5]); - assert.deepEqual(yScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); + assert.deepEqual(yScale.domain(), [0, 2], "y domain includes both visible segments"); - xScale.domain([0.5, 1.5]); - assert.deepEqual(yScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); + xScale.domain([-0.5, 0.5]); + assert.deepEqual(yScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); - svg.remove(); + xScale.domain([0.5, 1.5]); + assert.deepEqual(yScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); + + svg.remove(); + }); }); describe("entitiesIn() returns segments that intersect with the given constraints", () => { @@ -121,6 +129,16 @@ describe("Plots", () => { { x: 4, x2: 5, y: 2, y2: 4 }, { x: 2, x2: 4, y: 1, y2: 1 }]; + let svg: d3.Selection; + let xScale: Plottable.Scales.Linear; + let yScale: Plottable.Scales.Linear; + + beforeEach(() => { + svg = TestMethods.generateSVG(500, 500); + xScale = new Plottable.Scales.Linear(); + yScale = new Plottable.Scales.Linear(); + }); + it("retrieves the entities that intersect with the bounding box", () => { let plot = new Plottable.Plots.Segment() .x((d) => d.x, xScale).x2((d) => d.x2) From 47fa57b40732b8a5e581a233eae22d40c750a1e3 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:49:06 -0700 Subject: [PATCH 020/160] [refactorSegment] indentation and afterEach() --- test/plots/segmentPlotTests.ts | 35 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index f811876cce..3b643a0449 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -20,6 +20,10 @@ describe("Plots", () => { yScale = new Plottable.Scales.Linear(); }); + afterEach(() => { + svg.remove(); + }); + it("renders a line properly", () => { let plot = new Plottable.Plots.Segment(); plot.x((d) => d.x, xScale); @@ -34,7 +38,6 @@ describe("Plots", () => { assert.strictEqual(+lineSelection.attr("x2"), 437.5, "x2 is correct"); assert.strictEqual(+lineSelection.attr("y1"), 437.5, "y1 is correct"); assert.strictEqual(+lineSelection.attr("y2"), 62.5, "y2 is correct"); - svg.remove(); }); it("renders vertical lines when x2 is not set", () => { @@ -46,10 +49,9 @@ describe("Plots", () => { plot.renderTo(svg); renderArea = ( plot)._renderArea; renderArea.selectAll("line")[0].forEach((line) => { - let lineSelection = d3.select(line); - assert.strictEqual(lineSelection.attr("x1"), lineSelection.attr("x2"), "line is vertical"); + let lineSelection = d3.select(line); + assert.strictEqual(lineSelection.attr("x1"), lineSelection.attr("x2"), "line is vertical"); }); - svg.remove(); }); it("renders horizontal lines when y2 is not set", () => { @@ -61,10 +63,9 @@ describe("Plots", () => { plot.renderTo(svg); renderArea = ( plot)._renderArea; renderArea.selectAll("line")[0].forEach((line) => { - let lineSelection = d3.select(line); - assert.strictEqual(lineSelection.attr("y1"), lineSelection.attr("y2"), "line is horizontal"); + let lineSelection = d3.select(line); + assert.strictEqual(lineSelection.attr("y1"), lineSelection.attr("y2"), "line is horizontal"); }); - svg.remove(); }); it("autorangeMode(\"x\")", () => { @@ -90,8 +91,6 @@ describe("Plots", () => { yScale.domain([0.5, 1.5]); assert.deepEqual(xScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); - - svg.remove(); }); it("autorangeMode(\"y\")", () => { @@ -117,12 +116,10 @@ describe("Plots", () => { xScale.domain([0.5, 1.5]); assert.deepEqual(yScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); - - svg.remove(); }); }); - describe("entitiesIn() returns segments that intersect with the given constraints", () => { + describe("SegmentPlot - entitiesIn()", () => { let data = [ { x: 1, x2: 1, y: 1, y2: 4 }, { x: 2, x2: 3, y: 4, y2: 3 }, @@ -139,6 +136,10 @@ describe("Plots", () => { yScale = new Plottable.Scales.Linear(); }); + afterEach(() => { + svg.remove(); + }); + it("retrieves the entities that intersect with the bounding box", () => { let plot = new Plottable.Plots.Segment() .x((d) => d.x, xScale).x2((d) => d.x2) @@ -150,7 +151,6 @@ describe("Plots", () => { assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); assert.strictEqual(entities[0].index, 0, "the entity of index 0 is retrieved"); assert.strictEqual(entities[1].index, 1, "the entity of index 1 is retrieved"); - svg.remove(); }); it("retrieves the entities that intersect with given ranges", () => { @@ -164,7 +164,6 @@ describe("Plots", () => { assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the ranges"); assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); - svg.remove(); }); it("retrieves the entity if exactly one of its endpoints is in the ranges", () => { @@ -188,8 +187,6 @@ describe("Plots", () => { // horizontal segment checkEntitiesInRange(plot, 3, 1.5, 2.5, 1.5, 0.5); checkEntitiesInRange(plot, 3, 3.5, 4.5, 1.5, 0.5); - - svg.remove(); }); it("retrieves the entity if both of its endpoints are in the ranges", () => { @@ -209,8 +206,6 @@ describe("Plots", () => { // horizontal segment checkEntitiesInRange(plot, 3, 1.5, 4.5, 1.5, 0.5); - - svg.remove(); }); it("retrieves the entity if it intersects with the ranges with no endpoints inside", () => { @@ -230,8 +225,6 @@ describe("Plots", () => { // horizontal segment checkEntitiesInRange(plot, 3, 2.5, 3.5, 1.5, 0.5); - - svg.remove(); }); it("returns empty array when no entities intersect with the ranges", () => { @@ -244,8 +237,6 @@ describe("Plots", () => { { min: xScale.scale(1.5), max: xScale.scale(2.5) }, { min: yScale.scale(2.5), max: yScale.scale(1.5) }); assert.lengthOf(entities, 0, "no entities intersects with the ranges"); - - svg.remove(); }); function checkEntitiesInRange(plot: Plottable.Plots.Segment, index: number, From 7276be542f1486188f0e7ffe960ba8a7abed3079 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:51:51 -0700 Subject: [PATCH 021/160] [refactorSegment] finished the segmentPlotTest refactor pass 1 --- test/plots/segmentPlotTests.ts | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index 3b643a0449..a80486175f 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -129,11 +129,16 @@ describe("Plots", () => { let svg: d3.Selection; let xScale: Plottable.Scales.Linear; let yScale: Plottable.Scales.Linear; + let plot: Plottable.Plots.Segment; beforeEach(() => { svg = TestMethods.generateSVG(500, 500); xScale = new Plottable.Scales.Linear(); yScale = new Plottable.Scales.Linear(); + plot = new Plottable.Plots.Segment() + .x((d) => d.x, xScale).x2((d) => d.x2) + .y((d) => d.y, yScale).y2((d) => d.y2); + plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); }); afterEach(() => { @@ -141,10 +146,6 @@ describe("Plots", () => { }); it("retrieves the entities that intersect with the bounding box", () => { - let plot = new Plottable.Plots.Segment() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); let entities = plot.entitiesIn({ topLeft: { x: xScale.scale(0), y: yScale.scale(4.5) }, bottomRight: { x: xScale.scale(2.5), y: yScale.scale(3) } }); @@ -154,10 +155,6 @@ describe("Plots", () => { }); it("retrieves the entities that intersect with given ranges", () => { - let plot = new Plottable.Plots.Segment() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); let entities = plot.entitiesIn( { min: xScale.scale(2.5), max: xScale.scale(4.5) }, { min: yScale.scale(4.5), max: yScale.scale(2.5) }); @@ -167,11 +164,6 @@ describe("Plots", () => { }); it("retrieves the entity if exactly one of its endpoints is in the ranges", () => { - let plot = new Plottable.Plots.Segment() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); - // vertial segment checkEntitiesInRange(plot, 0, 0.5, 1.5, 1.5, 0.5); checkEntitiesInRange(plot, 0, 0.5, 1.5, 4.5, 3.5); @@ -190,11 +182,6 @@ describe("Plots", () => { }); it("retrieves the entity if both of its endpoints are in the ranges", () => { - let plot = new Plottable.Plots.Segment() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); - // vertial segment checkEntitiesInRange(plot, 0, 0.5, 1.5, 4.5, 0.5); @@ -209,11 +196,6 @@ describe("Plots", () => { }); it("retrieves the entity if it intersects with the ranges with no endpoints inside", () => { - let plot = new Plottable.Plots.Segment() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); - // vertial segment checkEntitiesInRange(plot, 0, 0.5, 1.5, 3.5, 1.5); @@ -228,11 +210,6 @@ describe("Plots", () => { }); it("returns empty array when no entities intersect with the ranges", () => { - let plot = new Plottable.Plots.Segment() - .x((d) => d.x, xScale).x2((d) => d.x2) - .y((d) => d.y, yScale).y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); - let entities = plot.entitiesIn( { min: xScale.scale(1.5), max: xScale.scale(2.5) }, { min: yScale.scale(2.5), max: yScale.scale(1.5) }); From 6455fa29c9a896c95bb21466c105ab4872dcb0f9 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 14:54:07 -0700 Subject: [PATCH 022/160] [refactorSegment] tslint --- test/plots/segmentPlotTests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index a80486175f..5bc8d3f585 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -30,7 +30,7 @@ describe("Plots", () => { plot.x2((d) => d.x2); plot.y((d) => d.y, yScale); plot.y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset([data[0]])) + plot.addDataset(new Plottable.Dataset([data[0]])); plot.renderTo(svg); renderArea = ( plot)._renderArea; let lineSelection = d3.select(renderArea.selectAll("line")[0][0]); @@ -45,7 +45,7 @@ describe("Plots", () => { plot.x((d) => d.x, xScale); plot.y((d) => d.y, yScale); plot.y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset(data)) + plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); renderArea = ( plot)._renderArea; renderArea.selectAll("line")[0].forEach((line) => { @@ -59,7 +59,7 @@ describe("Plots", () => { plot.x((d) => d.x, xScale); plot.x2((d) => d.x2); plot.y((d) => d.y, yScale); - plot.addDataset(new Plottable.Dataset(data)) + plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); renderArea = ( plot)._renderArea; renderArea.selectAll("line")[0].forEach((line) => { From 9c847dadef9174b7be17d9e281174a9329911d5a Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 15:15:10 -0700 Subject: [PATCH 023/160] [refactorLayers] Hierarchy --- test/components/dragBoxLayerTests.ts | 460 ++++++++++++++------------- 1 file changed, 238 insertions(+), 222 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 5068f1cfaf..773436f682 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -2,272 +2,280 @@ describe("Interactive Components", () => { describe("DragBoxLayer", () => { - let SVG_WIDTH = 400; - let SVG_HEIGHT = 400; - - it("correctly draws box on drag", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dbl = new Plottable.Components.DragBoxLayer(); - dbl.renderTo(svg); - assert.isFalse(dbl.boxVisible(), "box is hidden initially"); - - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; - - let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - assert.isTrue(dbl.boxVisible(), "box is drawn on drag"); - let bounds = dbl.bounds(); - assert.deepEqual(bounds.topLeft, startPoint, "top-left point was set correctly"); - assert.deepEqual(bounds.bottomRight, endPoint, "bottom-right point was set correctly"); - svg.remove(); - }); + describe("DragBoxLayer - basics", () => { + let SVG_WIDTH = 400; + let SVG_HEIGHT = 400; - it("dismisses on click", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dbl = new Plottable.Components.DragBoxLayer(); - dbl.renderTo(svg); + it("correctly draws box on drag", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dbl = new Plottable.Components.DragBoxLayer(); + dbl.renderTo(svg); + assert.isFalse(dbl.boxVisible(), "box is hidden initially"); - let targetPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; + let startPoint = { + x: SVG_WIDTH / 4, + y: SVG_HEIGHT / 4 + }; + let endPoint = { + x: SVG_WIDTH / 2, + y: SVG_HEIGHT / 2 + }; - let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, targetPoint, targetPoint); + let target = dbl.background(); + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + assert.isTrue(dbl.boxVisible(), "box is drawn on drag"); + let bounds = dbl.bounds(); + assert.deepEqual(bounds.topLeft, startPoint, "top-left point was set correctly"); + assert.deepEqual(bounds.bottomRight, endPoint, "bottom-right point was set correctly"); - assert.isFalse(dbl.boxVisible(), "box is hidden on click"); + svg.remove(); + }); - svg.remove(); - }); + it("dismisses on click", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dbl = new Plottable.Components.DragBoxLayer(); + dbl.renderTo(svg); - it("clipPath enabled", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dbl = new Plottable.Components.DragBoxLayer(); - dbl.renderTo(svg); - TestMethods.verifyClipPath(dbl); - let clipRect = ( dbl)._boxContainer.select(".clip-rect"); - assert.strictEqual(TestMethods.numAttr(clipRect, "width"), SVG_WIDTH, "the clipRect has an appropriate width"); - assert.strictEqual(TestMethods.numAttr(clipRect, "height"), SVG_HEIGHT, "the clipRect has an appropriate height"); - svg.remove(); - }); + let targetPoint = { + x: SVG_WIDTH / 2, + y: SVG_HEIGHT / 2 + }; - it("detectionRadius()", () => { - let dbl = new Plottable.Components.DragBoxLayer(); + let target = dbl.background(); + TestMethods.triggerFakeDragSequence(target, targetPoint, targetPoint); - assert.doesNotThrow(() => dbl.detectionRadius(3), Error, "can set detection radius before anchoring"); + assert.isFalse(dbl.boxVisible(), "box is hidden on click"); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - dbl.renderTo("svg"); + svg.remove(); + }); - let radius = 5; - dbl.detectionRadius(radius); - assert.strictEqual(dbl.detectionRadius(), radius, "can retrieve the detection radius"); - let edges = dbl.content().selectAll("line"); - edges.each(function() { - let edge = d3.select(this); - assert.strictEqual(edge.style("stroke-width"), 2 * radius, "edge width was set correctly"); + it("clipPath enabled", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dbl = new Plottable.Components.DragBoxLayer(); + dbl.renderTo(svg); + TestMethods.verifyClipPath(dbl); + let clipRect = ( dbl)._boxContainer.select(".clip-rect"); + assert.strictEqual(TestMethods.numAttr(clipRect, "width"), SVG_WIDTH, "the clipRect has an appropriate width"); + assert.strictEqual(TestMethods.numAttr(clipRect, "height"), SVG_HEIGHT, "the clipRect has an appropriate height"); + svg.remove(); }); - let corners = dbl.content().selectAll("circle"); - corners.each(function() { - let corner = d3.select(this); - assert.strictEqual(corner.attr("r"), radius, "corner radius was set correctly"); + + it("detectionRadius()", () => { + let dbl = new Plottable.Components.DragBoxLayer(); + + assert.doesNotThrow(() => dbl.detectionRadius(3), Error, "can set detection radius before anchoring"); + + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + dbl.renderTo("svg"); + + let radius = 5; + dbl.detectionRadius(radius); + assert.strictEqual(dbl.detectionRadius(), radius, "can retrieve the detection radius"); + let edges = dbl.content().selectAll("line"); + edges.each(function() { + let edge = d3.select(this); + assert.strictEqual(edge.style("stroke-width"), 2 * radius, "edge width was set correctly"); + }); + let corners = dbl.content().selectAll("circle"); + corners.each(function() { + let corner = d3.select(this); + assert.strictEqual(corner.attr("r"), radius, "corner radius was set correctly"); + }); + + // HACKHACK: chai-assert.d.ts has the wrong signature + ( assert.throws)(() => dbl.detectionRadius(-1), Error, "", "rejects negative values"); + + svg.remove(); }); - // HACKHACK: chai-assert.d.ts has the wrong signature - ( assert.throws)(() => dbl.detectionRadius(-1), Error, "", "rejects negative values"); + it("onDragStart()", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dbl = new Plottable.Components.DragBoxLayer(); + dbl.renderTo(svg); - svg.remove(); - }); + let startPoint = { + x: SVG_WIDTH / 4, + y: SVG_HEIGHT / 4 + }; + let endPoint = { + x: SVG_WIDTH / 2, + y: SVG_HEIGHT / 2 + }; - it("onDragStart()", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dbl = new Plottable.Components.DragBoxLayer(); - dbl.renderTo(svg); + let receivedBounds: Plottable.Bounds; + let callbackCalled = false; + let callback = (b: Plottable.Bounds) => { + receivedBounds = b; + callbackCalled = true; + }; + dbl.onDragStart(callback); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; + let target = dbl.background(); + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - let receivedBounds: Plottable.Bounds; - let callbackCalled = false; - let callback = (b: Plottable.Bounds) => { - receivedBounds = b; - callbackCalled = true; - }; - dbl.onDragStart(callback); + assert.isTrue(callbackCalled, "the callback was called"); + assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); + assert.deepEqual(receivedBounds.bottomRight, startPoint, "bottom-right point was set correctly"); - let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + dbl.offDragStart(callback); - assert.isTrue(callbackCalled, "the callback was called"); - assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); - assert.deepEqual(receivedBounds.bottomRight, startPoint, "bottom-right point was set correctly"); + callbackCalled = false; + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + assert.isFalse(callbackCalled, "the callback was detached from the dragBoxLayer and not called"); - dbl.offDragStart(callback); + svg.remove(); + }); - callbackCalled = false; - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - assert.isFalse(callbackCalled, "the callback was detached from the dragBoxLayer and not called"); + it("onDrag()", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dbl = new Plottable.Components.DragBoxLayer(); + dbl.renderTo(svg); - svg.remove(); - }); + let startPoint = { + x: SVG_WIDTH / 4, + y: SVG_HEIGHT / 4 + }; + let endPoint = { + x: SVG_WIDTH / 2, + y: SVG_HEIGHT / 2 + }; - it("onDrag()", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dbl = new Plottable.Components.DragBoxLayer(); - dbl.renderTo(svg); + let receivedBounds: Plottable.Bounds; + let callbackCalled = false; + let callback = (b: Plottable.Bounds) => { + receivedBounds = b; + callbackCalled = true; + }; + dbl.onDrag(callback); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; + let target = dbl.background(); + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - let receivedBounds: Plottable.Bounds; - let callbackCalled = false; - let callback = (b: Plottable.Bounds) => { - receivedBounds = b; - callbackCalled = true; - }; - dbl.onDrag(callback); + assert.isTrue(callbackCalled, "the callback was called"); + assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); + assert.deepEqual(receivedBounds.bottomRight, endPoint, "bottom-right point was set correctly"); - let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + callbackCalled = false; + dbl.offDrag(callback); - assert.isTrue(callbackCalled, "the callback was called"); - assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); - assert.deepEqual(receivedBounds.bottomRight, endPoint, "bottom-right point was set correctly"); + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); - callbackCalled = false; - dbl.offDrag(callback); + svg.remove(); + }); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); + it("onDragEnd()", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dbl = new Plottable.Components.DragBoxLayer(); + dbl.renderTo(svg); - svg.remove(); - }); + let startPoint = { + x: SVG_WIDTH / 4, + y: SVG_HEIGHT / 4 + }; + let endPoint = { + x: SVG_WIDTH / 2, + y: SVG_HEIGHT / 2 + }; - it("onDragEnd()", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dbl = new Plottable.Components.DragBoxLayer(); - dbl.renderTo(svg); + let receivedBounds: Plottable.Bounds; + let callbackCalled = false; + let callback = (b: Plottable.Bounds) => { + receivedBounds = b; + callbackCalled = true; + }; + dbl.onDragEnd(callback); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; + let target = dbl.background(); + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - let receivedBounds: Plottable.Bounds; - let callbackCalled = false; - let callback = (b: Plottable.Bounds) => { - receivedBounds = b; - callbackCalled = true; - }; - dbl.onDragEnd(callback); + assert.isTrue(callbackCalled, "the callback was called"); + assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); + assert.deepEqual(receivedBounds.bottomRight, endPoint, "bottom-right point was set correctly"); + dbl.offDragEnd(callback); + callbackCalled = false; - let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); - assert.isTrue(callbackCalled, "the callback was called"); - assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); - assert.deepEqual(receivedBounds.bottomRight, endPoint, "bottom-right point was set correctly"); - dbl.offDragEnd(callback); - callbackCalled = false; + svg.remove(); + }); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); + it("multiple drag interaction callbacks", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dbl = new Plottable.Components.DragBoxLayer(); + dbl.renderTo(svg); - svg.remove(); - }); + let startPoint = { + x: SVG_WIDTH / 4, + y: SVG_HEIGHT / 4 + }; + let endPoint = { + x: SVG_WIDTH / 2, + y: SVG_HEIGHT / 2 + }; - it("multiple drag interaction callbacks", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); - let dbl = new Plottable.Components.DragBoxLayer(); - dbl.renderTo(svg); + let callbackDragStart1Called = false; + let callbackDragStart2Called = false; + let callbackDrag1Called = false; + let callbackDrag2Called = false; + let callbackDragEnd1Called = false; + let callbackDragEnd2Called = false; + + let callbackDragStart1 = () => callbackDragStart1Called = true; + let callbackDragStart2 = () => callbackDragStart2Called = true; + let callbackDrag1 = () => callbackDrag1Called = true; + let callbackDrag2 = () => callbackDrag2Called = true; + let callbackDragEnd1 = () => callbackDragEnd1Called = true; + let callbackDragEnd2 = () => callbackDragEnd2Called = true; + + dbl.onDragStart(callbackDragStart1); + dbl.onDragStart(callbackDragStart2); + dbl.onDrag(callbackDrag1); + dbl.onDrag(callbackDrag2); + dbl.onDragEnd(callbackDragEnd1); + dbl.onDragEnd(callbackDragEnd2); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; + let target = dbl.background(); + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + + assert.isTrue(callbackDragStart1Called, "the callback 1 for drag start was called"); + assert.isTrue(callbackDragStart2Called, "the callback 2 for drag start was called"); + assert.isTrue(callbackDrag1Called, "the callback 1 for drag was called"); + assert.isTrue(callbackDrag2Called, "the callback 2 for drag was called"); + assert.isTrue(callbackDragEnd1Called, "the callback 1 for drag end was called"); + assert.isTrue(callbackDragEnd2Called, "the callback 2 for drag end was called"); + + dbl.offDragStart(callbackDragStart1); + dbl.offDrag(callbackDrag1); + dbl.offDragEnd(callbackDragEnd1); + + callbackDragStart1Called = false; + callbackDragStart2Called = false; + callbackDrag1Called = false; + callbackDrag2Called = false; + callbackDragEnd1Called = false; + callbackDragEnd2Called = false; + + TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + assert.isFalse(callbackDragStart1Called, "the callback 1 for drag start was disconnected"); + assert.isTrue(callbackDragStart2Called, "the callback 2 for drag start is still connected"); + assert.isFalse(callbackDrag1Called, "the callback 1 for drag was called disconnected"); + assert.isTrue(callbackDrag2Called, "the callback 2 for drag is still connected"); + assert.isFalse(callbackDragEnd1Called, "the callback 1 for drag end was disconnected"); + assert.isTrue(callbackDragEnd2Called, "the callback 2 for drag end is still connected"); - let callbackDragStart1Called = false; - let callbackDragStart2Called = false; - let callbackDrag1Called = false; - let callbackDrag2Called = false; - let callbackDragEnd1Called = false; - let callbackDragEnd2Called = false; - - let callbackDragStart1 = () => callbackDragStart1Called = true; - let callbackDragStart2 = () => callbackDragStart2Called = true; - let callbackDrag1 = () => callbackDrag1Called = true; - let callbackDrag2 = () => callbackDrag2Called = true; - let callbackDragEnd1 = () => callbackDragEnd1Called = true; - let callbackDragEnd2 = () => callbackDragEnd2Called = true; - - dbl.onDragStart(callbackDragStart1); - dbl.onDragStart(callbackDragStart2); - dbl.onDrag(callbackDrag1); - dbl.onDrag(callbackDrag2); - dbl.onDragEnd(callbackDragEnd1); - dbl.onDragEnd(callbackDragEnd2); - - let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - - assert.isTrue(callbackDragStart1Called, "the callback 1 for drag start was called"); - assert.isTrue(callbackDragStart2Called, "the callback 2 for drag start was called"); - assert.isTrue(callbackDrag1Called, "the callback 1 for drag was called"); - assert.isTrue(callbackDrag2Called, "the callback 2 for drag was called"); - assert.isTrue(callbackDragEnd1Called, "the callback 1 for drag end was called"); - assert.isTrue(callbackDragEnd2Called, "the callback 2 for drag end was called"); - - dbl.offDragStart(callbackDragStart1); - dbl.offDrag(callbackDrag1); - dbl.offDragEnd(callbackDragEnd1); - - callbackDragStart1Called = false; - callbackDragStart2Called = false; - callbackDrag1Called = false; - callbackDrag2Called = false; - callbackDragEnd1Called = false; - callbackDragEnd2Called = false; - - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); - assert.isFalse(callbackDragStart1Called, "the callback 1 for drag start was disconnected"); - assert.isTrue(callbackDragStart2Called, "the callback 2 for drag start is still connected"); - assert.isFalse(callbackDrag1Called, "the callback 1 for drag was called disconnected"); - assert.isTrue(callbackDrag2Called, "the callback 2 for drag is still connected"); - assert.isFalse(callbackDragEnd1Called, "the callback 1 for drag end was disconnected"); - assert.isTrue(callbackDragEnd2Called, "the callback 2 for drag end is still connected"); - - svg.remove(); + svg.remove(); + }); }); + describe("enabling/disabling", () => { + + let SVG_WIDTH = 400; + let SVG_HEIGHT = 400; + it("enabled(boolean) properly modifies the state", () => { let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); @@ -329,6 +337,10 @@ describe("Interactive Components", () => { }); describe("resizing", () => { + + let SVG_WIDTH = 400; + let SVG_HEIGHT = 400; + let svg: d3.Selection; let dbl: Plottable.Components.DragBoxLayer; let target: d3.Selection; @@ -519,6 +531,10 @@ describe("Interactive Components", () => { }); describe("moving", () => { + + let SVG_WIDTH = 400; + let SVG_HEIGHT = 400; + let svg: d3.Selection; let dbl: Plottable.Components.DragBoxLayer; let target: d3.Selection; From eef4d56636f679bc8481ca8d722b3ec89ced5185 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 15:19:32 -0700 Subject: [PATCH 024/160] [refactorLayers] added afterEach clauses --- test/components/dragBoxLayerTests.ts | 84 ++++++++++------------------ 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 773436f682..40b62c6e3f 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -7,8 +7,17 @@ describe("Interactive Components", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; + var svg: d3.Selection; + + beforeEach(() => { + svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + }); + + afterEach(() => { + svg.remove(); + }); + it("correctly draws box on drag", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); assert.isFalse(dbl.boxVisible(), "box is hidden initially"); @@ -28,12 +37,9 @@ describe("Interactive Components", () => { let bounds = dbl.bounds(); assert.deepEqual(bounds.topLeft, startPoint, "top-left point was set correctly"); assert.deepEqual(bounds.bottomRight, endPoint, "bottom-right point was set correctly"); - - svg.remove(); }); it("dismisses on click", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); @@ -46,19 +52,15 @@ describe("Interactive Components", () => { TestMethods.triggerFakeDragSequence(target, targetPoint, targetPoint); assert.isFalse(dbl.boxVisible(), "box is hidden on click"); - - svg.remove(); }); it("clipPath enabled", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); TestMethods.verifyClipPath(dbl); let clipRect = ( dbl)._boxContainer.select(".clip-rect"); assert.strictEqual(TestMethods.numAttr(clipRect, "width"), SVG_WIDTH, "the clipRect has an appropriate width"); assert.strictEqual(TestMethods.numAttr(clipRect, "height"), SVG_HEIGHT, "the clipRect has an appropriate height"); - svg.remove(); }); it("detectionRadius()", () => { @@ -66,7 +68,6 @@ describe("Interactive Components", () => { assert.doesNotThrow(() => dbl.detectionRadius(3), Error, "can set detection radius before anchoring"); - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); dbl.renderTo("svg"); let radius = 5; @@ -85,12 +86,9 @@ describe("Interactive Components", () => { // HACKHACK: chai-assert.d.ts has the wrong signature ( assert.throws)(() => dbl.detectionRadius(-1), Error, "", "rejects negative values"); - - svg.remove(); }); it("onDragStart()", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); @@ -123,12 +121,9 @@ describe("Interactive Components", () => { callbackCalled = false; TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragBoxLayer and not called"); - - svg.remove(); }); it("onDrag()", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); @@ -161,12 +156,9 @@ describe("Interactive Components", () => { TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); - - svg.remove(); }); it("onDragEnd()", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); @@ -198,12 +190,9 @@ describe("Interactive Components", () => { TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); - - svg.remove(); }); it("multiple drag interaction callbacks", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); @@ -265,28 +254,32 @@ describe("Interactive Components", () => { assert.isTrue(callbackDrag2Called, "the callback 2 for drag is still connected"); assert.isFalse(callbackDragEnd1Called, "the callback 1 for drag end was disconnected"); assert.isTrue(callbackDragEnd2Called, "the callback 2 for drag end is still connected"); - - svg.remove(); }); }); - describe("enabling/disabling", () => { - + describe("DragBoxLayer - enabling/disabling", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; + var svg: d3.Selection; + + beforeEach(() => { + svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + }); + + afterEach(() => { + svg.remove(); + }); + it("enabled(boolean) properly modifies the state", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); assert.isTrue(dbl.enabled(), "drag box layer is enabled by default"); assert.strictEqual(dbl.enabled(false), dbl, "enabled(boolean) returns itself"); assert.isFalse(dbl.enabled(), "drag box layer reports when it is disabled"); - svg.remove(); }); it("disables box when enabled(false)", () => { - let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dbl = new Plottable.Components.DragBoxLayer(); dbl.enabled(false); dbl.renderTo(svg); @@ -307,7 +300,6 @@ describe("Interactive Components", () => { dbl.enabled(true); TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); assert.isTrue(dbl.boxVisible(), "box is shown when enabled"); - svg.remove(); }); it("does not have resizable CSS classes when enabled(false)", () => { @@ -336,7 +328,7 @@ describe("Interactive Components", () => { }); }); - describe("resizing", () => { + describe("DragBoxLayer - resizing", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; @@ -371,11 +363,14 @@ describe("Interactive Components", () => { resetBox(); }); + afterEach(() => { + svg.remove(); + }); + it("resizable() getter/setter", () => { assert.isFalse(dbl.resizable(), "defaults to false"); assert.strictEqual(dbl.resizable(true), dbl, "returns DragBoxLayer when invoked as setter"); assert.isTrue(dbl.resizable(), "successfully set to true"); - svg.remove(); }); it("resizable() correctly sets pointer-events", () => { @@ -390,7 +385,6 @@ describe("Interactive Components", () => { let computedStyle = window.getComputedStyle( corner); assert.strictEqual(computedStyle.pointerEvents.toLowerCase(), "visiblefill", "pointer-events set correctly on corners"); }); - svg.remove(); }); it("resize from top edge", () => { @@ -412,7 +406,6 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.bottomRight.y, SVG_HEIGHT, "can drag through to other side"); - svg.remove(); }); it("resize from bottom edge", () => { @@ -434,7 +427,6 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.y, 0, "can drag through to other side"); - svg.remove(); }); it("resize from left edge", () => { @@ -456,7 +448,6 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.bottomRight.x, SVG_WIDTH, "can drag through to other side"); - svg.remove(); }); it("resize from right edge", () => { @@ -478,7 +469,6 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.x, 0, "can drag through to other side"); - svg.remove(); }); it("resizes if grabbed within detectionRadius()", () => { @@ -502,8 +492,6 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.y, startYOutside, "new box was started at the drag start position"); - - svg.remove(); }); it("doesn't dismiss on no-op resize", () => { @@ -525,12 +513,10 @@ describe("Interactive Components", () => { ); let bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.y, initialBounds.bottomRight.y, "new box was started at the drag start position"); - - svg.remove(); }); }); - describe("moving", () => { + describe("DragBoxLayer - moving", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; @@ -559,13 +545,16 @@ describe("Interactive Components", () => { initialBounds = dbl.bounds(); }); + afterEach(() => { + svg.remove(); + }); + it("get and set movable()", () => { assert.isFalse(dbl.movable(), "defaults to false"); assert.isFalse(dbl.hasClass("movable"), "initially does not have \"movable\" CSS class"); assert.strictEqual(dbl.movable(true), dbl, "setter mode returns DragBoxLayer"); assert.isTrue(dbl.movable(), "set to true"); assert.isTrue(dbl.hasClass("movable"), "\"movable\" CSS class is applied"); - svg.remove(); }); it("move left", () => { @@ -579,7 +568,6 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.x, initialBounds.bottomRight.x - dragDistance, "right edge moved"); assert.strictEqual(bounds.topLeft.y, initialBounds.topLeft.y, "top edge did not move"); assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y, "bottom edge did not move"); - svg.remove(); }); it("move right", () => { @@ -593,7 +581,6 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.x, initialBounds.bottomRight.x + dragDistance, "right edge moved"); assert.strictEqual(bounds.topLeft.y, initialBounds.topLeft.y, "top edge did not move"); assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y, "bottom edge did not move"); - svg.remove(); }); it("move up", () => { @@ -607,7 +594,6 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.x, initialBounds.bottomRight.x, "right edge did not move"); assert.strictEqual(bounds.topLeft.y, initialBounds.topLeft.y - dragDistance, "top edge moved"); assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y - dragDistance, "bottom edge moved"); - svg.remove(); }); it("move down", () => { @@ -621,7 +607,6 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.x, initialBounds.bottomRight.x, "right edge did not move"); assert.strictEqual(bounds.topLeft.y, initialBounds.topLeft.y + dragDistance, "top edge moved"); assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y + dragDistance, "bottom edge moved"); - svg.remove(); }); it("does not move if grabbed within detectionRadius() while resizable()", () => { @@ -636,7 +621,6 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y, "bottom edge was not moved"); assert.strictEqual(bounds.topLeft.x, initialBounds.topLeft.x, "left edge was not moved"); assert.strictEqual(bounds.bottomRight.x, SVG_WIDTH, "right edge was repositioned"); - svg.remove(); }); it("doesn't dismiss on no-op move", () => { @@ -648,7 +632,6 @@ describe("Interactive Components", () => { assert.isTrue(dbl.boxVisible(), "box remains visible"); let bounds = dbl.bounds(); assert.deepEqual(bounds, initialBounds, "bounds did not change"); - svg.remove(); }); it("dismisses on click outside of box", () => { @@ -656,7 +639,6 @@ describe("Interactive Components", () => { let origin = { x: 0, y: 0 }; TestMethods.triggerFakeDragSequence(target, origin, origin); assert.isFalse(dbl.boxVisible(), "box is no longer visible"); - svg.remove(); }); it("starts new box if hidden instead of moving", () => { @@ -669,16 +651,12 @@ describe("Interactive Components", () => { let bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.x, midPoint.x, "new box was started at the drag start position (x)"); assert.strictEqual(bounds.topLeft.y, midPoint.y, "new box was started at the drag start position (y)"); - - svg.remove(); }); it("destroy() does not error if scales are not inputted", () => { let sbl = new Plottable.Components.DragBoxLayer(); sbl.renderTo(svg); assert.doesNotThrow(() => sbl.destroy(), Error, "can destroy"); - - svg.remove(); }); }); }); From fac4ae16142330ccd46aae7fdb6f865da6a2ab7b Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 15:21:41 -0700 Subject: [PATCH 025/160] [refactorLayers] dbl is instantiated in the beforeEach --- test/components/dragBoxLayerTests.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 40b62c6e3f..66d5f77007 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -8,9 +8,11 @@ describe("Interactive Components", () => { let SVG_HEIGHT = 400; var svg: d3.Selection; + let dbl: Plottable.Components.DragBoxLayer; beforeEach(() => { svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + dbl = new Plottable.Components.DragBoxLayer(); }); afterEach(() => { @@ -18,7 +20,6 @@ describe("Interactive Components", () => { }); it("correctly draws box on drag", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); assert.isFalse(dbl.boxVisible(), "box is hidden initially"); @@ -40,7 +41,6 @@ describe("Interactive Components", () => { }); it("dismisses on click", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); let targetPoint = { @@ -55,8 +55,8 @@ describe("Interactive Components", () => { }); it("clipPath enabled", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); + TestMethods.verifyClipPath(dbl); let clipRect = ( dbl)._boxContainer.select(".clip-rect"); assert.strictEqual(TestMethods.numAttr(clipRect, "width"), SVG_WIDTH, "the clipRect has an appropriate width"); @@ -64,10 +64,7 @@ describe("Interactive Components", () => { }); it("detectionRadius()", () => { - let dbl = new Plottable.Components.DragBoxLayer(); - assert.doesNotThrow(() => dbl.detectionRadius(3), Error, "can set detection radius before anchoring"); - dbl.renderTo("svg"); let radius = 5; @@ -89,7 +86,6 @@ describe("Interactive Components", () => { }); it("onDragStart()", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); let startPoint = { @@ -124,7 +120,6 @@ describe("Interactive Components", () => { }); it("onDrag()", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); let startPoint = { @@ -159,7 +154,6 @@ describe("Interactive Components", () => { }); it("onDragEnd()", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); let startPoint = { @@ -193,7 +187,6 @@ describe("Interactive Components", () => { }); it("multiple drag interaction callbacks", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.renderTo(svg); let startPoint = { @@ -257,7 +250,6 @@ describe("Interactive Components", () => { }); }); - describe("DragBoxLayer - enabling/disabling", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; From 0065256cc8699f56dff1e87fc89ec98221eaeeb9 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 15:27:09 -0700 Subject: [PATCH 026/160] [refactorLayers] Extracted common points --- test/components/dragBoxLayerTests.ts | 100 +++++++++------------------ 1 file changed, 31 insertions(+), 69 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 66d5f77007..35437fabcc 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -7,12 +7,24 @@ describe("Interactive Components", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; - var svg: d3.Selection; + let svg: d3.Selection; let dbl: Plottable.Components.DragBoxLayer; + let quarterPoint: Plottable.Point; + let halfPoint: Plottable.Point; beforeEach(() => { svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); dbl = new Plottable.Components.DragBoxLayer(); + + quarterPoint = { + x: SVG_WIDTH / 4, + y: SVG_HEIGHT / 4 + }; + halfPoint = { + x: SVG_WIDTH / 2, + y: SVG_HEIGHT / 2 + }; + }); afterEach(() => { @@ -23,33 +35,19 @@ describe("Interactive Components", () => { dbl.renderTo(svg); assert.isFalse(dbl.boxVisible(), "box is hidden initially"); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; - let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isTrue(dbl.boxVisible(), "box is drawn on drag"); let bounds = dbl.bounds(); - assert.deepEqual(bounds.topLeft, startPoint, "top-left point was set correctly"); - assert.deepEqual(bounds.bottomRight, endPoint, "bottom-right point was set correctly"); + assert.deepEqual(bounds.topLeft, quarterPoint, "top-left point was set correctly"); + assert.deepEqual(bounds.bottomRight, halfPoint, "bottom-right point was set correctly"); }); it("dismisses on click", () => { dbl.renderTo(svg); - let targetPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; - let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, targetPoint, targetPoint); + TestMethods.triggerFakeDragSequence(target, halfPoint, halfPoint); assert.isFalse(dbl.boxVisible(), "box is hidden on click"); }); @@ -88,15 +86,6 @@ describe("Interactive Components", () => { it("onDragStart()", () => { dbl.renderTo(svg); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; - let receivedBounds: Plottable.Bounds; let callbackCalled = false; let callback = (b: Plottable.Bounds) => { @@ -106,31 +95,22 @@ describe("Interactive Components", () => { dbl.onDragStart(callback); let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isTrue(callbackCalled, "the callback was called"); - assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); - assert.deepEqual(receivedBounds.bottomRight, startPoint, "bottom-right point was set correctly"); + assert.deepEqual(receivedBounds.topLeft, quarterPoint, "top-left point was set correctly"); + assert.deepEqual(receivedBounds.bottomRight, quarterPoint, "bottom-right point was set correctly"); dbl.offDragStart(callback); callbackCalled = false; - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragBoxLayer and not called"); }); it("onDrag()", () => { dbl.renderTo(svg); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; - let receivedBounds: Plottable.Bounds; let callbackCalled = false; let callback = (b: Plottable.Bounds) => { @@ -140,31 +120,22 @@ describe("Interactive Components", () => { dbl.onDrag(callback); let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isTrue(callbackCalled, "the callback was called"); - assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); - assert.deepEqual(receivedBounds.bottomRight, endPoint, "bottom-right point was set correctly"); + assert.deepEqual(receivedBounds.topLeft, quarterPoint, "top-left point was set correctly"); + assert.deepEqual(receivedBounds.bottomRight, halfPoint, "bottom-right point was set correctly"); callbackCalled = false; dbl.offDrag(callback); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); }); it("onDragEnd()", () => { dbl.renderTo(svg); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; - let receivedBounds: Plottable.Bounds; let callbackCalled = false; let callback = (b: Plottable.Bounds) => { @@ -174,30 +145,21 @@ describe("Interactive Components", () => { dbl.onDragEnd(callback); let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isTrue(callbackCalled, "the callback was called"); - assert.deepEqual(receivedBounds.topLeft, startPoint, "top-left point was set correctly"); - assert.deepEqual(receivedBounds.bottomRight, endPoint, "bottom-right point was set correctly"); + assert.deepEqual(receivedBounds.topLeft, quarterPoint, "top-left point was set correctly"); + assert.deepEqual(receivedBounds.bottomRight, halfPoint, "bottom-right point was set correctly"); dbl.offDragEnd(callback); callbackCalled = false; - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); }); it("multiple drag interaction callbacks", () => { dbl.renderTo(svg); - let startPoint = { - x: SVG_WIDTH / 4, - y: SVG_HEIGHT / 4 - }; - let endPoint = { - x: SVG_WIDTH / 2, - y: SVG_HEIGHT / 2 - }; - let callbackDragStart1Called = false; let callbackDragStart2Called = false; let callbackDrag1Called = false; @@ -220,7 +182,7 @@ describe("Interactive Components", () => { dbl.onDragEnd(callbackDragEnd2); let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isTrue(callbackDragStart1Called, "the callback 1 for drag start was called"); assert.isTrue(callbackDragStart2Called, "the callback 2 for drag start was called"); @@ -240,7 +202,7 @@ describe("Interactive Components", () => { callbackDragEnd1Called = false; callbackDragEnd2Called = false; - TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isFalse(callbackDragStart1Called, "the callback 1 for drag start was disconnected"); assert.isTrue(callbackDragStart2Called, "the callback 2 for drag start is still connected"); assert.isFalse(callbackDrag1Called, "the callback 1 for drag was called disconnected"); From 0ab67863b206364a32a9df1395d16904ef44334f Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 15:29:03 -0700 Subject: [PATCH 027/160] [refactorLayers] Finished the basic dragBoxLayer refactor --- test/components/dragBoxLayerTests.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 35437fabcc..a5439ff906 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -15,7 +15,6 @@ describe("Interactive Components", () => { beforeEach(() => { svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); dbl = new Plottable.Components.DragBoxLayer(); - quarterPoint = { x: SVG_WIDTH / 4, y: SVG_HEIGHT / 4 @@ -24,7 +23,6 @@ describe("Interactive Components", () => { x: SVG_WIDTH / 2, y: SVG_HEIGHT / 2 }; - }); afterEach(() => { From 40bf16a029bff1af7c09f6d7cb6898bc7ac84679 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 15:30:17 -0700 Subject: [PATCH 028/160] [refactorLayers] factored common code out for dragbox layer enable / disable --- test/components/dragBoxLayerTests.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index a5439ff906..522d6a16cb 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -215,9 +215,11 @@ describe("Interactive Components", () => { let SVG_HEIGHT = 400; var svg: d3.Selection; + let dbl: Plottable.Components.DragBoxLayer; beforeEach(() => { svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + dbl = new Plottable.Components.DragBoxLayer(); }); afterEach(() => { @@ -225,14 +227,12 @@ describe("Interactive Components", () => { }); it("enabled(boolean) properly modifies the state", () => { - let dbl = new Plottable.Components.DragBoxLayer(); assert.isTrue(dbl.enabled(), "drag box layer is enabled by default"); assert.strictEqual(dbl.enabled(false), dbl, "enabled(boolean) returns itself"); assert.isFalse(dbl.enabled(), "drag box layer reports when it is disabled"); }); it("disables box when enabled(false)", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.enabled(false); dbl.renderTo(svg); assert.isFalse(dbl.boxVisible(), "box is hidden initially"); @@ -255,7 +255,6 @@ describe("Interactive Components", () => { }); it("does not have resizable CSS classes when enabled(false)", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.resizable(true); assert.isTrue(dbl.hasClass("x-resizable"), "carries \"x-resizable\" class if resizable"); assert.isTrue(dbl.hasClass("y-resizable"), "carries \"y-resizable\" class if resizable"); @@ -269,7 +268,6 @@ describe("Interactive Components", () => { }); it("does not have movable CSS classe when enabled(false)", () => { - let dbl = new Plottable.Components.DragBoxLayer(); dbl.movable(true); assert.isTrue(dbl.hasClass("movable"), "carries \"movable\" class if movable"); dbl.enabled(false); From aeb6901bfcfd28c03beb0c341207ac0250553eda Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 15:34:45 -0700 Subject: [PATCH 029/160] [refactorLayers] finished DragBoxLayer test refactor --- test/components/dragBoxLayerTests.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 522d6a16cb..384249a85e 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -81,6 +81,10 @@ describe("Interactive Components", () => { ( assert.throws)(() => dbl.detectionRadius(-1), Error, "", "rejects negative values"); }); + it("destroy() does not error if scales are not inputted", () => { + assert.doesNotThrow(() => dbl.destroy(), Error, "can destroy"); + }); + it("onDragStart()", () => { dbl.renderTo(svg); @@ -279,7 +283,6 @@ describe("Interactive Components", () => { }); describe("DragBoxLayer - resizing", () => { - let SVG_WIDTH = 400; let SVG_HEIGHT = 400; @@ -295,7 +298,7 @@ describe("Interactive Components", () => { function resetBox() { dbl.bounds({ topLeft: { x: 0, y: 0 }, - bottomRight: { x: 0, y: 0} + bottomRight: { x: 0, y: 0 } }); TestMethods.triggerFakeDragSequence(target, { x: SVG_WIDTH / 4, y: SVG_HEIGHT / 4}, @@ -467,7 +470,6 @@ describe("Interactive Components", () => { }); describe("DragBoxLayer - moving", () => { - let SVG_WIDTH = 400; let SVG_HEIGHT = 400; @@ -602,12 +604,6 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.topLeft.x, midPoint.x, "new box was started at the drag start position (x)"); assert.strictEqual(bounds.topLeft.y, midPoint.y, "new box was started at the drag start position (y)"); }); - - it("destroy() does not error if scales are not inputted", () => { - let sbl = new Plottable.Components.DragBoxLayer(); - sbl.renderTo(svg); - assert.doesNotThrow(() => sbl.destroy(), Error, "can destroy"); - }); }); }); }); From 1da5d02702e2d349cab4b2d1af7fb7faf1e756c9 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 15:36:31 -0700 Subject: [PATCH 030/160] [refactorDragBoxLayer] Finished DragBoxLayer refactor pass1 --- test/components/dragBoxLayerTests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 384249a85e..f51bf14ff8 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -218,7 +218,7 @@ describe("Interactive Components", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; - var svg: d3.Selection; + let svg: d3.Selection; let dbl: Plottable.Components.DragBoxLayer; beforeEach(() => { From 4997127aa9e54eb7e7bb3975fadf28d60f87f768 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 16:01:25 -0700 Subject: [PATCH 031/160] [refactorSegment] CR patch 1 --- test/plots/segmentPlotTests.ts | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index 5bc8d3f585..dfae75c274 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -3,7 +3,7 @@ describe("Plots", () => { describe("SegmentPlot", () => { - describe("SegmentPlot - basics", () => { + describe("Basics", () => { let svg: d3.Selection; let xScale: Plottable.Scales.Linear; let yScale: Plottable.Scales.Linear; @@ -32,12 +32,13 @@ describe("Plots", () => { plot.y2((d) => d.y2); plot.addDataset(new Plottable.Dataset([data[0]])); plot.renderTo(svg); - renderArea = ( plot)._renderArea; - let lineSelection = d3.select(renderArea.selectAll("line")[0][0]); - assert.strictEqual(+lineSelection.attr("x1"), 62.5, "x1 is correct"); - assert.strictEqual(+lineSelection.attr("x2"), 437.5, "x2 is correct"); - assert.strictEqual(+lineSelection.attr("y1"), 437.5, "y1 is correct"); - assert.strictEqual(+lineSelection.attr("y2"), 62.5, "y2 is correct"); + + let line = plot.content().selectAll("line"); + assert.strictEqual(line.size(), 1, "exactly one line has been rendered"); + assert.strictEqual(+line.attr("x1"), 62.5, "x1 is correct"); + assert.strictEqual(+line.attr("x2"), 437.5, "x2 is correct"); + assert.strictEqual(+line.attr("y1"), 437.5, "y1 is correct"); + assert.strictEqual(+line.attr("y2"), 62.5, "y2 is correct"); }); it("renders vertical lines when x2 is not set", () => { @@ -47,8 +48,8 @@ describe("Plots", () => { plot.y2((d) => d.y2); plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); - renderArea = ( plot)._renderArea; - renderArea.selectAll("line")[0].forEach((line) => { + + plot.content().selectAll("line")[0].forEach((line) => { let lineSelection = d3.select(line); assert.strictEqual(lineSelection.attr("x1"), lineSelection.attr("x2"), "line is vertical"); }); @@ -61,8 +62,8 @@ describe("Plots", () => { plot.y((d) => d.y, yScale); plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); - renderArea = ( plot)._renderArea; - renderArea.selectAll("line")[0].forEach((line) => { + + plot.content().selectAll("line")[0].forEach((line) => { let lineSelection = d3.select(line); assert.strictEqual(lineSelection.attr("y1"), lineSelection.attr("y2"), "line is horizontal"); }); @@ -84,13 +85,13 @@ describe("Plots", () => { plot.renderTo(svg); - assert.deepEqual(xScale.domain(), [0, 2], "y domain includes both visible segments"); + assert.deepEqual(xScale.domain(), [0, 2], "x domain includes both visible segments"); yScale.domain([-0.5, 0.5]); - assert.deepEqual(xScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); + assert.deepEqual(xScale.domain(), [0, 1], "x domain includes only the visible segment (first)"); yScale.domain([0.5, 1.5]); - assert.deepEqual(xScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); + assert.deepEqual(xScale.domain(), [1, 2], "x domain includes only the visible segment (second)"); }); it("autorangeMode(\"y\")", () => { @@ -119,7 +120,7 @@ describe("Plots", () => { }); }); - describe("SegmentPlot - entitiesIn()", () => { + describe("entitiesIn()", () => { let data = [ { x: 1, x2: 1, y: 1, y2: 4 }, { x: 2, x2: 3, y: 4, y2: 3 }, From 5fdd902d0cc5cf5b30d635e59f7f58e978ab8324 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 16:02:19 -0700 Subject: [PATCH 032/160] [refactorSegment] tslint --- test/plots/segmentPlotTests.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index dfae75c274..84a56d9a70 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -7,7 +7,6 @@ describe("Plots", () => { let svg: d3.Selection; let xScale: Plottable.Scales.Linear; let yScale: Plottable.Scales.Linear; - let renderArea: d3.Selection; let data = [ { x: 1, y: 1, x2: 4, y2: 4 }, { x: 2, y: 2, x2: 3, y2: 5 }, From 6162ebfe6e9185311c40e1e6dac6621290e8ad8e Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 16:21:55 -0700 Subject: [PATCH 033/160] [refactorSegment] The SVG is removed inside each test --- test/plots/segmentPlotTests.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index 84a56d9a70..f1c9d0effc 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -19,10 +19,6 @@ describe("Plots", () => { yScale = new Plottable.Scales.Linear(); }); - afterEach(() => { - svg.remove(); - }); - it("renders a line properly", () => { let plot = new Plottable.Plots.Segment(); plot.x((d) => d.x, xScale); @@ -38,6 +34,7 @@ describe("Plots", () => { assert.strictEqual(+line.attr("x2"), 437.5, "x2 is correct"); assert.strictEqual(+line.attr("y1"), 437.5, "y1 is correct"); assert.strictEqual(+line.attr("y2"), 62.5, "y2 is correct"); + svg.remove(); }); it("renders vertical lines when x2 is not set", () => { @@ -52,6 +49,7 @@ describe("Plots", () => { let lineSelection = d3.select(line); assert.strictEqual(lineSelection.attr("x1"), lineSelection.attr("x2"), "line is vertical"); }); + svg.remove(); }); it("renders horizontal lines when y2 is not set", () => { @@ -66,6 +64,7 @@ describe("Plots", () => { let lineSelection = d3.select(line); assert.strictEqual(lineSelection.attr("y1"), lineSelection.attr("y2"), "line is horizontal"); }); + svg.remove(); }); it("autorangeMode(\"x\")", () => { @@ -91,6 +90,7 @@ describe("Plots", () => { yScale.domain([0.5, 1.5]); assert.deepEqual(xScale.domain(), [1, 2], "x domain includes only the visible segment (second)"); + svg.remove(); }); it("autorangeMode(\"y\")", () => { @@ -116,6 +116,7 @@ describe("Plots", () => { xScale.domain([0.5, 1.5]); assert.deepEqual(yScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); + svg.remove(); }); }); @@ -141,10 +142,6 @@ describe("Plots", () => { plot.addDataset(new Plottable.Dataset(data)).renderTo(svg); }); - afterEach(() => { - svg.remove(); - }); - it("retrieves the entities that intersect with the bounding box", () => { let entities = plot.entitiesIn({ topLeft: { x: xScale.scale(0), y: yScale.scale(4.5) }, @@ -152,6 +149,7 @@ describe("Plots", () => { assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); assert.strictEqual(entities[0].index, 0, "the entity of index 0 is retrieved"); assert.strictEqual(entities[1].index, 1, "the entity of index 1 is retrieved"); + svg.remove(); }); it("retrieves the entities that intersect with given ranges", () => { @@ -161,6 +159,7 @@ describe("Plots", () => { assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the ranges"); assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); + svg.remove(); }); it("retrieves the entity if exactly one of its endpoints is in the ranges", () => { @@ -179,6 +178,7 @@ describe("Plots", () => { // horizontal segment checkEntitiesInRange(plot, 3, 1.5, 2.5, 1.5, 0.5); checkEntitiesInRange(plot, 3, 3.5, 4.5, 1.5, 0.5); + svg.remove(); }); it("retrieves the entity if both of its endpoints are in the ranges", () => { @@ -193,6 +193,7 @@ describe("Plots", () => { // horizontal segment checkEntitiesInRange(plot, 3, 1.5, 4.5, 1.5, 0.5); + svg.remove(); }); it("retrieves the entity if it intersects with the ranges with no endpoints inside", () => { @@ -207,6 +208,7 @@ describe("Plots", () => { // horizontal segment checkEntitiesInRange(plot, 3, 2.5, 3.5, 1.5, 0.5); + svg.remove(); }); it("returns empty array when no entities intersect with the ranges", () => { @@ -214,6 +216,7 @@ describe("Plots", () => { { min: xScale.scale(1.5), max: xScale.scale(2.5) }, { min: yScale.scale(2.5), max: yScale.scale(1.5) }); assert.lengthOf(entities, 0, "no entities intersects with the ranges"); + svg.remove(); }); function checkEntitiesInRange(plot: Plottable.Plots.Segment, index: number, From 16a8e05764c47fc9e6a0fde5afc974f880ab7a99 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 16:24:19 -0700 Subject: [PATCH 034/160] [refactorSegment] Nice d3 iteration now --- test/plots/segmentPlotTests.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index f1c9d0effc..6df333c071 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -45,8 +45,8 @@ describe("Plots", () => { plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); - plot.content().selectAll("line")[0].forEach((line) => { - let lineSelection = d3.select(line); + plot.content().selectAll("line").each(function() { + let lineSelection = d3.select(this); assert.strictEqual(lineSelection.attr("x1"), lineSelection.attr("x2"), "line is vertical"); }); svg.remove(); @@ -60,8 +60,8 @@ describe("Plots", () => { plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); - plot.content().selectAll("line")[0].forEach((line) => { - let lineSelection = d3.select(line); + plot.content().selectAll("line").each(function() { + let lineSelection = d3.select(this); assert.strictEqual(lineSelection.attr("y1"), lineSelection.attr("y2"), "line is horizontal"); }); svg.remove(); From a327445b7cc796cb10a0cec7904519003f572c23 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 17:02:34 -0700 Subject: [PATCH 035/160] [refactorRectangle] CR patch 1 --- test/plots/rectanglePlotTests.ts | 98 +++++++++++++++----------------- 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 3b0e71c0c4..21da7d285e 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -2,15 +2,15 @@ describe("Plots", () => { describe("RectanglePlot", () => { - describe("RectanglePlot - basics", () => { - let DATA = [ + describe("Basic usage", () => { + let data = [ { x: 0, y: 0, x2: 1, y2: 1 }, { x: 1, y: 1, x2: 2, y2: 2 }, { x: 2, y: 2, x2: 3, y2: 3 }, { x: 3, y: 3, x2: 4, y2: 4 }, { x: 4, y: 4, x2: 5, y2: 5 } ]; - let VERIFY_CELLS = (cells: d3.Selection) => { + let verifyCells = (cells: d3.Selection) => { assert.strictEqual(cells[0].length, 5); cells.each(function(d, i) { let cell = d3.select(this); @@ -35,27 +35,25 @@ describe("Plots", () => { plot.y((d) => d.y, yScale).y2((d) => d.y2); }); - afterEach(() => { - svg.remove(); - }); - - it("renders correctly", () => { - plot.addDataset(new Plottable.Dataset(DATA)); + it("has correct rectangle heights and positions (renders correctly)", () => { + plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); - VERIFY_CELLS(( plot)._renderArea.selectAll("rect")); + verifyCells(plot.content().selectAll("rect")); + svg.remove(); }); it("retrieves the correct entity under a point", () => { - plot.addDataset(new Plottable.Dataset(DATA)); + plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) }); assert.lengthOf(entities, 1, "found only one entity when querying a point inside the third rectangle"); assert.strictEqual(entities[0].index, 2, "entity retrieved is at index 2"); + svg.remove(); }); - it("retrieves correct entities under a point", () => { + it("retrieves correct entities under a point when rectangles intersect", () => { let dataset = new Plottable.Dataset([ { x: 1, y: 1, x2: 3, y2: 3 }, { x: 4, y: 2, x2: 2, y2: 4 } @@ -73,10 +71,11 @@ describe("Plots", () => { entities = plot.entitiesAt({ x: xScale.scale(1), y: yScale.scale(1) }); assert.lengthOf(entities, 1, "found only one entity when querying a point inside the first rectangle"); assert.strictEqual(entities[0].index, 0, "entity retrieved is at index 0"); + svg.remove(); }); it("retrieves the entities that intersect with the bounding box", () => { - plot.addDataset(new Plottable.Dataset(DATA)); + plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); let entities = plot.entitiesIn({ @@ -85,10 +84,11 @@ describe("Plots", () => { assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); + svg.remove(); }); it("retrieves the entities that intersect with the given ranges", () => { - plot.addDataset(new Plottable.Dataset(DATA)); + plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); let entities = plot.entitiesIn( @@ -97,21 +97,18 @@ describe("Plots", () => { assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); + svg.remove(); }); }); - describe("RectanglePlot - autorangeMode()", () => { + describe("autorangeMode()", () => { let svg: d3.Selection; beforeEach(() => { svg = TestMethods.generateSVG(300, 300); }); - afterEach(() => { - svg.remove(); - }); - - it("autorangeMode(\"x\")", () => { + it("autorangeMode on x behaves as expected when changing the domain of the yScale", () => { let staggeredData = [ { y: "A", x: 0, x2: 1 }, { y: "B", x: 1, x2: 2 } @@ -129,17 +126,17 @@ describe("Plots", () => { plot.autorangeMode("x"); plot.renderTo(svg); - assert.deepEqual(xScale.domain(), [0, 2], "y domain includes both visible segments"); + assert.deepEqual(xScale.domain(), [0, 2], "x domain includes both visible segments"); yScale.domain(["A"]); - assert.deepEqual(xScale.domain(), [0, 1], "y domain includes only the visible segment (first)"); + assert.deepEqual(xScale.domain(), [0, 1], "x domain includes only the visible segment (first)"); yScale.domain(["B"]); - assert.deepEqual(xScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); - + assert.deepEqual(xScale.domain(), [1, 2], "x domain includes only the visible segment (second)"); + svg.remove(); }); - it("autorangeMode(\"y\")", () => { + it("autorangeMode on y behaves as expected when changing the domain of the xScale", () => { let staggeredData = [ { x: "A", y: 0, y2: 1 }, { x: "B", y: 1, y2: 2 } @@ -164,11 +161,11 @@ describe("Plots", () => { xScale.domain(["B"]); assert.deepEqual(yScale.domain(), [1, 2], "y domain includes only the visible segment (second)"); - + svg.remove(); }); }); - describe("RectanglePlot - fail safe tests", () => { + describe("Fail safe tests", () => { it("illegal rectangles don't get displayed", () => { let svg = TestMethods.generateSVG(); @@ -213,17 +210,17 @@ describe("Plots", () => { }); }); - describe("RectanglePlot - Grids", () => { + describe("Grids", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 200; - let DATA = [ + let data = [ {x: "A", y: "U", magnitude: 0}, {x: "B", y: "U", magnitude: 2}, {x: "A", y: "V", magnitude: 16}, {x: "B", y: "V", magnitude: 8}, ]; - let VERIFY_CELLS = (cells: any[]) => { + let verifyCells = (cells: any[]) => { assert.strictEqual(cells.length, 4); let cellAU = d3.select(cells[0]); @@ -269,18 +266,15 @@ describe("Plots", () => { colorScale.range(["black", "white"]); }); - afterEach(() => { - svg.remove(); - }); - it("renders correctly", () => { let plot = new Plottable.Plots.Rectangle(); - plot.addDataset(new Plottable.Dataset(DATA)); + plot.addDataset(new Plottable.Dataset(data)); plot.attr("fill", (d) => d.magnitude, colorScale); plot.x((d: any) => d.x, xScale); plot.y((d: any) => d.y, yScale); plot.renderTo(svg); - VERIFY_CELLS(( plot)._renderArea.selectAll("rect")[0]); + verifyCells(plot.content().selectAll("rect")[0]); + svg.remove(); }); it("renders correctly when data is set after construction", () => { @@ -291,8 +285,9 @@ describe("Plots", () => { plot.x((d: any) => d.x, xScale); plot.y((d: any) => d.y, yScale); plot.renderTo(svg); - dataset.data(DATA); - VERIFY_CELLS(( plot)._renderArea.selectAll("rect")[0]); + dataset.data(data); + verifyCells(plot.content().selectAll("rect")[0]); + svg.remove(); }); it("renders correctly when there isn't data for every spot", () => { @@ -312,7 +307,7 @@ describe("Plots", () => { {x: "D", y: "Z", magnitude: 24} ]; dataset.data(data); - let cells = ( plot)._renderArea.selectAll("rect")[0]; + let cells = plot.content().selectAll("rect")[0]; assert.strictEqual(cells.length, data.length); for (let i = 0; i < cells.length; i++) { let cell = d3.select(cells[i]); @@ -321,11 +316,12 @@ describe("Plots", () => { assert.strictEqual(cell.attr("width"), String(CELL_WIDTH), "Cell width is correct"); assert.strictEqual(cell.attr("height"), String(CELL_HEIGHT), "Cell height is correct"); } + svg.remove(); }); it("can invert y axis correctly", () => { let plot = new Plottable.Plots.Rectangle(); - plot.addDataset(new Plottable.Dataset(DATA)); + plot.addDataset(new Plottable.Dataset(data)); plot.attr("fill", (d) => d.magnitude, colorScale); plot.x((d: any) => d.x, xScale); plot.y((d: any) => d.y, yScale); @@ -333,7 +329,7 @@ describe("Plots", () => { yScale.domain(["U", "V"]); - let cells = ( plot)._renderArea.selectAll("rect")[0]; + let cells = plot.content().selectAll("rect")[0]; let cellAU = d3.select(cells[0]); let cellAV = d3.select(cells[2]); cellAU.attr("fill", "#000000"); @@ -345,7 +341,7 @@ describe("Plots", () => { cellAV.attr("y", "0"); yScale.domain(["V", "U"]); - cells = ( plot)._renderArea.selectAll("rect")[0]; + cells = plot.content().selectAll("rect")[0]; cellAU = d3.select(cells[0]); cellAV = d3.select(cells[2]); cellAU.attr("fill", "#000000"); @@ -355,13 +351,14 @@ describe("Plots", () => { cellAV.attr("fill", "#ffffff"); cellAV.attr("x", "0"); cellAV.attr("y", "100"); + svg.remove(); }); }); - describe("Rectangle Plot - selections()", () => { + describe("selections()", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 200; - let DATA = [ + let data = [ {x: "A", y: "U", magnitude: 0}, {x: "B", y: "U", magnitude: 2}, {x: "A", y: "V", magnitude: 16}, @@ -387,25 +384,23 @@ describe("Plots", () => { plot.x((d: any) => d.x, xScale); plot.y((d: any) => d.y, yScale); - dataset = new Plottable.Dataset(DATA); + dataset = new Plottable.Dataset(data); plot.addDataset(dataset); plot.renderTo(svg); }); - afterEach(() => { - svg.remove(); - }); - it("retrieves all selections with no args", () => { let allCells = plot.selections(); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); + svg.remove(); }); it("retrieves correct selections", () => { let allCells = plot.selections([dataset]); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); let selectionData = allCells.data(); - assert.includeMembers(selectionData, DATA, "data in selection data"); + assert.includeMembers(selectionData, data, "data in selection data"); + svg.remove(); }); it("skips invalid Datasets", () => { @@ -413,7 +408,8 @@ describe("Plots", () => { let allCells = plot.selections([dataset, dummyDataset]); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); let selectionData = allCells.data(); - assert.includeMembers(selectionData, DATA, "data in selection data"); + assert.includeMembers(selectionData, data, "data in selection data"); + svg.remove(); }); }); }); From 53e22c93c8b899f246b35d35ca606ba481d94f9e Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 17:07:39 -0700 Subject: [PATCH 036/160] [refactorRectangle] CR patch 2 --- test/plots/rectanglePlotTests.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 21da7d285e..fd4b884d44 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -109,7 +109,7 @@ describe("Plots", () => { }); it("autorangeMode on x behaves as expected when changing the domain of the yScale", () => { - let staggeredData = [ + let data = [ { y: "A", x: 0, x2: 1 }, { y: "B", x: 1, x2: 2 } ]; @@ -122,7 +122,7 @@ describe("Plots", () => { plot.x((d) => d.x, xScale); plot.x2((d) => d.x2); plot.y((d) => d.y, yScale); - plot.addDataset(new Plottable.Dataset(staggeredData)); + plot.addDataset(new Plottable.Dataset(data)); plot.autorangeMode("x"); plot.renderTo(svg); @@ -137,7 +137,7 @@ describe("Plots", () => { }); it("autorangeMode on y behaves as expected when changing the domain of the xScale", () => { - let staggeredData = [ + let data = [ { x: "A", y: 0, y2: 1 }, { x: "B", y: 1, y2: 2 } ]; @@ -150,7 +150,7 @@ describe("Plots", () => { plot.x((d) => d.x, xScale); plot.y((d) => d.y, yScale); plot.y2((d) => d.y2); - plot.addDataset(new Plottable.Dataset(staggeredData)); + plot.addDataset(new Plottable.Dataset(data)); plot.autorangeMode("y"); plot.renderTo(svg); @@ -166,7 +166,7 @@ describe("Plots", () => { }); describe("Fail safe tests", () => { - it("illegal rectangles don't get displayed", () => { + it("data points that are not valid, do not draw rectangles on the plot", () => { let svg = TestMethods.generateSVG(); let data1 = [ From 3159654a78a36c56875059bf7b45ef0179ffc852 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 17:17:51 -0700 Subject: [PATCH 037/160] [refactorRectangle] improved the semantics of the it() --- test/plots/rectanglePlotTests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index fd4b884d44..976cfd79ea 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -108,7 +108,7 @@ describe("Plots", () => { svg = TestMethods.generateSVG(300, 300); }); - it("autorangeMode on x behaves as expected when changing the domain of the yScale", () => { + it("adjusts the xScale domain with respect to the yScale domain when autorangeMode on x", () => { let data = [ { y: "A", x: 0, x2: 1 }, { y: "B", x: 1, x2: 2 } @@ -136,7 +136,7 @@ describe("Plots", () => { svg.remove(); }); - it("autorangeMode on y behaves as expected when changing the domain of the xScale", () => { + it("adjusts the yScale domain with respect to the xScale domain when autorangeMode on y", () => { let data = [ { x: "A", y: 0, y2: 1 }, { x: "B", y: 1, y2: 2 } @@ -166,7 +166,7 @@ describe("Plots", () => { }); describe("Fail safe tests", () => { - it("data points that are not valid, do not draw rectangles on the plot", () => { + it("does not draw rectangles for invalid data points", () => { let svg = TestMethods.generateSVG(); let data1 = [ From a1074f77f26d2f2ca984684e70563b63b44c4843 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 17:27:32 -0700 Subject: [PATCH 038/160] [refactorRectangle] Amended the merge to pass tests again --- test/plots/rectanglePlotTests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 9bdebd4373..ca60027b56 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -414,7 +414,7 @@ describe("Plots", () => { }); - describe("Rectangle Plot With Labels", () => { + describe("Labels", () => { let svg: d3.Selection; let rectanglePlot: Plottable.Plots.Rectangle; let DATA: [any]; @@ -424,7 +424,7 @@ describe("Plots", () => { beforeEach(() => { xScale = new Plottable.Scales.Linear(); yScale = new Plottable.Scales.Linear(); - svg = TestMethods.generateSVG(SVG_WIDTH / 2, SVG_HEIGHT); + svg = TestMethods.generateSVG(150, 300); rectanglePlot = new Plottable.Plots.Rectangle(); DATA = [ { x: 0, y: 0, x2: 1, y2: 1, val: "1" }, @@ -468,7 +468,7 @@ describe("Plots", () => { it("rectangle labels hide if rectangle is too short", () => { rectanglePlot.labelsEnabled(true); svg.remove(); - svg = TestMethods.generateSVG(SVG_WIDTH / 2, 30); + svg = TestMethods.generateSVG(150, 30); rectanglePlot.label((d: any) => d.val); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 0, "labels are not drawn when rectangles are too short"); From e17e5267ca03c17c25365da6ea91b81eb702cde9 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 17:38:42 -0700 Subject: [PATCH 039/160] [refactorRectangle] lower case for the data variable, plot name for the rectanglePlot --- test/plots/rectanglePlotTests.ts | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index ca60027b56..e56cd3cf30 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -416,8 +416,11 @@ describe("Plots", () => { describe("Labels", () => { let svg: d3.Selection; - let rectanglePlot: Plottable.Plots.Rectangle; - let DATA: [any]; + let plot: Plottable.Plots.Rectangle; + let data = [ + { x: 0, y: 0, x2: 1, y2: 1, val: "1" }, + { x: 0, y: 1, x2: 1, y2: 2, val: "2" } + ]; let dataset: Plottable.Dataset; let xScale: Plottable.Scales.Linear; let yScale: Plottable.Scales.Linear; @@ -425,14 +428,11 @@ describe("Plots", () => { xScale = new Plottable.Scales.Linear(); yScale = new Plottable.Scales.Linear(); svg = TestMethods.generateSVG(150, 300); - rectanglePlot = new Plottable.Plots.Rectangle(); - DATA = [ - { x: 0, y: 0, x2: 1, y2: 1, val: "1" }, - { x: 0, y: 1, x2: 1, y2: 2, val: "2" } - ]; - dataset = new Plottable.Dataset(DATA); - rectanglePlot.addDataset(dataset); - rectanglePlot.x((d: any) => d.x, xScale) + plot = new Plottable.Plots.Rectangle(); + data = ; + dataset = new Plottable.Dataset(data); + plot.addDataset(dataset); + plot.x((d: any) => d.x, xScale) .y((d: any) => d.y, yScale) .x2((d: any) => d.x2) .y2((d: any) => d.y2) @@ -447,18 +447,18 @@ describe("Plots", () => { }); it("rectangle labels render properly", () => { - rectanglePlot.labelsEnabled(true); + plot.labelsEnabled(true); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 2, "all labels are drawn"); texts.forEach((text, i) => { - assert.strictEqual(text, DATA[i].val, "label is drawn correctly"); + assert.strictEqual(text, data[i].val, "label is drawn correctly"); }); svg.remove(); }); it("rectangle labels hide if rectangle is too skinny", () => { - rectanglePlot.labelsEnabled(true); - rectanglePlot.label((d: any, i: number) => d.val + ( i !== 0 ? "a really really really long string" : "" )); + plot.labelsEnabled(true); + plot.label((d: any, i: number) => d.val + ( i !== 0 ? "a really really really long string" : "" )); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 1, "the second label is too long to be drawn"); assert.strictEqual(texts[0], "1"); @@ -466,17 +466,17 @@ describe("Plots", () => { }); it("rectangle labels hide if rectangle is too short", () => { - rectanglePlot.labelsEnabled(true); + plot.labelsEnabled(true); svg.remove(); svg = TestMethods.generateSVG(150, 30); - rectanglePlot.label((d: any) => d.val); + plot.label((d: any) => d.val); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 0, "labels are not drawn when rectangles are too short"); svg.remove(); }); it("rectangle labels are updated on dataset change", () => { - rectanglePlot.labelsEnabled(true); + plot.labelsEnabled(true); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 2, "all labels are drawn"); @@ -489,7 +489,7 @@ describe("Plots", () => { }); it("labels cut off by edges are not shown", () => { - rectanglePlot.labelsEnabled(true); + plot.labelsEnabled(true); let data = [ { x: 2, y: 2, x2: 3, y2: 3, val: "center" }, { x: 0.5, y: 2, x2: 1.5, y2: 3, val: "left" }, @@ -507,7 +507,7 @@ describe("Plots", () => { }); it("labels cut off by other rectangels are not shown", () => { - rectanglePlot.labelsEnabled(true); + plot.labelsEnabled(true); let data = [ { x: 0, y: 0, x2: 2, y2: 2, val: "bottom" }, { x: 1, y: 1, x2: 3, y2: 3, val: "middle" }]; @@ -519,7 +519,7 @@ describe("Plots", () => { assert.lengthOf(texts, 1, "1 label is drawn"); assert.strictEqual(texts[0], "middle"); - rectanglePlot.addDataset(new Plottable.Dataset(data2)); + plot.addDataset(new Plottable.Dataset(data2)); texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 2, "2 labels are drawn"); From b22472b751f275e62b29da1928dbbd5262d86018 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 17:42:34 -0700 Subject: [PATCH 040/160] [refactorRectangle] svg creation per test in Labels --- test/plots/rectanglePlotTests.ts | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index e56cd3cf30..52baee9a03 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -415,7 +415,6 @@ describe("Plots", () => { }); describe("Labels", () => { - let svg: d3.Selection; let plot: Plottable.Plots.Rectangle; let data = [ { x: 0, y: 0, x2: 1, y2: 1, val: "1" }, @@ -427,26 +426,27 @@ describe("Plots", () => { beforeEach(() => { xScale = new Plottable.Scales.Linear(); yScale = new Plottable.Scales.Linear(); - svg = TestMethods.generateSVG(150, 300); plot = new Plottable.Plots.Rectangle(); - data = ; dataset = new Plottable.Dataset(data); plot.addDataset(dataset); plot.x((d: any) => d.x, xScale) - .y((d: any) => d.y, yScale) - .x2((d: any) => d.x2) - .y2((d: any) => d.y2) - .label((d: any) => d.val) - .renderTo(svg); + .y((d: any) => d.y, yScale) + .x2((d: any) => d.x2) + .y2((d: any) => d.y2) + .label((d: any) => d.val); }); it("rectangle labels disabled by default", () => { + let svg = TestMethods.generateSVG(150, 300); + plot.renderTo(svg); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 0, "by default, no labels are drawn"); svg.remove(); }); it("rectangle labels render properly", () => { + let svg = TestMethods.generateSVG(150, 300); + plot.renderTo(svg); plot.labelsEnabled(true); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 2, "all labels are drawn"); @@ -457,6 +457,8 @@ describe("Plots", () => { }); it("rectangle labels hide if rectangle is too skinny", () => { + let svg = TestMethods.generateSVG(150, 300); + plot.renderTo(svg); plot.labelsEnabled(true); plot.label((d: any, i: number) => d.val + ( i !== 0 ? "a really really really long string" : "" )); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); @@ -466,9 +468,9 @@ describe("Plots", () => { }); it("rectangle labels hide if rectangle is too short", () => { + let svg = TestMethods.generateSVG(150, 30) + plot.renderTo(svg); plot.labelsEnabled(true); - svg.remove(); - svg = TestMethods.generateSVG(150, 30); plot.label((d: any) => d.val); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 0, "labels are not drawn when rectangles are too short"); @@ -476,6 +478,8 @@ describe("Plots", () => { }); it("rectangle labels are updated on dataset change", () => { + let svg = TestMethods.generateSVG(150, 300) + plot.renderTo(svg); plot.labelsEnabled(true); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); assert.lengthOf(texts, 2, "all labels are drawn"); @@ -489,6 +493,8 @@ describe("Plots", () => { }); it("labels cut off by edges are not shown", () => { + let svg = TestMethods.generateSVG(150, 300) + plot.renderTo(svg); plot.labelsEnabled(true); let data = [ { x: 2, y: 2, x2: 3, y2: 3, val: "center" }, @@ -507,6 +513,8 @@ describe("Plots", () => { }); it("labels cut off by other rectangels are not shown", () => { + let svg = TestMethods.generateSVG(150, 300) + plot.renderTo(svg); plot.labelsEnabled(true); let data = [ { x: 0, y: 0, x2: 2, y2: 2, val: "bottom" }, From 883fc5acaf916c0b856aa26ed76112744bccb0be Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 17:44:06 -0700 Subject: [PATCH 041/160] [refactorRectangle] finished refactoring the merge --- test/plots/rectanglePlotTests.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 52baee9a03..cc2b32f9e4 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -423,6 +423,7 @@ describe("Plots", () => { let dataset: Plottable.Dataset; let xScale: Plottable.Scales.Linear; let yScale: Plottable.Scales.Linear; + beforeEach(() => { xScale = new Plottable.Scales.Linear(); yScale = new Plottable.Scales.Linear(); From 2513a449e1c204d755aab8dba467408376de59e4 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 17:44:52 -0700 Subject: [PATCH 042/160] [refactorRectangle] tslint --- test/plots/rectanglePlotTests.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index cc2b32f9e4..e3ad1735e2 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -469,7 +469,7 @@ describe("Plots", () => { }); it("rectangle labels hide if rectangle is too short", () => { - let svg = TestMethods.generateSVG(150, 30) + let svg = TestMethods.generateSVG(150, 30); plot.renderTo(svg); plot.labelsEnabled(true); plot.label((d: any) => d.val); @@ -479,7 +479,7 @@ describe("Plots", () => { }); it("rectangle labels are updated on dataset change", () => { - let svg = TestMethods.generateSVG(150, 300) + let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); @@ -494,7 +494,7 @@ describe("Plots", () => { }); it("labels cut off by edges are not shown", () => { - let svg = TestMethods.generateSVG(150, 300) + let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); let data = [ @@ -514,7 +514,7 @@ describe("Plots", () => { }); it("labels cut off by other rectangels are not shown", () => { - let svg = TestMethods.generateSVG(150, 300) + let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); let data = [ From edec0423bf30ba0d138f2aea73f3cb9fd5fd6c3c Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Wed, 19 Aug 2015 18:42:08 -0700 Subject: [PATCH 043/160] [refactorRectangle] improved semantics of the tests for labels --- test/plots/rectanglePlotTests.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index e3ad1735e2..1807ba455e 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -414,7 +414,7 @@ describe("Plots", () => { }); - describe("Labels", () => { + describe("Label behavior", () => { let plot: Plottable.Plots.Rectangle; let data = [ { x: 0, y: 0, x2: 1, y2: 1, val: "1" }, @@ -437,7 +437,7 @@ describe("Plots", () => { .label((d: any) => d.val); }); - it("rectangle labels disabled by default", () => { + it("displays rectangle labels by default", () => { let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); @@ -445,7 +445,7 @@ describe("Plots", () => { svg.remove(); }); - it("rectangle labels render properly", () => { + it("renders correct number of labels with the correct text", () => { let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); @@ -457,7 +457,7 @@ describe("Plots", () => { svg.remove(); }); - it("rectangle labels hide if rectangle is too skinny", () => { + it("hides labels when rectangles do not offer enough width", () => { let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); @@ -468,7 +468,7 @@ describe("Plots", () => { svg.remove(); }); - it("rectangle labels hide if rectangle is too short", () => { + it("hides labels when rectangles do not offer enough height", () => { let svg = TestMethods.generateSVG(150, 30); plot.renderTo(svg); plot.labelsEnabled(true); @@ -478,7 +478,7 @@ describe("Plots", () => { svg.remove(); }); - it("rectangle labels are updated on dataset change", () => { + it("updates labels on dataset change", () => { let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); @@ -493,7 +493,7 @@ describe("Plots", () => { svg.remove(); }); - it("labels cut off by edges are not shown", () => { + it("hides labels cut off by edges", () => { let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); @@ -513,7 +513,7 @@ describe("Plots", () => { svg.remove(); }); - it("labels cut off by other rectangels are not shown", () => { + it("hides labels cut off by other rectangels", () => { let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); From 35cfd4b39c08d2c7b562a8c4fd83664de129ab41 Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Wed, 19 Aug 2015 18:49:58 -0700 Subject: [PATCH 044/160] Clean up tests - Use correct target for events. - Corrected starting postitions in drag tests. - Corrected cursor style name. --- test/components/dragLineLayerTests.ts | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/components/dragLineLayerTests.ts b/test/components/dragLineLayerTests.ts index 5fc96c6226..81ffa7ff71 100644 --- a/test/components/dragLineLayerTests.ts +++ b/test/components/dragLineLayerTests.ts @@ -25,10 +25,10 @@ describe("Interactive Components", () => { dll.renderTo(svg); let dragEdge = dll.content().select(".drag-edge"); let computedStyles = window.getComputedStyle( dragEdge.node()); - assert.strictEqual(computedStyles.cursor, "resize-ew", "shows the resize cursor if enabled"); + assert.strictEqual(computedStyles.cursor, "ew-resize", "shows the resize cursor if enabled"); dll.enabled(false); computedStyles = window.getComputedStyle( dragEdge.node()); - assert.strictEqual(computedStyles.cursor, "inherit", "cursor set to \"auto\" if not enabled"); + assert.strictEqual(computedStyles.cursor, "auto", "cursor set to \"auto\" if not enabled"); svg.remove(); }); @@ -38,10 +38,10 @@ describe("Interactive Components", () => { dll.renderTo(svg); let dragEdge = dll.content().select(".drag-edge"); let computedStyles = window.getComputedStyle( dragEdge.node()); - assert.strictEqual(computedStyles.cursor, "resize-ns", "shows the resize cursor if enabled"); + assert.strictEqual(computedStyles.cursor, "ns-resize", "shows the resize cursor if enabled"); dll.enabled(false); computedStyles = window.getComputedStyle( dragEdge.node()); - assert.strictEqual(computedStyles.cursor, "inherit", "cursor set to \"auto\" if not enabled"); + assert.strictEqual(computedStyles.cursor, "auto", "cursor set to \"auto\" if not enabled"); svg.remove(); }); @@ -57,7 +57,7 @@ describe("Interactive Components", () => { dll.renderTo(svg); let endX = SVG_WIDTH / 4; TestMethods.triggerFakeDragSequence( - dll.content(), + dll.background(), { x: startX, y: SVG_HEIGHT / 2 }, { x: endX, y: SVG_HEIGHT / 2 } ); @@ -78,13 +78,13 @@ describe("Interactive Components", () => { it("line can be dragged if drag starts within detectionRadius()", () => { let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dll = new Plottable.Components.DragLineLayer("vertical"); - let startX = SVG_WIDTH / 2 + dll.detectionRadius(); - dll.pixelPosition(startX); + let linePosition = SVG_WIDTH / 2; + dll.pixelPosition(linePosition); dll.renderTo(svg); let endX = SVG_WIDTH / 4; TestMethods.triggerFakeDragSequence( - dll.content(), - { x: startX, y: SVG_HEIGHT / 2 }, + dll.background(), + { x: linePosition + dll.detectionRadius(), y: SVG_HEIGHT / 2 }, { x: endX, y: SVG_HEIGHT / 2 } ); TestMethods.assertLineAttrs( @@ -104,21 +104,21 @@ describe("Interactive Components", () => { it("starting a drag outside the detection radius does nothing", () => { let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); let dll = new Plottable.Components.DragLineLayer("vertical"); - let startX = SVG_WIDTH / 2 + 2 * dll.detectionRadius(); - dll.pixelPosition(startX); + let linePosition = SVG_WIDTH / 2; + dll.pixelPosition(linePosition); dll.renderTo(svg); let endX = SVG_WIDTH / 4; TestMethods.triggerFakeDragSequence( - dll.content(), - { x: startX, y: SVG_HEIGHT / 2 }, + dll.background(), + { x: linePosition + 2 * dll.detectionRadius(), y: SVG_HEIGHT / 2 }, { x: endX, y: SVG_HEIGHT / 2 } ); TestMethods.assertLineAttrs( dll.content().select(".guide-line"), { - x1: startX, + x1: linePosition, y1: 0, - x2: startX, + x2: linePosition, y2: SVG_HEIGHT }, "line did not move" @@ -135,7 +135,7 @@ describe("Interactive Components", () => { dll.renderTo(svg); let endX = SVG_WIDTH / 4; TestMethods.triggerFakeDragSequence( - dll.content(), + dll.background(), { x: startX, y: SVG_HEIGHT / 2 }, { x: endX, y: SVG_HEIGHT / 2 } ); @@ -166,7 +166,7 @@ describe("Interactive Components", () => { let startX = scale.scale(startValue); let endX = SVG_WIDTH / 4; TestMethods.triggerFakeDragSequence( - dll.content(), + dll.background(), { x: startX, y: SVG_HEIGHT / 2 }, { x: endX, y: SVG_HEIGHT / 2 } ); @@ -191,7 +191,7 @@ describe("Interactive Components", () => { let endX = SVG_WIDTH / 4; TestMethods.triggerFakeDragSequence( - dll.content(), + dll.background(), { x: startX, y: SVG_HEIGHT / 2 }, { x: endX, y: SVG_HEIGHT / 2 } ); From 8b9478d0df03c6b299e74e2dc8c70944f8078572 Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Wed, 19 Aug 2015 19:14:53 -0700 Subject: [PATCH 045/160] Add tests for dragging horizontal DragLineLayer --- test/components/dragLineLayerTests.ts | 159 ++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/test/components/dragLineLayerTests.ts b/test/components/dragLineLayerTests.ts index 81ffa7ff71..a30dd8cf45 100644 --- a/test/components/dragLineLayerTests.ts +++ b/test/components/dragLineLayerTests.ts @@ -204,6 +204,165 @@ describe("Interactive Components", () => { }); }); + describe("Dragging (horizontal)", () => { + let SVG_WIDTH = 300; + let SVG_HEIGHT = 400; + + it("line can be dragged", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("horizontal"); + let startY = SVG_HEIGHT / 2; + dll.pixelPosition(startY); + dll.renderTo(svg); + let endY = SVG_HEIGHT / 4; + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: SVG_WIDTH / 2, y: startY }, + { x: SVG_WIDTH / 2, y: endY } + ); + TestMethods.assertLineAttrs( + dll.content().select(".guide-line"), + { + x1: 0, + y1: endY, + x2: SVG_WIDTH, + y2: endY + }, + "line was dragged to the final location" + ); + assert.strictEqual(dll.pixelPosition(), endY, "pixelPosition was updated correctly"); + svg.remove(); + }); + + it("line can be dragged if drag starts within detectionRadius()", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("horizontal"); + let linePosition = SVG_HEIGHT / 2; + dll.pixelPosition(linePosition); + dll.renderTo(svg); + let endY = SVG_HEIGHT / 4; + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: SVG_WIDTH / 2, y: linePosition + dll.detectionRadius() }, + { x: SVG_WIDTH / 2, y: endY } + ); + TestMethods.assertLineAttrs( + dll.content().select(".guide-line"), + { + x1: 0, + y1: endY, + x2: SVG_WIDTH, + y2: endY + }, + "line was dragged to the final location" + ); + assert.strictEqual(dll.pixelPosition(), endY, "pixelPosition was updated correctly"); + svg.remove(); + }); + + it("starting a drag outside the detection radius does nothing", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("horizontal"); + let linePosition = SVG_HEIGHT / 2; + dll.pixelPosition(linePosition); + dll.renderTo(svg); + let endY = SVG_HEIGHT / 4; + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: SVG_WIDTH / 2, y: linePosition + 2 * dll.detectionRadius() }, + { x: SVG_WIDTH / 2, y: endY } + ); + TestMethods.assertLineAttrs( + dll.content().select(".guide-line"), + { + x1: 0, + y1: linePosition, + x2: SVG_WIDTH, + y2: linePosition + }, + "line did not move" + ); + svg.remove(); + }); + + it("can't be dragged if not enabled", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("horizontal"); + dll.enabled(false); + let startY = SVG_HEIGHT / 2; + dll.pixelPosition(startY); + dll.renderTo(svg); + let endY = SVG_HEIGHT / 4; + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: SVG_WIDTH / 2, y: startY }, + { x: SVG_WIDTH / 2, y: endY } + ); + TestMethods.assertLineAttrs( + dll.content().select(".guide-line"), + { + x1: 0, + y1: startY, + x2: SVG_WIDTH, + y2: startY + }, + "line did not move" + ); + svg.remove(); + }); + + it("dragging does not affect the mode (value mode)", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("horizontal"); + let scale = new Plottable.Scales.Linear(); + scale.domain([0, 1]); + dll.scale(scale); + + let startValue = 0.5; + dll.value(startValue); + dll.renderTo(svg); + + let startY = scale.scale(startValue); + let endY = SVG_HEIGHT / 4; + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: SVG_WIDTH / 2, y: startY }, + { x: SVG_WIDTH / 2, y: endY } + ); + let endValue = scale.invert(endY); + assert.strictEqual(dll.value(), endValue, "value was updated correctly"); + + scale.domain([0, 2]); + assert.strictEqual(dll.value(), endValue, "remained in \"value\" mode: value did not change when scale updated"); + svg.remove(); + }); + + it("dragging does not affect the mode (pixel mode)", () => { + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + let dll = new Plottable.Components.DragLineLayer("horizontal"); + let scale = new Plottable.Scales.Linear(); + scale.domain([0, 1]); + dll.scale(scale); + + let startY = SVG_HEIGHT / 2; + dll.pixelPosition(startY); + dll.renderTo(svg); + + let endY = SVG_HEIGHT / 4; + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: SVG_WIDTH / 2, y: startY }, + { x: SVG_WIDTH / 2, y: endY } + ); + let endValue = scale.invert(endY); + assert.strictEqual(dll.value(), endValue, "value was updated correctly"); + + scale.domain([0, 2]); + assert.strictEqual(dll.pixelPosition(), endY, "remained in \"position\" mode: position did not change when scale updated"); + svg.remove(); + }); + }); + // it("onDragStart()", () => { // triggers on start // passed correct object From 7dd2aea92be46444f8c70724ef08b03aa691b35e Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Wed, 19 Aug 2015 19:15:23 -0700 Subject: [PATCH 046/160] Initial implementation of DragLineLayer Still needed: attaching callbacks, destroy() cleaning up properly. --- plottable.css | 8 +++ plottable.d.ts | 7 ++- plottable.js | 88 ++++++++++++++++++++++++++++-- src/components/dragLineLayer.ts | 91 +++++++++++++++++++++++++++++++- src/components/guideLineLayer.ts | 10 +++- 5 files changed, 197 insertions(+), 7 deletions(-) diff --git a/plottable.css b/plottable.css index fe8daab4a5..423dea5895 100644 --- a/plottable.css +++ b/plottable.css @@ -164,6 +164,14 @@ svg.plottable { stroke-width: 1px; } +.plottable .drag-line-layer.enabled.vertical line.drag-edge { + cursor: ew-resize; +} + +.plottable .drag-line-layer.enabled.horizontal line.drag-edge { + cursor: ns-resize; +} + .plottable .legend text { fill: #32313F; font-family: "Helvetica Neue", sans-serif; diff --git a/plottable.d.ts b/plottable.d.ts index fc8ab55da6..8b63d486df 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -2437,10 +2437,12 @@ declare module Plottable { width: number; height: number; }; + protected _isVertical(): boolean; fixedWidth(): boolean; fixedHeight(): boolean; computeLayout(origin?: Point, availableWidth?: number, availableHeight?: number): GuideLineLayer; renderImmediately(): GuideLineLayer; + protected _setPixelPositionWithoutChangingMode(pixelPosition: number): void; /** * Gets the QuantitativeScale on the GuideLineLayer. * @@ -4411,8 +4413,11 @@ declare module Plottable { declare module Plottable { module Components { class DragLineLayer extends GuideLineLayer { + constructor(orientation: string); + protected _setup(): void; + renderImmediately(): DragLineLayer; detectionRadius(): number; - detectionRadius(r: number): DragLineLayer; + detectionRadius(detectionRadius: number): DragLineLayer; enabled(): boolean; enabled(enabled: boolean): DragLineLayer; } diff --git a/plottable.js b/plottable.js index 9c818339d1..173342dca4 100644 --- a/plottable.js +++ b/plottable.js @@ -6301,6 +6301,13 @@ var Plottable; this._value = this.scale().invert(this.pixelPosition()); } }; + GuideLineLayer.prototype._setPixelPositionWithoutChangingMode = function (pixelPosition) { + this._pixelPosition = pixelPosition; + if (this.scale() != null) { + this._value = this.scale().invert(this.pixelPosition()); + } + this.render(); + }; GuideLineLayer.prototype.scale = function (scale) { if (scale == null) { return this._scale; @@ -11477,12 +11484,87 @@ var Plottable; (function (Components) { var DragLineLayer = (function (_super) { __extends(DragLineLayer, _super); - function DragLineLayer() { - _super.apply(this, arguments); + function DragLineLayer(orientation) { + var _this = this; + _super.call(this, orientation); + this._detectionRadius = 3; + this._enabled = true; + this.addClass("drag-line-layer"); + this.addClass("enabled"); + if (this._isVertical()) { + this.addClass("vertical"); + } + else { + this.addClass("horizontal"); + } + this._dragInteraction = new Plottable.Interactions.Drag(); + this._dragInteraction.attachTo(this); + var grabbedLine = function (p) { + return (_this._isVertical() && + p.x >= _this.pixelPosition() - _this.detectionRadius() && + p.x <= _this.pixelPosition() + _this.detectionRadius()) || + (!_this._isVertical() && + p.y >= _this.pixelPosition() - _this.detectionRadius() && + p.y <= _this.pixelPosition() + _this.detectionRadius()); + }; + var dragging = false; + this._dragInteraction.onDragStart(function (start) { + if (grabbedLine(start)) { + dragging = true; + } + }); + this._dragInteraction.onDrag(function (start, end) { + if (dragging) { + _this._setPixelPositionWithoutChangingMode(_this._isVertical() ? end.x : end.y); + } + }); + this._dragInteraction.onDragEnd(function (start, end) { + dragging = false; + }); } - DragLineLayer.prototype.detectionRadius = function (r) { + DragLineLayer.prototype._setup = function () { + _super.prototype._setup.call(this); + this._detectionEdge = this.content().append("line").style({ + opacity: 0, + fill: "pink", + "pointer-events": "visibleStroke" + }).classed("drag-edge", true); + }; + DragLineLayer.prototype.renderImmediately = function () { + _super.prototype.renderImmediately.call(this); + this._detectionEdge.attr({ + x1: this._isVertical() ? this.pixelPosition() : 0, + y1: this._isVertical() ? 0 : this.pixelPosition(), + x2: this._isVertical() ? this.pixelPosition() : this.width(), + y2: this._isVertical() ? this.height() : this.pixelPosition(), + "stroke-width": this._detectionRadius * 2 + }); + return this; + }; + DragLineLayer.prototype.detectionRadius = function (detectionRadius) { + if (detectionRadius == null) { + return this._detectionRadius; + } + if (detectionRadius < 0) { + throw new Error("detection radius cannot be negative."); + } + this._detectionRadius = detectionRadius; + this.render(); + return this; }; DragLineLayer.prototype.enabled = function (enabled) { + if (enabled == null) { + return this._enabled; + } + this._enabled = enabled; + if (enabled) { + this.addClass("enabled"); + } + else { + this.removeClass("enabled"); + } + this._dragInteraction.enabled(enabled); + return this; }; return DragLineLayer; })(Components.GuideLineLayer); diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index cebfc451c0..c00310688f 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -3,15 +3,102 @@ module Plottable { export module Components { export class DragLineLayer extends GuideLineLayer { + private _dragInteraction: Interactions.Drag; + private _detectionRadius = 3; + private _detectionEdge: d3.Selection; + private _enabled = true; + + constructor(orientation: string) { + super(orientation); + this.addClass("drag-line-layer"); + this.addClass("enabled"); + if (this._isVertical()) { + this.addClass("vertical"); + } else { + this.addClass("horizontal"); + } + + this._dragInteraction = new Plottable.Interactions.Drag(); + this._dragInteraction.attachTo(this); + + let grabbedLine = (p: Point) => { + return (this._isVertical() && + p.x >= this.pixelPosition() - this.detectionRadius() && + p.x <= this.pixelPosition() + this.detectionRadius() + ) || + ( + !this._isVertical() && + p.y >= this.pixelPosition() - this.detectionRadius() && + p.y <= this.pixelPosition() + this.detectionRadius() + ); + } + + let dragging = false; + this._dragInteraction.onDragStart((start: Point) => { + if (grabbedLine(start)) { + dragging = true; + } + }); + this._dragInteraction.onDrag((start: Point, end: Point) => { + if (dragging) { + this._setPixelPositionWithoutChangingMode(this._isVertical() ? end.x : end.y); + } + }); + this._dragInteraction.onDragEnd((start: Point, end: Point) => { + dragging = false; + }); + } + + protected _setup() { + super._setup(); + this._detectionEdge = this.content().append("line").style({ + opacity: 0, + fill: "pink", + "pointer-events": "visibleStroke" + }).classed("drag-edge", true); + } + + public renderImmediately() { + super.renderImmediately(); + this._detectionEdge.attr({ + x1: this._isVertical() ? this.pixelPosition() : 0, + y1: this._isVertical() ? 0 : this.pixelPosition(), + x2: this._isVertical() ? this.pixelPosition() : this.width(), + y2: this._isVertical() ? this.height() : this.pixelPosition(), + "stroke-width": this._detectionRadius * 2 + }); + + return this; + } public detectionRadius(): number; - public detectionRadius(r: number): DragLineLayer; - public detectionRadius(r?: number): any { + public detectionRadius(detectionRadius: number): DragLineLayer; + public detectionRadius(detectionRadius?: number): any { + if (detectionRadius == null) { + return this._detectionRadius; + } + if (detectionRadius < 0) { + throw new Error("detection radius cannot be negative."); + } + this._detectionRadius = detectionRadius; + this.render(); + return this; } public enabled(): boolean; public enabled(enabled: boolean): DragLineLayer; public enabled(enabled?: boolean): any { + if (enabled == null) { + return this._enabled; + } + this._enabled = enabled; + if (enabled) { + this.addClass("enabled"); + } else { + this.removeClass("enabled"); + } + this._dragInteraction.enabled(enabled); + return this; } } } diff --git a/src/components/guideLineLayer.ts b/src/components/guideLineLayer.ts index 592eba3970..cb5977eb53 100644 --- a/src/components/guideLineLayer.ts +++ b/src/components/guideLineLayer.ts @@ -41,7 +41,7 @@ export module Components { }; } - private _isVertical() { + protected _isVertical() { return this._orientation === GuideLineLayer.ORIENTATION_VERTICAL; } @@ -89,6 +89,14 @@ export module Components { } } + protected _setPixelPositionWithoutChangingMode(pixelPosition: number) { + this._pixelPosition = pixelPosition; + if (this.scale() != null) { + this._value = this.scale().invert(this.pixelPosition()); + } + this.render(); + } + /** * Gets the QuantitativeScale on the GuideLineLayer. * From 4b402107ef901dc3660cf1501a7c870a814cdb27 Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Wed, 19 Aug 2015 23:56:33 -0700 Subject: [PATCH 047/160] Add tests for dragstart, drag, and dragend callbacks --- test/components/dragLineLayerTests.ts | 141 +++++++++++++++++++++++--- 1 file changed, 128 insertions(+), 13 deletions(-) diff --git a/test/components/dragLineLayerTests.ts b/test/components/dragLineLayerTests.ts index a30dd8cf45..40a4727644 100644 --- a/test/components/dragLineLayerTests.ts +++ b/test/components/dragLineLayerTests.ts @@ -363,21 +363,136 @@ describe("Interactive Components", () => { }); }); - // it("onDragStart()", () => { - // triggers on start - // passed correct object - // does not trigger if started off line - // }); + it("onDragStart() / offDragStart()", () => { + let dll = new Plottable.Components.DragLineLayer("vertical"); - // it("onDrag()", () => { - // triggers on move - // passed correct object - // }); + let callbackCalled = false; + let pixelPositionOnCalling: number; + let callback = (layer: Plottable.Components.DragLineLayer) => { + assert.strictEqual(layer, dll, "was passed the calling DragLineLayer"); + pixelPositionOnCalling = dll.pixelPosition(); + callbackCalled = true; + }; + assert.strictEqual(dll.onDragStart(callback), dll, "onDragStart() returns the calling DragLineLayer"); - // it("onDragEnd()", () => { - // triggers on end - // passed correct object - // }); + let SVG_WIDTH = 400; + let SVG_HEIGHT = 300; + dll.pixelPosition(SVG_WIDTH / 2); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + dll.renderTo(svg); + + TestMethods.triggerFakeMouseEvent("mousedown", dll.background(), SVG_WIDTH / 2, SVG_HEIGHT / 2); + assert.isTrue(callbackCalled, "callback was called on drag start"); + assert.strictEqual(pixelPositionOnCalling, SVG_WIDTH / 2, "DragLineLayer's state was updated before calling callbacks"); + TestMethods.triggerFakeMouseEvent("mouseup", dll.background(), SVG_WIDTH / 2, SVG_HEIGHT / 2); + + callbackCalled = false; + TestMethods.triggerFakeMouseEvent("mousedown", dll.background(), 0, SVG_HEIGHT / 2); + assert.isFalse(callbackCalled, "callback not called if line was not grabbed"); + TestMethods.triggerFakeMouseEvent("mouseup", dll.background(), 0, SVG_HEIGHT / 2); + + assert.strictEqual(dll.offDragStart(callback), dll, "offDragStart() returns the calling DragLineLayer"); + TestMethods.triggerFakeMouseEvent("mousedown", dll.background(), SVG_WIDTH / 2, SVG_HEIGHT / 2); + assert.isFalse(callbackCalled, "callback was deregistered successfully"); + TestMethods.triggerFakeMouseEvent("mouseup", dll.background(), SVG_WIDTH / 2, SVG_HEIGHT / 2); + + svg.remove(); + }); + + it("onDrag()", () => { + let dll = new Plottable.Components.DragLineLayer("vertical"); + + let callbackCalled = false; + let pixelPositionOnCalling: number; + let callback = (layer: Plottable.Components.DragLineLayer) => { + assert.strictEqual(layer, dll, "was passed the calling DragLineLayer"); + pixelPositionOnCalling = dll.pixelPosition(); + callbackCalled = true; + }; + assert.strictEqual(dll.onDrag(callback), dll, "onDrag() returns the calling DragLineLayer"); + + let SVG_WIDTH = 400; + let SVG_HEIGHT = 300; + let startX = SVG_WIDTH / 2; + dll.pixelPosition(startX); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + dll.renderTo(svg); + + let midX = startX * 3 / 8; + let endX = SVG_WIDTH / 4; + TestMethods.triggerFakeMouseEvent("mousedown", dll.background(), startX, SVG_HEIGHT / 2); + TestMethods.triggerFakeMouseEvent("mousemove", dll.background(), midX, SVG_HEIGHT / 2); + assert.isTrue(callbackCalled, "callback was called on drag"); + assert.strictEqual(pixelPositionOnCalling, midX, "DragLineLayer's state was updated before calling callbacks"); + callbackCalled = false; + TestMethods.triggerFakeMouseEvent("mousemove", dll.background(), endX, SVG_HEIGHT / 2); + assert.isTrue(callbackCalled, "callback was called again on continued dragging"); + assert.strictEqual(pixelPositionOnCalling, endX, "DragLineLayer's state was updated again"); + TestMethods.triggerFakeMouseEvent("mouseup", dll.background(), endX, SVG_HEIGHT / 2); + + callbackCalled = false; + dll.pixelPosition(startX); + TestMethods.triggerFakeMouseEvent("mousedown", dll.background(), 0, SVG_HEIGHT / 2); + TestMethods.triggerFakeMouseEvent("mousemove", dll.background(), endX, SVG_HEIGHT / 2); + assert.isFalse(callbackCalled, "callback not called if line was not grabbed"); + TestMethods.triggerFakeMouseEvent("mouseup", dll.background(), endX, SVG_HEIGHT / 2); + + assert.strictEqual(dll.offDrag(callback), dll, "offDrag() returns the calling DragLineLayer"); + TestMethods.triggerFakeMouseEvent("mousedown", dll.background(), startX, SVG_HEIGHT / 2); + TestMethods.triggerFakeMouseEvent("mousemove", dll.background(), endX, SVG_HEIGHT / 2); + assert.isFalse(callbackCalled, "callback was deregistered successfully"); + TestMethods.triggerFakeMouseEvent("mouseup", dll.background(), endX, SVG_HEIGHT / 2); + + svg.remove(); + }); + + it("onDragEnd()", () => { + let dll = new Plottable.Components.DragLineLayer("vertical"); + + let callbackCalled = false; + let pixelPositionOnCalling: number; + let callback = (layer: Plottable.Components.DragLineLayer) => { + assert.strictEqual(layer, dll, "was passed the calling DragLineLayer"); + pixelPositionOnCalling = dll.pixelPosition(); + callbackCalled = true; + }; + assert.strictEqual(dll.onDragEnd(callback), dll, "onDragEnd() returns the calling DragLineLayer"); + + let SVG_WIDTH = 400; + let SVG_HEIGHT = 300; + let startX = SVG_WIDTH / 2; + dll.pixelPosition(startX); + let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT); + dll.renderTo(svg); + + let endX = SVG_WIDTH / 4; + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: startX, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + assert.isTrue(callbackCalled, "callback was called on drag end"); + assert.strictEqual(pixelPositionOnCalling, endX, "DragLineLayer's state was updated before calling callbacks"); + + callbackCalled = false; + dll.pixelPosition(startX); + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: 0, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + assert.isFalse(callbackCalled, "callback not called if line was not grabbed"); + + assert.strictEqual(dll.offDragEnd(callback), dll, "offDragEnd() returns the calling DragLineLayer"); + TestMethods.triggerFakeDragSequence( + dll.background(), + { x: startX, y: SVG_HEIGHT / 2 }, + { x: endX, y: SVG_HEIGHT / 2 } + ); + assert.isFalse(callbackCalled, "callback was deregistered successfully"); + + svg.remove(); + }); // it("destroy() removes all callbacks and properly disconnects from its Interaction", () => { // }); From 261df13f0b13a4ca35214fc3db0acb174eb0ea2b Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Wed, 19 Aug 2015 23:56:51 -0700 Subject: [PATCH 048/160] Implement callbacks on DragLineLayer --- plottable.d.ts | 9 +++++++ plottable.js | 35 +++++++++++++++++++++++- src/components/dragLineLayer.ts | 47 ++++++++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/plottable.d.ts b/plottable.d.ts index 8b63d486df..94effbc413 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -4412,6 +4412,9 @@ declare module Plottable { declare module Plottable { module Components { + interface DragLineCallback { + (dragLineLayer: DragLineLayer): void; + } class DragLineLayer extends GuideLineLayer { constructor(orientation: string); protected _setup(): void; @@ -4420,6 +4423,12 @@ declare module Plottable { detectionRadius(detectionRadius: number): DragLineLayer; enabled(): boolean; enabled(enabled: boolean): DragLineLayer; + onDragStart(callback: DragLineCallback): DragLineLayer; + offDragStart(callback: DragLineCallback): DragLineLayer; + onDrag(callback: DragLineCallback): DragLineLayer; + offDrag(callback: DragLineCallback): DragLineLayer; + onDragEnd(callback: DragLineCallback): DragLineLayer; + offDragEnd(callback: DragLineCallback): DragLineLayer; } } } diff --git a/plottable.js b/plottable.js index 173342dca4..4bfb162b7a 100644 --- a/plottable.js +++ b/plottable.js @@ -11482,6 +11482,7 @@ var Plottable; (function (Plottable) { var Components; (function (Components) { + ; var DragLineLayer = (function (_super) { __extends(DragLineLayer, _super); function DragLineLayer(orientation) { @@ -11511,16 +11512,24 @@ var Plottable; this._dragInteraction.onDragStart(function (start) { if (grabbedLine(start)) { dragging = true; + _this._dragStartCallbacks.callCallbacks(_this); } }); this._dragInteraction.onDrag(function (start, end) { if (dragging) { _this._setPixelPositionWithoutChangingMode(_this._isVertical() ? end.x : end.y); + _this._dragCallbacks.callCallbacks(_this); } }); this._dragInteraction.onDragEnd(function (start, end) { - dragging = false; + if (dragging) { + dragging = false; + _this._dragEndCallbacks.callCallbacks(_this); + } }); + this._dragStartCallbacks = new Plottable.Utils.CallbackSet(); + this._dragCallbacks = new Plottable.Utils.CallbackSet(); + this._dragEndCallbacks = new Plottable.Utils.CallbackSet(); } DragLineLayer.prototype._setup = function () { _super.prototype._setup.call(this); @@ -11566,6 +11575,30 @@ var Plottable; this._dragInteraction.enabled(enabled); return this; }; + DragLineLayer.prototype.onDragStart = function (callback) { + this._dragStartCallbacks.add(callback); + return this; + }; + DragLineLayer.prototype.offDragStart = function (callback) { + this._dragStartCallbacks.delete(callback); + return this; + }; + DragLineLayer.prototype.onDrag = function (callback) { + this._dragCallbacks.add(callback); + return this; + }; + DragLineLayer.prototype.offDrag = function (callback) { + this._dragCallbacks.delete(callback); + return this; + }; + DragLineLayer.prototype.onDragEnd = function (callback) { + this._dragEndCallbacks.add(callback); + return this; + }; + DragLineLayer.prototype.offDragEnd = function (callback) { + this._dragEndCallbacks.delete(callback); + return this; + }; return DragLineLayer; })(Components.GuideLineLayer); Components.DragLineLayer = DragLineLayer; diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index c00310688f..ac534d6b58 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -2,12 +2,18 @@ module Plottable { export module Components { + export interface DragLineCallback { (dragLineLayer: DragLineLayer): void }; + export class DragLineLayer extends GuideLineLayer { private _dragInteraction: Interactions.Drag; private _detectionRadius = 3; private _detectionEdge: d3.Selection; private _enabled = true; + private _dragStartCallbacks: Utils.CallbackSet>; + private _dragCallbacks: Utils.CallbackSet>; + private _dragEndCallbacks: Utils.CallbackSet>; + constructor(orientation: string) { super(orientation); this.addClass("drag-line-layer"); @@ -37,16 +43,25 @@ export module Components { this._dragInteraction.onDragStart((start: Point) => { if (grabbedLine(start)) { dragging = true; + this._dragStartCallbacks.callCallbacks(this); } }); this._dragInteraction.onDrag((start: Point, end: Point) => { if (dragging) { this._setPixelPositionWithoutChangingMode(this._isVertical() ? end.x : end.y); + this._dragCallbacks.callCallbacks(this); } }); this._dragInteraction.onDragEnd((start: Point, end: Point) => { - dragging = false; + if (dragging) { + dragging = false; + this._dragEndCallbacks.callCallbacks(this); + } }); + + this._dragStartCallbacks = new Utils.CallbackSet>(); + this._dragCallbacks = new Utils.CallbackSet>(); + this._dragEndCallbacks = new Utils.CallbackSet>(); } protected _setup() { @@ -100,6 +115,36 @@ export module Components { this._dragInteraction.enabled(enabled); return this; } + + public onDragStart(callback: DragLineCallback) { + this._dragStartCallbacks.add(callback); + return this; + } + + public offDragStart(callback: DragLineCallback) { + this._dragStartCallbacks.delete(callback); + return this; + } + + public onDrag(callback: DragLineCallback) { + this._dragCallbacks.add(callback); + return this; + } + + public offDrag(callback: DragLineCallback) { + this._dragCallbacks.delete(callback) + return this; + } + + public onDragEnd(callback: DragLineCallback) { + this._dragEndCallbacks.add(callback); + return this; + } + + public offDragEnd(callback: DragLineCallback) { + this._dragEndCallbacks.delete(callback); + return this; + } } } } From 26eb2ea27e51035944229d10aa41d883569f02c6 Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Thu, 20 Aug 2015 00:01:19 -0700 Subject: [PATCH 049/160] TSLint --- src/components/dragLineLayer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index ac534d6b58..eba2b13c2a 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -2,7 +2,7 @@ module Plottable { export module Components { - export interface DragLineCallback { (dragLineLayer: DragLineLayer): void }; + export interface DragLineCallback { (dragLineLayer: DragLineLayer): void; }; export class DragLineLayer extends GuideLineLayer { private _dragInteraction: Interactions.Drag; @@ -37,7 +37,7 @@ export module Components { p.y >= this.pixelPosition() - this.detectionRadius() && p.y <= this.pixelPosition() + this.detectionRadius() ); - } + }; let dragging = false; this._dragInteraction.onDragStart((start: Point) => { @@ -132,7 +132,7 @@ export module Components { } public offDrag(callback: DragLineCallback) { - this._dragCallbacks.delete(callback) + this._dragCallbacks.delete(callback); return this; } From 4e9fac7de05b8608729da7cc53c3c1001cd8c104 Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Thu, 20 Aug 2015 00:19:58 -0700 Subject: [PATCH 050/160] Add tests for destroy() --- test/components/dragLineLayerTests.ts | 32 +++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/test/components/dragLineLayerTests.ts b/test/components/dragLineLayerTests.ts index 40a4727644..40d919fa12 100644 --- a/test/components/dragLineLayerTests.ts +++ b/test/components/dragLineLayerTests.ts @@ -494,7 +494,35 @@ describe("Interactive Components", () => { svg.remove(); }); - // it("destroy() removes all callbacks and properly disconnects from its Interaction", () => { - // }); + it("destroy() removes all callbacks on the DragLineLayer", () => { + let dll = new Plottable.Components.DragLineLayer("vertical"); + let callback = () => "foo"; + dll.onDragStart(callback); + dll.onDrag(callback); + dll.onDragEnd(callback); + + dll.destroy(); + + let dragStartCallbacks = >> ( dll)._dragStartCallbacks; + let dragCallbacks = >> ( dll)._dragCallbacks; + let dragEndCallbacks = >> ( dll)._dragEndCallbacks; + assert.strictEqual(dragStartCallbacks.size, 0, "dragStart callbacks removed on destroy()"); + assert.strictEqual(dragCallbacks.size, 0, "drag callbacks removed on destroy()"); + assert.strictEqual(dragEndCallbacks.size, 0, "drag end callbacks removed on destroy()"); + }); + + it("destroy() correctly disconnects from the internal Drag Interaction", () => { + let dll = new Plottable.Components.DragLineLayer("vertical"); + let dragInteraction = ( dll)._dragInteraction; + + dll.destroy(); + + let interactionStartCallbacks = > dragInteraction._dragStartCallbacks; + let interactionCallbacks = > dragInteraction._dragCallbacks; + let interactionEndCallbacks = > dragInteraction._dragEndCallbacks; + assert.strictEqual(interactionStartCallbacks.size, 0, "Interaction dragStart callbacks removed on destroy()"); + assert.strictEqual(interactionCallbacks.size, 0, "Interaction drag callbacks removed on destroy()"); + assert.strictEqual(interactionEndCallbacks.size, 0, "Interaction drag end callbacks removed on destroy()"); + }); }); }); From bc2607dbb9d6386b0f6558568e447399754aba6f Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Thu, 20 Aug 2015 00:20:22 -0700 Subject: [PATCH 051/160] Implement destroy() on DragLineLayer - Removes all callbacks on itself when destroy()-ed - Removs callbacks from the dragInteraction when destroy()-ed --- plottable.d.ts | 7 ++++--- plottable.js | 31 +++++++++++++++++++++------- src/components/dragLineLayer.ts | 36 +++++++++++++++++++++++++-------- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/plottable.d.ts b/plottable.d.ts index 94effbc413..8c0bf0d662 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -4411,10 +4411,10 @@ declare module Plottable { declare module Plottable { + interface DragLineCallback { + (dragLineLayer: Components.DragLineLayer): void; + } module Components { - interface DragLineCallback { - (dragLineLayer: DragLineLayer): void; - } class DragLineLayer extends GuideLineLayer { constructor(orientation: string); protected _setup(): void; @@ -4429,6 +4429,7 @@ declare module Plottable { offDrag(callback: DragLineCallback): DragLineLayer; onDragEnd(callback: DragLineCallback): DragLineLayer; offDragEnd(callback: DragLineCallback): DragLineLayer; + destroy(): void; } } } diff --git a/plottable.js b/plottable.js index 4bfb162b7a..ba2c6e50bb 100644 --- a/plottable.js +++ b/plottable.js @@ -11480,9 +11480,9 @@ var __extends = (this && this.__extends) || function (d, b) { }; var Plottable; (function (Plottable) { + ; var Components; (function (Components) { - ; var DragLineLayer = (function (_super) { __extends(DragLineLayer, _super); function DragLineLayer(orientation) { @@ -11509,24 +11509,33 @@ var Plottable; p.y <= _this.pixelPosition() + _this.detectionRadius()); }; var dragging = false; - this._dragInteraction.onDragStart(function (start) { + var dragStartCallback = function (start) { if (grabbedLine(start)) { dragging = true; _this._dragStartCallbacks.callCallbacks(_this); } - }); - this._dragInteraction.onDrag(function (start, end) { + }; + this._dragInteraction.onDragStart(dragStartCallback); + var dragCallback = function (start, end) { if (dragging) { _this._setPixelPositionWithoutChangingMode(_this._isVertical() ? end.x : end.y); _this._dragCallbacks.callCallbacks(_this); } - }); - this._dragInteraction.onDragEnd(function (start, end) { + }; + this._dragInteraction.onDrag(dragCallback); + var dragEndCallback = function (start, end) { if (dragging) { dragging = false; _this._dragEndCallbacks.callCallbacks(_this); } - }); + }; + this._dragInteraction.onDragEnd(dragEndCallback); + this._disconnectInteractionCallbacks = function () { + _this._dragInteraction.offDragStart(dragStartCallback); + _this._dragInteraction.offDrag(dragCallback); + _this._dragInteraction.offDragEnd(dragEndCallback); + delete _this._disconnectInteractionCallbacks; + }; this._dragStartCallbacks = new Plottable.Utils.CallbackSet(); this._dragCallbacks = new Plottable.Utils.CallbackSet(); this._dragEndCallbacks = new Plottable.Utils.CallbackSet(); @@ -11599,6 +11608,14 @@ var Plottable; this._dragEndCallbacks.delete(callback); return this; }; + DragLineLayer.prototype.destroy = function () { + var _this = this; + _super.prototype.destroy.call(this); + this._dragStartCallbacks.forEach(function (callback) { return _this._dragStartCallbacks.delete(callback); }); + this._dragCallbacks.forEach(function (callback) { return _this._dragCallbacks.delete(callback); }); + this._dragEndCallbacks.forEach(function (callback) { return _this._dragEndCallbacks.delete(callback); }); + this._disconnectInteractionCallbacks(); + }; return DragLineLayer; })(Components.GuideLineLayer); Components.DragLineLayer = DragLineLayer; diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index eba2b13c2a..fe63bdb44d 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -1,9 +1,10 @@ /// module Plottable { -export module Components { - export interface DragLineCallback { (dragLineLayer: DragLineLayer): void; }; +export interface DragLineCallback { (dragLineLayer: Components.DragLineLayer): void; }; + +export module Components { export class DragLineLayer extends GuideLineLayer { private _dragInteraction: Interactions.Drag; private _detectionRadius = 3; @@ -13,6 +14,7 @@ export module Components { private _dragStartCallbacks: Utils.CallbackSet>; private _dragCallbacks: Utils.CallbackSet>; private _dragEndCallbacks: Utils.CallbackSet>; + private _disconnectInteractionCallbacks: () => void; constructor(orientation: string) { super(orientation); @@ -40,24 +42,34 @@ export module Components { }; let dragging = false; - this._dragInteraction.onDragStart((start: Point) => { + let dragStartCallback = (start: Point) => { if (grabbedLine(start)) { dragging = true; this._dragStartCallbacks.callCallbacks(this); } - }); - this._dragInteraction.onDrag((start: Point, end: Point) => { + }; + this._dragInteraction.onDragStart(dragStartCallback); + let dragCallback = (start: Point, end: Point) => { if (dragging) { this._setPixelPositionWithoutChangingMode(this._isVertical() ? end.x : end.y); this._dragCallbacks.callCallbacks(this); } - }); - this._dragInteraction.onDragEnd((start: Point, end: Point) => { + }; + this._dragInteraction.onDrag(dragCallback); + let dragEndCallback = (start: Point, end: Point) => { if (dragging) { dragging = false; this._dragEndCallbacks.callCallbacks(this); } - }); + }; + this._dragInteraction.onDragEnd(dragEndCallback); + + this._disconnectInteractionCallbacks = () => { + this._dragInteraction.offDragStart(dragStartCallback); + this._dragInteraction.offDrag(dragCallback); + this._dragInteraction.offDragEnd(dragEndCallback); + delete this._disconnectInteractionCallbacks; + }; this._dragStartCallbacks = new Utils.CallbackSet>(); this._dragCallbacks = new Utils.CallbackSet>(); @@ -145,6 +157,14 @@ export module Components { this._dragEndCallbacks.delete(callback); return this; } + + public destroy() { + super.destroy(); + this._dragStartCallbacks.forEach((callback) => this._dragStartCallbacks.delete(callback)); + this._dragCallbacks.forEach((callback) => this._dragCallbacks.delete(callback)); + this._dragEndCallbacks.forEach((callback) => this._dragEndCallbacks.delete(callback)); + this._disconnectInteractionCallbacks(); + } } } } From fa48c2b17d5ca0d8c4c30fd72990f639784ffa73 Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Thu, 20 Aug 2015 10:27:48 -0700 Subject: [PATCH 052/160] Add documentation. --- plottable.d.ts | 57 ++++++++++++++++++++++++++++++++ plottable.js | 39 ++++++++++++++++++++++ src/components/dragLineLayer.ts | 58 ++++++++++++++++++++++++++++++++- 3 files changed, 153 insertions(+), 1 deletion(-) diff --git a/plottable.d.ts b/plottable.d.ts index 8c0bf0d662..40680f46b1 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -4419,15 +4419,72 @@ declare module Plottable { constructor(orientation: string); protected _setup(): void; renderImmediately(): DragLineLayer; + /** + * Gets the detection radius of the drag line in pixels. + */ detectionRadius(): number; + /** + * Sets the detection radius of the drag line in pixels. + * + * @param {number} detectionRadius + * @return {DragLineLayer} The calling DragLineLayer. + */ detectionRadius(detectionRadius: number): DragLineLayer; + /** + * Gets whether the DragLineLayer is enabled. + */ enabled(): boolean; + /** + * Enables or disables the DragLineLayer. + * + * @param {boolean} enabled + * @return {DragLineLayer} The calling DragLineLayer. + */ enabled(enabled: boolean): DragLineLayer; + /** + * Sets the callback to be called when dragging starts. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ onDragStart(callback: DragLineCallback): DragLineLayer; + /** + * Removes a callback that would be called when dragging starts. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ offDragStart(callback: DragLineCallback): DragLineLayer; + /** + * Sets a callback to be called during dragging. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ onDrag(callback: DragLineCallback): DragLineLayer; + /** + * Removes a callback that would be called during dragging. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ offDrag(callback: DragLineCallback): DragLineLayer; + /** + * Sets a callback to be called when dragging ends. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ onDragEnd(callback: DragLineCallback): DragLineLayer; + /** + * Removes a callback that would be called when dragging ends. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ offDragEnd(callback: DragLineCallback): DragLineLayer; destroy(): void; } diff --git a/plottable.js b/plottable.js index ba2c6e50bb..0c13bf3761 100644 --- a/plottable.js +++ b/plottable.js @@ -11584,26 +11584,65 @@ var Plottable; this._dragInteraction.enabled(enabled); return this; }; + /** + * Sets the callback to be called when dragging starts. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ DragLineLayer.prototype.onDragStart = function (callback) { this._dragStartCallbacks.add(callback); return this; }; + /** + * Removes a callback that would be called when dragging starts. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ DragLineLayer.prototype.offDragStart = function (callback) { this._dragStartCallbacks.delete(callback); return this; }; + /** + * Sets a callback to be called during dragging. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ DragLineLayer.prototype.onDrag = function (callback) { this._dragCallbacks.add(callback); return this; }; + /** + * Removes a callback that would be called during dragging. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ DragLineLayer.prototype.offDrag = function (callback) { this._dragCallbacks.delete(callback); return this; }; + /** + * Sets a callback to be called when dragging ends. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ DragLineLayer.prototype.onDragEnd = function (callback) { this._dragEndCallbacks.add(callback); return this; }; + /** + * Removes a callback that would be called when dragging ends. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ DragLineLayer.prototype.offDragEnd = function (callback) { this._dragEndCallbacks.delete(callback); return this; diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index fe63bdb44d..0477e00d9b 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -97,8 +97,16 @@ export module Components { return this; } - + /** + * Gets the detection radius of the drag line in pixels. + */ public detectionRadius(): number; + /** + * Sets the detection radius of the drag line in pixels. + * + * @param {number} detectionRadius + * @return {DragLineLayer} The calling DragLineLayer. + */ public detectionRadius(detectionRadius: number): DragLineLayer; public detectionRadius(detectionRadius?: number): any { if (detectionRadius == null) { @@ -112,7 +120,16 @@ export module Components { return this; } + /** + * Gets whether the DragLineLayer is enabled. + */ public enabled(): boolean; + /** + * Enables or disables the DragLineLayer. + * + * @param {boolean} enabled + * @return {DragLineLayer} The calling DragLineLayer. + */ public enabled(enabled: boolean): DragLineLayer; public enabled(enabled?: boolean): any { if (enabled == null) { @@ -128,31 +145,70 @@ export module Components { return this; } + /** + * Sets the callback to be called when dragging starts. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ public onDragStart(callback: DragLineCallback) { this._dragStartCallbacks.add(callback); return this; } + /** + * Removes a callback that would be called when dragging starts. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ public offDragStart(callback: DragLineCallback) { this._dragStartCallbacks.delete(callback); return this; } + /** + * Sets a callback to be called during dragging. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ public onDrag(callback: DragLineCallback) { this._dragCallbacks.add(callback); return this; } + /** + * Removes a callback that would be called during dragging. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ public offDrag(callback: DragLineCallback) { this._dragCallbacks.delete(callback); return this; } + /** + * Sets a callback to be called when dragging ends. + * The callback will be passed the calling DragLineLayer. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ public onDragEnd(callback: DragLineCallback) { this._dragEndCallbacks.add(callback); return this; } + /** + * Removes a callback that would be called when dragging ends. + * + * @param {DragLineCallback} callback + * @returns {DragLineLayer} The calling DragLineLayer. + */ public offDragEnd(callback: DragLineCallback) { this._dragEndCallbacks.delete(callback); return this; From 18891e5df1a5755bd85df7607660edcff41d84a1 Mon Sep 17 00:00:00 2001 From: Cassie Date: Thu, 20 Aug 2015 12:11:51 -0700 Subject: [PATCH 053/160] add scales to dragbox test --- .../overlaying/tests/interactions/dragbox.js | 1 + .../tests/interactions/dragbox_scales.js | 66 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 quicktests/overlaying/tests/interactions/dragbox_scales.js diff --git a/quicktests/overlaying/tests/interactions/dragbox.js b/quicktests/overlaying/tests/interactions/dragbox.js index 720d3e9d6c..9c86558464 100644 --- a/quicktests/overlaying/tests/interactions/dragbox.js +++ b/quicktests/overlaying/tests/interactions/dragbox.js @@ -47,6 +47,7 @@ function run(svg, data, Plottable) { e.selection.attr("fill", "#34be6c"); }); }) + .xScale(xScale) .movable(true); var hover = new Plottable.Interactions.Pointer() diff --git a/quicktests/overlaying/tests/interactions/dragbox_scales.js b/quicktests/overlaying/tests/interactions/dragbox_scales.js new file mode 100644 index 0000000000..0922356ef7 --- /dev/null +++ b/quicktests/overlaying/tests/interactions/dragbox_scales.js @@ -0,0 +1,66 @@ +function makeData() { + "use strict"; + var segment_data = []; + for (var i = 0; i < 10; i++) { segment_data.push({ + "x": i, + "y": Math.random(), + "x2": i + Math.random() + }); } + var rect_data = []; + for (var i = 0; i < 10; i++) { rect_data.push({ + "x": i, + "y": Math.random(), + "x2": i + Math.random() + }); } + return [segment_data, rect_data]; + +} + +function run(svg, data, Plottable) { + "use strict"; + + + var xScale = new Plottable.Scales.Linear(); + var yScale = new Plottable.Scales.Linear(); + + var xAxis = new Plottable.Axes.Numeric(xScale, "bottom"); + var yAxis = new Plottable.Axes.Numeric(yScale, "left"); + + var segment = new Plottable.Plots.Segment() + .x(function(d) { return d.x; }, xScale) + .x2(function(d) { return d.x2; }, xScale) + .y(function(d) { return d.y; }, yScale) + .attr("stroke", "#dddddd") + .addDataset(new Plottable.Dataset(data[0])); + + var rectangle = new Plottable.Plots.Rectangle() + .x(function(d) { return d.x; }, xScale) + .x2(function(d) { return d.x2; }, xScale) + .y(function(d) { return d.y; }, yScale) + .y2(function(d){ return d.y + .1; }, yScale) + .attr("fill", "#dddddd") + .addDataset(new Plottable.Dataset(data[1])); + + + var dbl = new Plottable.Components.DragBoxLayer() + .onDrag(function(bounds){ + segment.entities().forEach(function(e){ + e.selection.attr("stroke", "#dddddd"); + }); + segment.entitiesIn(bounds).forEach(function(e){ + e.selection.attr("stroke", "#be346c"); + }); + rectangle.entities().forEach(function(e){ + e.selection.attr("fill", "#dddddd"); + }); + rectangle.entitiesIn(bounds).forEach(function(e){ + e.selection.attr("fill", "#34be6c"); + }); + }) + .xScale(xScale) + .yScale(yScale) + .movable(true); + + var group = new Plottable.Components.Group([segment, rectangle, dbl]); + new Plottable.Components.Table([[yAxis, group], [null, xAxis]]).renderTo(svg) +} From 99c88ebd8e20fd4eeb934eaab2fe417515931479 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 13:48:50 -0700 Subject: [PATCH 054/160] [refactorDragBoxLayer] CR Applied all suggested changes --- test/components/dragBoxLayerTests.ts | 183 ++++++++++++++++----------- 1 file changed, 107 insertions(+), 76 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index f51bf14ff8..607c220b24 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -3,7 +3,7 @@ describe("Interactive Components", () => { describe("DragBoxLayer", () => { - describe("DragBoxLayer - basics", () => { + describe("Basics usage", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; @@ -25,10 +25,6 @@ describe("Interactive Components", () => { }; }); - afterEach(() => { - svg.remove(); - }); - it("correctly draws box on drag", () => { dbl.renderTo(svg); assert.isFalse(dbl.boxVisible(), "box is hidden initially"); @@ -39,53 +35,76 @@ describe("Interactive Components", () => { let bounds = dbl.bounds(); assert.deepEqual(bounds.topLeft, quarterPoint, "top-left point was set correctly"); assert.deepEqual(bounds.bottomRight, halfPoint, "bottom-right point was set correctly"); + svg.remove(); }); it("dismisses on click", () => { dbl.renderTo(svg); let target = dbl.background(); - TestMethods.triggerFakeDragSequence(target, halfPoint, halfPoint); + assert.isFalse(dbl.boxVisible(), "box is hidden initially"); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); + assert.isTrue(dbl.boxVisible(), "box is drawn on drag"); + + TestMethods.triggerFakeDragSequence(target, halfPoint, halfPoint); assert.isFalse(dbl.boxVisible(), "box is hidden on click"); + svg.remove(); }); - it("clipPath enabled", () => { + it("generates the correct clipPath", () => { dbl.renderTo(svg); TestMethods.verifyClipPath(dbl); let clipRect = ( dbl)._boxContainer.select(".clip-rect"); assert.strictEqual(TestMethods.numAttr(clipRect, "width"), SVG_WIDTH, "the clipRect has an appropriate width"); assert.strictEqual(TestMethods.numAttr(clipRect, "height"), SVG_HEIGHT, "the clipRect has an appropriate height"); + svg.remove(); }); - it("detectionRadius()", () => { - assert.doesNotThrow(() => dbl.detectionRadius(3), Error, "can set detection radius before anchoring"); + it("can get and set the detection radius", () => { + assert.strictEqual(dbl.detectionRadius(), 3, "there is a default detection radius"); + assert.doesNotThrow(() => dbl.detectionRadius(4), Error, "can set detection radius before anchoring"); + dbl.renderTo("svg"); + + assert.strictEqual(dbl.detectionRadius(), 4, "detection radius did not change upon rendering"); + assert.strictEqual(dbl.detectionRadius(5), dbl, "setting the detection radius returns the drag box layer"); + assert.strictEqual(dbl.detectionRadius(), 5, "can retrieve the detection radius"); + + assert.throws(() => dbl.detectionRadius(-1), "detection radius cannot be negative"); + svg.remove(); + }); + + it("applies the given detection radius", () => { dbl.renderTo("svg"); let radius = 5; dbl.detectionRadius(radius); - assert.strictEqual(dbl.detectionRadius(), radius, "can retrieve the detection radius"); + + TestMethods.triggerFakeDragSequence(dbl.background(), quarterPoint, halfPoint); + let edges = dbl.content().selectAll("line"); + assert.strictEqual(edges.size(), 4, "the edges of a rectangle are drawn"); edges.each(function() { let edge = d3.select(this); - assert.strictEqual(edge.style("stroke-width"), 2 * radius, "edge width was set correctly"); + assert.strictEqual(edge.style("stroke-width"), 2 * radius + "px", "edge width was set correctly"); }); let corners = dbl.content().selectAll("circle"); + assert.strictEqual(corners.size(), 4, "the corners of a rectangle are drawn"); corners.each(function() { let corner = d3.select(this); - assert.strictEqual(corner.attr("r"), radius, "corner radius was set correctly"); + assert.strictEqual(corner.attr("r"), "" + radius, "corner radius was set correctly"); }); - // HACKHACK: chai-assert.d.ts has the wrong signature - ( assert.throws)(() => dbl.detectionRadius(-1), Error, "", "rejects negative values"); + svg.remove(); }); - it("destroy() does not error if scales are not inputted", () => { + it("does not error on destroy() if scales are not inputted", () => { assert.doesNotThrow(() => dbl.destroy(), Error, "can destroy"); + svg.remove(); }); - it("onDragStart()", () => { + it("calls the onDragStart callback", () => { dbl.renderTo(svg); let receivedBounds: Plottable.Bounds; @@ -108,9 +127,10 @@ describe("Interactive Components", () => { callbackCalled = false; TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragBoxLayer and not called"); + svg.remove(); }); - it("onDrag()", () => { + it("calls the onDrag callback", () => { dbl.renderTo(svg); let receivedBounds: Plottable.Bounds; @@ -133,9 +153,10 @@ describe("Interactive Components", () => { TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); + svg.remove(); }); - it("onDragEnd()", () => { + it("calls the onDragEnd callback", () => { dbl.renderTo(svg); let receivedBounds: Plottable.Bounds; @@ -157,9 +178,10 @@ describe("Interactive Components", () => { TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isFalse(callbackCalled, "the callback was detached from the dragoBoxLayer and not called"); + svg.remove(); }); - it("multiple drag interaction callbacks", () => { + it("calls all the drag interaction callbacks when needed", () => { dbl.renderTo(svg); let callbackDragStart1Called = false; @@ -211,10 +233,11 @@ describe("Interactive Components", () => { assert.isTrue(callbackDrag2Called, "the callback 2 for drag is still connected"); assert.isFalse(callbackDragEnd1Called, "the callback 1 for drag end was disconnected"); assert.isTrue(callbackDragEnd2Called, "the callback 2 for drag end is still connected"); + svg.remove(); }); }); - describe("DragBoxLayer - enabling/disabling", () => { + describe("Enabling and disabling", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; @@ -226,14 +249,11 @@ describe("Interactive Components", () => { dbl = new Plottable.Components.DragBoxLayer(); }); - afterEach(() => { - svg.remove(); - }); - - it("enabled(boolean) properly modifies the state", () => { + it("can enable / disable the DragBoxLayer", () => { assert.isTrue(dbl.enabled(), "drag box layer is enabled by default"); - assert.strictEqual(dbl.enabled(false), dbl, "enabled(boolean) returns itself"); - assert.isFalse(dbl.enabled(), "drag box layer reports when it is disabled"); + assert.strictEqual(dbl.enabled(false), dbl, "the setter returns the drag box layer"); + assert.isFalse(dbl.enabled(), "drag box layer can be disabled"); + svg.remove(); }); it("disables box when enabled(false)", () => { @@ -256,33 +276,11 @@ describe("Interactive Components", () => { dbl.enabled(true); TestMethods.triggerFakeDragSequence(target, startPoint, endPoint); assert.isTrue(dbl.boxVisible(), "box is shown when enabled"); - }); - - it("does not have resizable CSS classes when enabled(false)", () => { - dbl.resizable(true); - assert.isTrue(dbl.hasClass("x-resizable"), "carries \"x-resizable\" class if resizable"); - assert.isTrue(dbl.hasClass("y-resizable"), "carries \"y-resizable\" class if resizable"); - dbl.enabled(false); - assert.isFalse(dbl.hasClass("x-resizable"), "does not carry \"x-resizable\" class if resizable, but not enabled"); - assert.isFalse(dbl.hasClass("y-resizable"), "does not carry \"y-resizable\" class if resizable, but not enabled"); - dbl.resizable(false); - dbl.enabled(true); - assert.isFalse(dbl.hasClass("x-resizable"), "does not carry \"x-resizable\" class if enabled, but not resizable"); - assert.isFalse(dbl.hasClass("y-resizable"), "does not carry \"y-resizable\" class if enabled, but not resizable"); - }); - - it("does not have movable CSS classe when enabled(false)", () => { - dbl.movable(true); - assert.isTrue(dbl.hasClass("movable"), "carries \"movable\" class if movable"); - dbl.enabled(false); - assert.isFalse(dbl.hasClass("movable"), "does not carry \"movable\" class if movable, but not enabled"); - dbl.movable(false); - dbl.enabled(true); - assert.isFalse(dbl.hasClass("movable"), "does not carry \"movable\" class if enabled, but not movable"); + svg.remove(); }); }); - describe("DragBoxLayer - resizing", () => { + describe("Resizing", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; @@ -316,17 +314,14 @@ describe("Interactive Components", () => { resetBox(); }); - afterEach(() => { - svg.remove(); - }); - - it("resizable() getter/setter", () => { + it("can get/set the resizable property", () => { assert.isFalse(dbl.resizable(), "defaults to false"); - assert.strictEqual(dbl.resizable(true), dbl, "returns DragBoxLayer when invoked as setter"); + assert.strictEqual(dbl.resizable(true), dbl, "the setter returns the drag box layer"); assert.isTrue(dbl.resizable(), "successfully set to true"); + svg.remove(); }); - it("resizable() correctly sets pointer-events", () => { + it("correctly sets pointer-events for resizable DragBoxLayer", () => { dbl.resizable(true); let edges = dbl.content().selectAll("line"); edges[0].forEach((edge) => { @@ -338,9 +333,10 @@ describe("Interactive Components", () => { let computedStyle = window.getComputedStyle( corner); assert.strictEqual(computedStyle.pointerEvents.toLowerCase(), "visiblefill", "pointer-events set correctly on corners"); }); + svg.remove(); }); - it("resize from top edge", () => { + it("can resize from top edge", () => { dbl.resizable(true); TestMethods.triggerFakeDragSequence(target, { x: midPoint.x, y: initialBounds.topLeft.y }, @@ -359,9 +355,10 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.bottomRight.y, SVG_HEIGHT, "can drag through to other side"); + svg.remove(); }); - it("resize from bottom edge", () => { + it("can resize from bottom edge", () => { dbl.resizable(true); TestMethods.triggerFakeDragSequence(target, { x: midPoint.x, y: initialBounds.bottomRight.y }, @@ -380,9 +377,10 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.y, 0, "can drag through to other side"); + svg.remove(); }); - it("resize from left edge", () => { + it("can resize from left edge", () => { dbl.resizable(true); TestMethods.triggerFakeDragSequence(target, { x: initialBounds.topLeft.x, y: midPoint.y }, @@ -401,9 +399,10 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.bottomRight.x, SVG_WIDTH, "can drag through to other side"); + svg.remove(); }); - it("resize from right edge", () => { + it("can resize from right edge", () => { dbl.resizable(true); TestMethods.triggerFakeDragSequence(target, { x: initialBounds.bottomRight.x, y: midPoint.y }, @@ -422,6 +421,7 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.x, 0, "can drag through to other side"); + svg.remove(); }); it("resizes if grabbed within detectionRadius()", () => { @@ -445,6 +445,7 @@ describe("Interactive Components", () => { ); bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.y, startYOutside, "new box was started at the drag start position"); + svg.remove(); }); it("doesn't dismiss on no-op resize", () => { @@ -466,10 +467,25 @@ describe("Interactive Components", () => { ); let bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.y, initialBounds.bottomRight.y, "new box was started at the drag start position"); + svg.remove(); + }); + + it("does not have resizable CSS classes when enabled(false) or resizable(false)", () => { + dbl.resizable(true); + assert.isTrue(dbl.hasClass("x-resizable"), "carries \"x-resizable\" class if resizable"); + assert.isTrue(dbl.hasClass("y-resizable"), "carries \"y-resizable\" class if resizable"); + dbl.enabled(false); + assert.isFalse(dbl.hasClass("x-resizable"), "does not carry \"x-resizable\" class if resizable, but not enabled"); + assert.isFalse(dbl.hasClass("y-resizable"), "does not carry \"y-resizable\" class if resizable, but not enabled"); + dbl.resizable(false); + dbl.enabled(true); + assert.isFalse(dbl.hasClass("x-resizable"), "does not carry \"x-resizable\" class if enabled, but not resizable"); + assert.isFalse(dbl.hasClass("y-resizable"), "does not carry \"y-resizable\" class if enabled, but not resizable"); + svg.remove(); }); }); - describe("DragBoxLayer - moving", () => { + describe("Moving", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 400; @@ -497,19 +513,14 @@ describe("Interactive Components", () => { initialBounds = dbl.bounds(); }); - afterEach(() => { - svg.remove(); - }); - - it("get and set movable()", () => { + it("can get/set the movable() property", () => { assert.isFalse(dbl.movable(), "defaults to false"); - assert.isFalse(dbl.hasClass("movable"), "initially does not have \"movable\" CSS class"); - assert.strictEqual(dbl.movable(true), dbl, "setter mode returns DragBoxLayer"); - assert.isTrue(dbl.movable(), "set to true"); - assert.isTrue(dbl.hasClass("movable"), "\"movable\" CSS class is applied"); + assert.strictEqual(dbl.movable(true), dbl, "setter returns DragBoxLayer"); + assert.isTrue(dbl.movable(), "can set to true"); + svg.remove(); }); - it("move left", () => { + it("can move left", () => { dbl.movable(true); TestMethods.triggerFakeDragSequence(target, { x: midPoint.x, y: midPoint.y }, @@ -520,9 +531,10 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.x, initialBounds.bottomRight.x - dragDistance, "right edge moved"); assert.strictEqual(bounds.topLeft.y, initialBounds.topLeft.y, "top edge did not move"); assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y, "bottom edge did not move"); + svg.remove(); }); - it("move right", () => { + it("can move right", () => { dbl.movable(true); TestMethods.triggerFakeDragSequence(target, { x: midPoint.x, y: midPoint.y }, @@ -533,9 +545,10 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.x, initialBounds.bottomRight.x + dragDistance, "right edge moved"); assert.strictEqual(bounds.topLeft.y, initialBounds.topLeft.y, "top edge did not move"); assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y, "bottom edge did not move"); + svg.remove(); }); - it("move up", () => { + it("can move up", () => { dbl.movable(true); TestMethods.triggerFakeDragSequence(target, { x: midPoint.x, y: midPoint.y }, @@ -546,9 +559,10 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.x, initialBounds.bottomRight.x, "right edge did not move"); assert.strictEqual(bounds.topLeft.y, initialBounds.topLeft.y - dragDistance, "top edge moved"); assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y - dragDistance, "bottom edge moved"); + svg.remove(); }); - it("move down", () => { + it("can move down", () => { dbl.movable(true); TestMethods.triggerFakeDragSequence(target, { x: midPoint.x, y: midPoint.y }, @@ -559,6 +573,7 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.x, initialBounds.bottomRight.x, "right edge did not move"); assert.strictEqual(bounds.topLeft.y, initialBounds.topLeft.y + dragDistance, "top edge moved"); assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y + dragDistance, "bottom edge moved"); + svg.remove(); }); it("does not move if grabbed within detectionRadius() while resizable()", () => { @@ -573,6 +588,7 @@ describe("Interactive Components", () => { assert.strictEqual(bounds.bottomRight.y, initialBounds.bottomRight.y, "bottom edge was not moved"); assert.strictEqual(bounds.topLeft.x, initialBounds.topLeft.x, "left edge was not moved"); assert.strictEqual(bounds.bottomRight.x, SVG_WIDTH, "right edge was repositioned"); + svg.remove(); }); it("doesn't dismiss on no-op move", () => { @@ -584,6 +600,7 @@ describe("Interactive Components", () => { assert.isTrue(dbl.boxVisible(), "box remains visible"); let bounds = dbl.bounds(); assert.deepEqual(bounds, initialBounds, "bounds did not change"); + svg.remove(); }); it("dismisses on click outside of box", () => { @@ -591,6 +608,7 @@ describe("Interactive Components", () => { let origin = { x: 0, y: 0 }; TestMethods.triggerFakeDragSequence(target, origin, origin); assert.isFalse(dbl.boxVisible(), "box is no longer visible"); + svg.remove(); }); it("starts new box if hidden instead of moving", () => { @@ -603,6 +621,19 @@ describe("Interactive Components", () => { let bounds = dbl.bounds(); assert.strictEqual(bounds.topLeft.x, midPoint.x, "new box was started at the drag start position (x)"); assert.strictEqual(bounds.topLeft.y, midPoint.y, "new box was started at the drag start position (y)"); + svg.remove(); + }); + + it("does not have movable CSS classe when enabled(false) or movable(false)", () => { + assert.isFalse(dbl.hasClass("movable"), "initially does not have \"movable\" CSS class"); + dbl.movable(true); + assert.isTrue(dbl.hasClass("movable"), "carries \"movable\" class if movable"); + dbl.enabled(false); + assert.isFalse(dbl.hasClass("movable"), "does not carry \"movable\" class if movable, but not enabled"); + dbl.movable(false); + dbl.enabled(true); + assert.isFalse(dbl.hasClass("movable"), "does not carry \"movable\" class if enabled, but not movable"); + svg.remove(); }); }); }); From 97ce5ab3d5772d207411eea189dc0ba54b1a1896 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 13:54:24 -0700 Subject: [PATCH 055/160] [refactorDragBoxLayer] CR Part 2 --- test/components/dragBoxLayerTests.ts | 65 ++++++++++++++++------------ 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 607c220b24..433dffe539 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -181,58 +181,67 @@ describe("Interactive Components", () => { svg.remove(); }); - it("calls all the drag interaction callbacks when needed", () => { + it("can register two callbacks for the same event", () => { dbl.renderTo(svg); let callbackDragStart1Called = false; let callbackDragStart2Called = false; - let callbackDrag1Called = false; - let callbackDrag2Called = false; - let callbackDragEnd1Called = false; - let callbackDragEnd2Called = false; let callbackDragStart1 = () => callbackDragStart1Called = true; let callbackDragStart2 = () => callbackDragStart2Called = true; - let callbackDrag1 = () => callbackDrag1Called = true; - let callbackDrag2 = () => callbackDrag2Called = true; - let callbackDragEnd1 = () => callbackDragEnd1Called = true; - let callbackDragEnd2 = () => callbackDragEnd2Called = true; dbl.onDragStart(callbackDragStart1); dbl.onDragStart(callbackDragStart2); - dbl.onDrag(callbackDrag1); - dbl.onDrag(callbackDrag2); - dbl.onDragEnd(callbackDragEnd1); - dbl.onDragEnd(callbackDragEnd2); let target = dbl.background(); TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isTrue(callbackDragStart1Called, "the callback 1 for drag start was called"); assert.isTrue(callbackDragStart2Called, "the callback 2 for drag start was called"); - assert.isTrue(callbackDrag1Called, "the callback 1 for drag was called"); - assert.isTrue(callbackDrag2Called, "the callback 2 for drag was called"); - assert.isTrue(callbackDragEnd1Called, "the callback 1 for drag end was called"); - assert.isTrue(callbackDragEnd2Called, "the callback 2 for drag end was called"); dbl.offDragStart(callbackDragStart1); - dbl.offDrag(callbackDrag1); - dbl.offDragEnd(callbackDragEnd1); - callbackDragStart1Called = false; callbackDragStart2Called = false; - callbackDrag1Called = false; - callbackDrag2Called = false; - callbackDragEnd1Called = false; - callbackDragEnd2Called = false; TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); assert.isFalse(callbackDragStart1Called, "the callback 1 for drag start was disconnected"); assert.isTrue(callbackDragStart2Called, "the callback 2 for drag start is still connected"); - assert.isFalse(callbackDrag1Called, "the callback 1 for drag was called disconnected"); - assert.isTrue(callbackDrag2Called, "the callback 2 for drag is still connected"); - assert.isFalse(callbackDragEnd1Called, "the callback 1 for drag end was disconnected"); - assert.isTrue(callbackDragEnd2Called, "the callback 2 for drag end is still connected"); + svg.remove(); + }); + + it("calls all the drag interaction callbacks when needed", () => { + dbl.renderTo(svg); + + let callbackDragStartCalled = false; + let callbackDragCalled = false; + let callbackDragEndCalled = false; + + let callbackDragStart = () => callbackDragStartCalled = true; + let callbackDrag = () => callbackDragCalled = true; + let callbackDragEnd = () => callbackDragEndCalled = true; + + dbl.onDragStart(callbackDragStart); + dbl.onDrag(callbackDrag); + dbl.onDragEnd(callbackDragEnd); + + let target = dbl.background(); + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); + + assert.isTrue(callbackDragStartCalled, "the callback for drag start was called"); + assert.isTrue(callbackDragCalled, "the callback for drag was called"); + assert.isTrue(callbackDragEndCalled, "the callback for drag end was called"); + + dbl.offDragStart(callbackDragStart); + dbl.offDrag(callbackDrag); + dbl.offDragEnd(callbackDragEnd); + + callbackDragStartCalled = false; + callbackDragCalled = false; + + TestMethods.triggerFakeDragSequence(target, quarterPoint, halfPoint); + assert.isFalse(callbackDragStartCalled, "the callback for drag start was disconnected"); + assert.isFalse(callbackDragCalled, "the callback for drag was disconnected"); + assert.isTrue(callbackDragEndCalled, "the callback for drag end is still connected"); svg.remove(); }); }); From ad01aa2099f07a1ce96e258539098845923e5858 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 14:00:50 -0700 Subject: [PATCH 056/160] [refactorDragBoxLayer] fixed browser incompatibilities --- test/components/dragBoxLayerTests.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 433dffe539..1ad6ea0eb4 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -87,13 +87,15 @@ describe("Interactive Components", () => { assert.strictEqual(edges.size(), 4, "the edges of a rectangle are drawn"); edges.each(function() { let edge = d3.select(this); - assert.strictEqual(edge.style("stroke-width"), 2 * radius + "px", "edge width was set correctly"); + let strokeWidth = parseFloat(edge.style("stroke-width")); + assert.strictEqual(strokeWidth, 2 * radius, "edge width was set correctly"); }); let corners = dbl.content().selectAll("circle"); assert.strictEqual(corners.size(), 4, "the corners of a rectangle are drawn"); corners.each(function() { let corner = d3.select(this); - assert.strictEqual(corner.attr("r"), "" + radius, "corner radius was set correctly"); + let cornerRadius = parseFloat(corner.attr("r")); + assert.strictEqual(cornerRadius, radius, "corner radius was set correctly"); }); svg.remove(); From 5afb972f179facd73d9135ed1bd0b162b1a693d1 Mon Sep 17 00:00:00 2001 From: Cassie Date: Thu, 20 Aug 2015 14:04:13 -0700 Subject: [PATCH 057/160] renderTo() now accepts DOM nodes Closes #1819. --- plottable.d.ts | 2 +- plottable.js | 3 +++ src/components/component.ts | 4 +++- test/components/componentTests.ts | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/plottable.d.ts b/plottable.d.ts index b9d05c0be5..33fd931256 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -1449,7 +1449,7 @@ declare module Plottable { * @param {String|d3.Selection} element A selector-string for the , or a d3 selection containing an . * @returns {Component} The calling Component. */ - renderTo(element: String | d3.Selection): Component; + renderTo(element: String | SVGSVGElement | d3.Selection): Component; /** * Gets the x alignment of the Component. */ diff --git a/plottable.js b/plottable.js index 9c3a5af314..5a976bdd5d 100644 --- a/plottable.js +++ b/plottable.js @@ -3161,6 +3161,9 @@ var Plottable; if (typeof (element) === "string") { selection = d3.select(element); } + else if (element instanceof SVGSVGElement) { + selection = d3.select(element); + } else { selection = element; } diff --git a/src/components/component.ts b/src/components/component.ts index 475e0fc3d4..2034194c2f 100644 --- a/src/components/component.ts +++ b/src/components/component.ts @@ -262,12 +262,14 @@ export class Component { * @param {String|d3.Selection} element A selector-string for the , or a d3 selection containing an . * @returns {Component} The calling Component. */ - public renderTo(element: String | d3.Selection): Component { + public renderTo(element: String | SVGSVGElement | d3.Selection): Component { this.detach(); if (element != null) { let selection: d3.Selection; if (typeof(element) === "string") { selection = d3.select( element); + } else if (element instanceof SVGSVGElement) { + selection = d3.select( element); } else { selection = > element; } diff --git a/test/components/componentTests.ts b/test/components/componentTests.ts index 40dc210bd7..690c1eb579 100644 --- a/test/components/componentTests.ts +++ b/test/components/componentTests.ts @@ -445,6 +445,20 @@ describe("Component behavior", () => { svg.remove(); }); + it("renderTo() only accepts strings, selections containing svgs, and SVG elements", () => { + svg.attr("id", "render-to-test"); + assert.doesNotThrow(() => c.renderTo("#render-to-test"), Error, "accepts strings that identify svgs"); + assert.doesNotThrow(() => c.renderTo(svg), Error, "accepts selections that contain svgs"); + assert.doesNotThrow(() => c.renderTo( svg.node()), Error, "accepts svg elements"); + let parent = TestMethods.getSVGParent(); + let div = parent.append("div"); + // HACKHACK #2614: chai-assert.d.ts has the wrong signature + ( assert).throws(() => c.renderTo(div), Error, "", "rejects selections that don't contain svgs"); + ( assert).throws(() => c.renderTo("#not-a-element"), Error, "", "rejects strings that don't correspond to DOM elements"); + ( assert).throws(() => c.renderTo(d3.select(null)), Error, "", "rejects empty d3 selections"); + svg.remove(); + }); + describe("origin methods", () => { let cWidth = 100; let cHeight = 100; From 3c82a5a53cac138efba3f949646240c6c8e1a82a Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Thu, 20 Aug 2015 14:12:07 -0700 Subject: [PATCH 058/160] Set "vertical" and "horizontal" CSS classes on GuideLineLayer --- plottable.js | 12 ++++++------ src/components/dragLineLayer.ts | 5 ----- src/components/guideLineLayer.ts | 5 +++++ test/components/guideLineLayerTests.ts | 7 +++++++ 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/plottable.js b/plottable.js index 0c13bf3761..6c0eb7bb9c 100644 --- a/plottable.js +++ b/plottable.js @@ -6242,6 +6242,12 @@ var Plottable; this._orientation = orientation; this._clipPathEnabled = true; this.addClass("guide-line-layer"); + if (this._isVertical()) { + this.addClass("vertical"); + } + else { + this.addClass("horizontal"); + } this._scaleUpdateCallback = function () { _this._syncPixelPositionAndValue(); _this.render(); @@ -11492,12 +11498,6 @@ var Plottable; this._enabled = true; this.addClass("drag-line-layer"); this.addClass("enabled"); - if (this._isVertical()) { - this.addClass("vertical"); - } - else { - this.addClass("horizontal"); - } this._dragInteraction = new Plottable.Interactions.Drag(); this._dragInteraction.attachTo(this); var grabbedLine = function (p) { diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index 0477e00d9b..93f5641694 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -20,11 +20,6 @@ export module Components { super(orientation); this.addClass("drag-line-layer"); this.addClass("enabled"); - if (this._isVertical()) { - this.addClass("vertical"); - } else { - this.addClass("horizontal"); - } this._dragInteraction = new Plottable.Interactions.Drag(); this._dragInteraction.attachTo(this); diff --git a/src/components/guideLineLayer.ts b/src/components/guideLineLayer.ts index cb5977eb53..f307ffe298 100644 --- a/src/components/guideLineLayer.ts +++ b/src/components/guideLineLayer.ts @@ -23,6 +23,11 @@ export module Components { this._orientation = orientation; this._clipPathEnabled = true; this.addClass("guide-line-layer"); + if (this._isVertical()) { + this.addClass("vertical"); + } else { + this.addClass("horizontal"); + } this._scaleUpdateCallback = () => { this._syncPixelPositionAndValue(); this.render(); diff --git a/test/components/guideLineLayerTests.ts b/test/components/guideLineLayerTests.ts index f2dee5bb2f..346c1daebd 100644 --- a/test/components/guideLineLayerTests.ts +++ b/test/components/guideLineLayerTests.ts @@ -1,6 +1,13 @@ /// describe("GuideLineLayer", () => { + it("has \"vertical\" class if vertical, \"horizontal\" class if horizontal", () => { + let verticalGLL = new Plottable.Components.GuideLineLayer("vertical"); + assert.isTrue(verticalGLL.hasClass("vertical"), "vertical GuideLineLayer has \"vertical\" class"); + let horizontalGLL = new Plottable.Components.GuideLineLayer("horizontal"); + assert.isTrue(horizontalGLL.hasClass("horizontal"), "horizontal GuideLineLayer has \"horizontal\" class"); + }); + it("scale()", () => { let gll = new Plottable.Components.GuideLineLayer("vertical"); let timeScale = new Plottable.Scales.Time(); From 5e70a9f9677ac68d67299bc1fce53b326342a693 Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Thu, 20 Aug 2015 14:35:03 -0700 Subject: [PATCH 059/160] Clean up inequality checks. --- plottable.js | 4 ++-- src/components/dragLineLayer.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plottable.js b/plottable.js index 6c0eb7bb9c..2dc9af1656 100644 --- a/plottable.js +++ b/plottable.js @@ -11502,10 +11502,10 @@ var Plottable; this._dragInteraction.attachTo(this); var grabbedLine = function (p) { return (_this._isVertical() && - p.x >= _this.pixelPosition() - _this.detectionRadius() && + _this.pixelPosition() - _this.detectionRadius() <= p.x && p.x <= _this.pixelPosition() + _this.detectionRadius()) || (!_this._isVertical() && - p.y >= _this.pixelPosition() - _this.detectionRadius() && + _this.pixelPosition() - _this.detectionRadius() <= p.y && p.y <= _this.pixelPosition() + _this.detectionRadius()); }; var dragging = false; diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index 93f5641694..306cb548b5 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -26,12 +26,12 @@ export module Components { let grabbedLine = (p: Point) => { return (this._isVertical() && - p.x >= this.pixelPosition() - this.detectionRadius() && + this.pixelPosition() - this.detectionRadius() <= p.x && p.x <= this.pixelPosition() + this.detectionRadius() ) || ( !this._isVertical() && - p.y >= this.pixelPosition() - this.detectionRadius() && + this.pixelPosition() - this.detectionRadius() <= p.y && p.y <= this.pixelPosition() + this.detectionRadius() ); }; From fc0ceff073b52038c7e2249b0d3b76a7ebb3cf8b Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Thu, 20 Aug 2015 15:03:18 -0700 Subject: [PATCH 060/160] Rename callback variables. --- plottable.js | 25 ++++++++++----------- src/components/dragLineLayer.ts | 31 +++++++++++++++------------ test/components/dragLineLayerTests.ts | 1 + 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/plottable.js b/plottable.js index 2dc9af1656..b874a0be4e 100644 --- a/plottable.js +++ b/plottable.js @@ -11509,32 +11509,33 @@ var Plottable; p.y <= _this.pixelPosition() + _this.detectionRadius()); }; var dragging = false; - var dragStartCallback = function (start) { + var interactionDragStartCallback = function (start) { if (grabbedLine(start)) { dragging = true; _this._dragStartCallbacks.callCallbacks(_this); } }; - this._dragInteraction.onDragStart(dragStartCallback); - var dragCallback = function (start, end) { + this._dragInteraction.onDragStart(interactionDragStartCallback); + var interactionDragCallback = function (start, end) { if (dragging) { _this._setPixelPositionWithoutChangingMode(_this._isVertical() ? end.x : end.y); _this._dragCallbacks.callCallbacks(_this); } }; - this._dragInteraction.onDrag(dragCallback); - var dragEndCallback = function (start, end) { + this._dragInteraction.onDrag(interactionDragCallback); + var interactionDragEndCallback = function (start, end) { if (dragging) { dragging = false; _this._dragEndCallbacks.callCallbacks(_this); } }; - this._dragInteraction.onDragEnd(dragEndCallback); - this._disconnectInteractionCallbacks = function () { - _this._dragInteraction.offDragStart(dragStartCallback); - _this._dragInteraction.offDrag(dragCallback); - _this._dragInteraction.offDragEnd(dragEndCallback); - delete _this._disconnectInteractionCallbacks; + this._dragInteraction.onDragEnd(interactionDragEndCallback); + this._disconnectInteraction = function () { + _this._dragInteraction.offDragStart(interactionDragStartCallback); + _this._dragInteraction.offDrag(interactionDragCallback); + _this._dragInteraction.offDragEnd(interactionDragEndCallback); + _this._dragInteraction.detachFrom(_this); + delete _this._disconnectInteraction; }; this._dragStartCallbacks = new Plottable.Utils.CallbackSet(); this._dragCallbacks = new Plottable.Utils.CallbackSet(); @@ -11653,7 +11654,7 @@ var Plottable; this._dragStartCallbacks.forEach(function (callback) { return _this._dragStartCallbacks.delete(callback); }); this._dragCallbacks.forEach(function (callback) { return _this._dragCallbacks.delete(callback); }); this._dragEndCallbacks.forEach(function (callback) { return _this._dragEndCallbacks.delete(callback); }); - this._disconnectInteractionCallbacks(); + this._disconnectInteraction(); }; return DragLineLayer; })(Components.GuideLineLayer); diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index 306cb548b5..ec46be908a 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -14,7 +14,7 @@ export module Components { private _dragStartCallbacks: Utils.CallbackSet>; private _dragCallbacks: Utils.CallbackSet>; private _dragEndCallbacks: Utils.CallbackSet>; - private _disconnectInteractionCallbacks: () => void; + private _disconnectInteraction: () => void; constructor(orientation: string) { super(orientation); @@ -37,33 +37,36 @@ export module Components { }; let dragging = false; - let dragStartCallback = (start: Point) => { + let interactionDragStartCallback = (start: Point) => { if (grabbedLine(start)) { dragging = true; this._dragStartCallbacks.callCallbacks(this); } }; - this._dragInteraction.onDragStart(dragStartCallback); - let dragCallback = (start: Point, end: Point) => { + this._dragInteraction.onDragStart(interactionDragStartCallback); + + let interactionDragCallback = (start: Point, end: Point) => { if (dragging) { this._setPixelPositionWithoutChangingMode(this._isVertical() ? end.x : end.y); this._dragCallbacks.callCallbacks(this); } }; - this._dragInteraction.onDrag(dragCallback); - let dragEndCallback = (start: Point, end: Point) => { + this._dragInteraction.onDrag(interactionDragCallback); + + let interactionDragEndCallback = (start: Point, end: Point) => { if (dragging) { dragging = false; this._dragEndCallbacks.callCallbacks(this); } }; - this._dragInteraction.onDragEnd(dragEndCallback); - - this._disconnectInteractionCallbacks = () => { - this._dragInteraction.offDragStart(dragStartCallback); - this._dragInteraction.offDrag(dragCallback); - this._dragInteraction.offDragEnd(dragEndCallback); - delete this._disconnectInteractionCallbacks; + this._dragInteraction.onDragEnd(interactionDragEndCallback); + + this._disconnectInteraction = () => { + this._dragInteraction.offDragStart(interactionDragStartCallback); + this._dragInteraction.offDrag(interactionDragCallback); + this._dragInteraction.offDragEnd(interactionDragEndCallback); + this._dragInteraction.detachFrom(this); + delete this._disconnectInteraction; }; this._dragStartCallbacks = new Utils.CallbackSet>(); @@ -214,7 +217,7 @@ export module Components { this._dragStartCallbacks.forEach((callback) => this._dragStartCallbacks.delete(callback)); this._dragCallbacks.forEach((callback) => this._dragCallbacks.delete(callback)); this._dragEndCallbacks.forEach((callback) => this._dragEndCallbacks.delete(callback)); - this._disconnectInteractionCallbacks(); + this._disconnectInteraction(); } } } diff --git a/test/components/dragLineLayerTests.ts b/test/components/dragLineLayerTests.ts index 40d919fa12..84abe136a1 100644 --- a/test/components/dragLineLayerTests.ts +++ b/test/components/dragLineLayerTests.ts @@ -523,6 +523,7 @@ describe("Interactive Components", () => { assert.strictEqual(interactionStartCallbacks.size, 0, "Interaction dragStart callbacks removed on destroy()"); assert.strictEqual(interactionCallbacks.size, 0, "Interaction drag callbacks removed on destroy()"); assert.strictEqual(interactionEndCallbacks.size, 0, "Interaction drag end callbacks removed on destroy()"); + assert.notStrictEqual(( dragInteraction)._componentAttachedTo, dll, "Interaction was detached"); }); }); }); From 4ad7b175c7784436b283f477d5d7b469e04ee7f9 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 15:56:24 -0700 Subject: [PATCH 061/160] [refactorRectangle] amended broken test --- test/plots/rectanglePlotTests.ts | 123 +++++++++++++++++++------------ 1 file changed, 77 insertions(+), 46 deletions(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index 1807ba455e..e812f466c8 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -3,15 +3,26 @@ describe("Plots", () => { describe("RectanglePlot", () => { describe("Basic usage", () => { - let data = [ - { x: 0, y: 0, x2: 1, y2: 1 }, - { x: 1, y: 1, x2: 2, y2: 2 }, - { x: 2, y: 2, x2: 3, y2: 3 }, - { x: 3, y: 3, x2: 4, y2: 4 }, - { x: 4, y: 4, x2: 5, y2: 5 } - ]; - let verifyCells = (cells: d3.Selection) => { - assert.strictEqual(cells[0].length, 5); + it("has correct rectangle heights and positions (renders correctly)", () => { + let data = [ + { x: 0, y: 0, x2: 1, y2: 1 }, + { x: 1, y: 1, x2: 2, y2: 2 }, + { x: 2, y: 2, x2: 3, y2: 3 }, + { x: 3, y: 3, x2: 4, y2: 4 }, + { x: 4, y: 4, x2: 5, y2: 5 } + ]; + + let svg = TestMethods.generateSVG(300, 300); + let xScale = new Plottable.Scales.Linear(); + let yScale = new Plottable.Scales.Linear(); + let plot = new Plottable.Plots.Rectangle(); + plot.x((d) => d.x, xScale).x2((d) => d.x2); + plot.y((d) => d.y, yScale).y2((d) => d.y2); + plot.addDataset(new Plottable.Dataset(data)); + plot.renderTo(svg); + + let cells = plot.content().selectAll("rect"); + assert.strictEqual(cells.size(), data.length); cells.each(function(d, i) { let cell = d3.select(this); assert.closeTo(+cell.attr("height"), 50, 0.5, "Cell height is correct"); @@ -19,7 +30,18 @@ describe("Plots", () => { assert.closeTo(+cell.attr("x"), 25 + 50 * i, 0.5, "Cell x coordinate is correct"); assert.closeTo(+cell.attr("y"), 25 + 50 * (cells[0].length - i - 1), 0.5, "Cell y coordinate is correct"); }); - }; + svg.remove(); + }); + }); + + describe("entities", () => { + let data = [ + { x: 0, y: 0, x2: 1, y2: 1 }, + { x: 1, y: 1, x2: 2, y2: 2 }, + { x: 2, y: 2, x2: 3, y2: 3 }, + { x: 3, y: 3, x2: 4, y2: 4 }, + { x: 4, y: 4, x2: 5, y2: 5 } + ]; let svg: d3.Selection; let xScale: Plottable.Scales.Linear; @@ -35,14 +57,6 @@ describe("Plots", () => { plot.y((d) => d.y, yScale).y2((d) => d.y2); }); - it("has correct rectangle heights and positions (renders correctly)", () => { - plot.addDataset(new Plottable.Dataset(data)); - plot.renderTo(svg); - - verifyCells(plot.content().selectAll("rect")); - svg.remove(); - }); - it("retrieves the correct entity under a point", () => { plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); @@ -108,7 +122,7 @@ describe("Plots", () => { svg = TestMethods.generateSVG(300, 300); }); - it("adjusts the xScale domain with respect to the yScale domain when autorangeMode on x", () => { + it("adjusts the xScale domain with respect to the yScale domain when autorangeMode is set to x", () => { let data = [ { y: "A", x: 0, x2: 1 }, { y: "B", x: 1, x2: 2 } @@ -136,7 +150,7 @@ describe("Plots", () => { svg.remove(); }); - it("adjusts the yScale domain with respect to the xScale domain when autorangeMode on y", () => { + it("adjusts the yScale domain with respect to the xScale domain when autorangeMode is set to y", () => { let data = [ { x: "A", y: 0, y2: 1 }, { x: "B", y: 1, y2: 2 } @@ -210,7 +224,7 @@ describe("Plots", () => { }); }); - describe("Grids", () => { + describe("Plots based on Category Scales", () => { let SVG_WIDTH = 400; let SVG_HEIGHT = 200; let data = [ @@ -291,8 +305,6 @@ describe("Plots", () => { }); it("renders correctly when there isn't data for every spot", () => { - let CELL_HEIGHT = 50; - let CELL_WIDTH = 100; let dataset = new Plottable.Dataset(); let plot = new Plottable.Plots.Rectangle(); plot.addDataset(dataset); @@ -309,12 +321,14 @@ describe("Plots", () => { dataset.data(data); let cells = plot.content().selectAll("rect")[0]; assert.strictEqual(cells.length, data.length); + let cellHeight = 50; + let cellWidth = 100; for (let i = 0; i < cells.length; i++) { let cell = d3.select(cells[i]); - assert.strictEqual(cell.attr("x"), String(i * CELL_WIDTH), "Cell x coord is correct"); - assert.strictEqual(cell.attr("y"), String(i * CELL_HEIGHT), "Cell y coord is correct"); - assert.strictEqual(cell.attr("width"), String(CELL_WIDTH), "Cell width is correct"); - assert.strictEqual(cell.attr("height"), String(CELL_HEIGHT), "Cell height is correct"); + assert.strictEqual(cell.attr("x"), String(i * cellWidth), "Cell x coord is correct"); + assert.strictEqual(cell.attr("y"), String(i * cellHeight), "Cell y coord is correct"); + assert.strictEqual(cell.attr("width"), String(cellWidth), "Cell width is correct"); + assert.strictEqual(cell.attr("height"), String(cellHeight), "Cell height is correct"); } svg.remove(); }); @@ -329,28 +343,45 @@ describe("Plots", () => { yScale.domain(["U", "V"]); - let cells = plot.content().selectAll("rect")[0]; - let cellAU = d3.select(cells[0]); - let cellAV = d3.select(cells[2]); - cellAU.attr("fill", "#000000"); - cellAU.attr("x", "0"); - cellAU.attr("y", "100"); + let cells = plot.content().selectAll("rect"); + assert.strictEqual(cells.size(), data.length, data.length + " cells are drawn"); + let cellAU = d3.select(cells[0][0]); + let cellAV = d3.select(cells[0][2]); - cellAV.attr("fill", "#ffffff"); - cellAV.attr("x", "0"); - cellAV.attr("y", "0"); + let checksDone = 0; + cells.each(function() { + let cell = d3.select(this); + if (cell.attr("x") === "0" && cell.attr("y") === "0") { + assert.strictEqual(cell.attr("fill"), "#000000", "top-left cell is black"); + checksDone++; + } + if (cell.attr("x") === "0" && cell.attr("y") === "100") { + assert.strictEqual(cell.attr("fill"), "#ffffff", "bottom-left cell is black"); + checksDone++; + } + }); + assert.strictEqual(checksDone, 2, "checked all both cells we were interested in"); yScale.domain(["V", "U"]); - cells = plot.content().selectAll("rect")[0]; - cellAU = d3.select(cells[0]); - cellAV = d3.select(cells[2]); - cellAU.attr("fill", "#000000"); - cellAU.attr("x", "0"); - cellAU.attr("y", "0"); - - cellAV.attr("fill", "#ffffff"); - cellAV.attr("x", "0"); - cellAV.attr("y", "100"); + + cells = plot.content().selectAll("rect"); + assert.strictEqual(cells.size(), data.length, data.length + " cells are drawn"); + cellAU = d3.select(cells[0][0]); + cellAV = d3.select(cells[0][2]); + + checksDone = 0; + cells.each(function() { + let cell = d3.select(this); + if (cell.attr("x") === "0" && cell.attr("y") === "0") { + assert.strictEqual(cell.attr("fill"), "#ffffff", "top-left cell is black"); + checksDone++; + } + if (cell.attr("x") === "0" && cell.attr("y") === "100") { + assert.strictEqual(cell.attr("fill"), "#000000", "bottom-left cell is black"); + checksDone++; + } + }); + assert.strictEqual(checksDone, 2, "checked all both cells we were interested in"); svg.remove(); }); }); From 50b7b5c6ded90f65e94a3fb1ca9b58286046074a Mon Sep 17 00:00:00 2001 From: Justin Lan Date: Thu, 20 Aug 2015 16:02:03 -0700 Subject: [PATCH 062/160] Rename helper function, don't delete cleanup method Nothing bad comes of calling the cleanup method twice, so leaving it around. --- plottable.js | 5 ++--- src/components/dragLineLayer.ts | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/plottable.js b/plottable.js index b874a0be4e..9244e15938 100644 --- a/plottable.js +++ b/plottable.js @@ -11500,7 +11500,7 @@ var Plottable; this.addClass("enabled"); this._dragInteraction = new Plottable.Interactions.Drag(); this._dragInteraction.attachTo(this); - var grabbedLine = function (p) { + var onLine = function (p) { return (_this._isVertical() && _this.pixelPosition() - _this.detectionRadius() <= p.x && p.x <= _this.pixelPosition() + _this.detectionRadius()) || @@ -11510,7 +11510,7 @@ var Plottable; }; var dragging = false; var interactionDragStartCallback = function (start) { - if (grabbedLine(start)) { + if (onLine(start)) { dragging = true; _this._dragStartCallbacks.callCallbacks(_this); } @@ -11535,7 +11535,6 @@ var Plottable; _this._dragInteraction.offDrag(interactionDragCallback); _this._dragInteraction.offDragEnd(interactionDragEndCallback); _this._dragInteraction.detachFrom(_this); - delete _this._disconnectInteraction; }; this._dragStartCallbacks = new Plottable.Utils.CallbackSet(); this._dragCallbacks = new Plottable.Utils.CallbackSet(); diff --git a/src/components/dragLineLayer.ts b/src/components/dragLineLayer.ts index ec46be908a..02c72d5207 100644 --- a/src/components/dragLineLayer.ts +++ b/src/components/dragLineLayer.ts @@ -24,7 +24,7 @@ export module Components { this._dragInteraction = new Plottable.Interactions.Drag(); this._dragInteraction.attachTo(this); - let grabbedLine = (p: Point) => { + let onLine = (p: Point) => { return (this._isVertical() && this.pixelPosition() - this.detectionRadius() <= p.x && p.x <= this.pixelPosition() + this.detectionRadius() @@ -38,7 +38,7 @@ export module Components { let dragging = false; let interactionDragStartCallback = (start: Point) => { - if (grabbedLine(start)) { + if (onLine(start)) { dragging = true; this._dragStartCallbacks.callCallbacks(this); } @@ -66,7 +66,6 @@ export module Components { this._dragInteraction.offDrag(interactionDragCallback); this._dragInteraction.offDragEnd(interactionDragEndCallback); this._dragInteraction.detachFrom(this); - delete this._disconnectInteraction; }; this._dragStartCallbacks = new Utils.CallbackSet>(); From 3ed821d88ca891b4416a40e6945b66bdbccbd913 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 16:03:37 -0700 Subject: [PATCH 063/160] [refactorRectangle] Finished implementing CR suggestions --- test/plots/rectanglePlotTests.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index e812f466c8..a8d564f073 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -423,6 +423,8 @@ describe("Plots", () => { it("retrieves all selections with no args", () => { let allCells = plot.selections(); assert.strictEqual(allCells.size(), 4, "all cells retrieved"); + let selectionData = allCells.data(); + assert.includeMembers(selectionData, data, "data in selection data"); svg.remove(); }); @@ -468,7 +470,7 @@ describe("Plots", () => { .label((d: any) => d.val); }); - it("displays rectangle labels by default", () => { + it("does not display rectangle labels by default", () => { let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); let texts = svg.selectAll("text")[0].map((n: any) => d3.select(n).text()); From 448e1a1d8d61d89dc696500c4bb0e87ad33b1d07 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 16:05:47 -0700 Subject: [PATCH 064/160] [refactorRectangle] no longer mentioning that we are counting for the number of labels, because we always do that anyway --- test/plots/rectanglePlotTests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/plots/rectanglePlotTests.ts b/test/plots/rectanglePlotTests.ts index a8d564f073..88c52978ed 100644 --- a/test/plots/rectanglePlotTests.ts +++ b/test/plots/rectanglePlotTests.ts @@ -478,7 +478,7 @@ describe("Plots", () => { svg.remove(); }); - it("renders correct number of labels with the correct text", () => { + it("renders correct text for the labels", () => { let svg = TestMethods.generateSVG(150, 300); plot.renderTo(svg); plot.labelsEnabled(true); From 33c971af2e8b16ca08c3fc55af42ef8bb15a4273 Mon Sep 17 00:00:00 2001 From: Cassie Date: Thu, 20 Aug 2015 16:12:31 -0700 Subject: [PATCH 065/160] SVGSVGElement to HTMLElement. add and clean up tests --- plottable.d.ts | 2 +- plottable.js | 2 +- src/components/component.ts | 6 +++--- test/components/componentTests.ts | 5 +++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/plottable.d.ts b/plottable.d.ts index 33fd931256..575bcaeedb 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -1449,7 +1449,7 @@ declare module Plottable { * @param {String|d3.Selection} element A selector-string for the , or a d3 selection containing an . * @returns {Component} The calling Component. */ - renderTo(element: String | SVGSVGElement | d3.Selection): Component; + renderTo(element: String | HTMLElement | d3.Selection): Component; /** * Gets the x alignment of the Component. */ diff --git a/plottable.js b/plottable.js index 5a976bdd5d..40a4440831 100644 --- a/plottable.js +++ b/plottable.js @@ -3161,7 +3161,7 @@ var Plottable; if (typeof (element) === "string") { selection = d3.select(element); } - else if (element instanceof SVGSVGElement) { + else if (element instanceof HTMLElement) { selection = d3.select(element); } else { diff --git a/src/components/component.ts b/src/components/component.ts index 2034194c2f..7303d96ac1 100644 --- a/src/components/component.ts +++ b/src/components/component.ts @@ -262,14 +262,14 @@ export class Component { * @param {String|d3.Selection} element A selector-string for the , or a d3 selection containing an . * @returns {Component} The calling Component. */ - public renderTo(element: String | SVGSVGElement | d3.Selection): Component { + public renderTo(element: String | HTMLElement | d3.Selection): Component { this.detach(); if (element != null) { let selection: d3.Selection; if (typeof(element) === "string") { selection = d3.select( element); - } else if (element instanceof SVGSVGElement) { - selection = d3.select( element); + } else if (element instanceof HTMLElement) { + selection = d3.select( element); } else { selection = > element; } diff --git a/test/components/componentTests.ts b/test/components/componentTests.ts index 690c1eb579..c777abcf51 100644 --- a/test/components/componentTests.ts +++ b/test/components/componentTests.ts @@ -449,14 +449,15 @@ describe("Component behavior", () => { svg.attr("id", "render-to-test"); assert.doesNotThrow(() => c.renderTo("#render-to-test"), Error, "accepts strings that identify svgs"); assert.doesNotThrow(() => c.renderTo(svg), Error, "accepts selections that contain svgs"); - assert.doesNotThrow(() => c.renderTo( svg.node()), Error, "accepts svg elements"); + assert.doesNotThrow(() => c.renderTo( document.getElementById("render-to-test")), Error, "accepts svg elements"); let parent = TestMethods.getSVGParent(); let div = parent.append("div"); // HACKHACK #2614: chai-assert.d.ts has the wrong signature ( assert).throws(() => c.renderTo(div), Error, "", "rejects selections that don't contain svgs"); + ( assert).throws(() => c.renderTo( div[0][0]), Error, "", "rejects DOM nodes that are not svgs"); ( assert).throws(() => c.renderTo("#not-a-element"), Error, "", "rejects strings that don't correspond to DOM elements"); ( assert).throws(() => c.renderTo(d3.select(null)), Error, "", "rejects empty d3 selections"); - svg.remove(); + //svg.remove(); }); describe("origin methods", () => { From 791a6c239eaccc186b2717bce0aa34f16f53ebe1 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 16:12:47 -0700 Subject: [PATCH 066/160] [refactorSegment] amended test names and describes --- test/plots/segmentPlotTests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index 6df333c071..4be8085e0c 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -3,7 +3,7 @@ describe("Plots", () => { describe("SegmentPlot", () => { - describe("Basics", () => { + describe("Basic Usage", () => { let svg: d3.Selection; let xScale: Plottable.Scales.Linear; let yScale: Plottable.Scales.Linear; @@ -67,7 +67,7 @@ describe("Plots", () => { svg.remove(); }); - it("autorangeMode(\"x\")", () => { + it("adjusts the xScale domain with respect to the yScale domain when autorangeMode is set to x", () => { let staggeredData = [ { y: 0, x: 0, x2: 1 }, { y: 1, x: 1, x2: 2 } @@ -93,7 +93,7 @@ describe("Plots", () => { svg.remove(); }); - it("autorangeMode(\"y\")", () => { + it("adjusts the yScale domain with respect to the xScale domain when autorangeMode is set to y", () => { let staggeredData = [ { x: 0, y: 0, y2: 1 }, { x: 1, y: 1, y2: 2 } From 436fa71f857b987873832a61483d64f8f2cf7bf5 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 16:20:43 -0700 Subject: [PATCH 067/160] [refactorSegment] added ideas from other CRs --- test/plots/segmentPlotTests.ts | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index 4be8085e0c..48d96371a4 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -45,7 +45,9 @@ describe("Plots", () => { plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); - plot.content().selectAll("line").each(function() { + let lines = plot.content().selectAll("line"); + assert.strictEqual(lines.size(), data.length, "correct number of lines has been drawn"); + lines.each(function() { let lineSelection = d3.select(this); assert.strictEqual(lineSelection.attr("x1"), lineSelection.attr("x2"), "line is vertical"); }); @@ -60,19 +62,34 @@ describe("Plots", () => { plot.addDataset(new Plottable.Dataset(data)); plot.renderTo(svg); - plot.content().selectAll("line").each(function() { + let lines = plot.content().selectAll("line"); + assert.strictEqual(lines.size(), data.length, "correct number of lines has been drawn"); + lines.each(function() { let lineSelection = d3.select(this); assert.strictEqual(lineSelection.attr("y1"), lineSelection.attr("y2"), "line is horizontal"); }); svg.remove(); }); + }); + + describe("autorangeMode", () => { + let svg: d3.Selection; + let xScale: Plottable.Scales.Linear; + let yScale: Plottable.Scales.Linear; + + beforeEach(() => { + svg = TestMethods.generateSVG(500, 500); + xScale = new Plottable.Scales.Linear(); + yScale = new Plottable.Scales.Linear(); + xScale.padProportion(0); + yScale.padProportion(0); + }); it("adjusts the xScale domain with respect to the yScale domain when autorangeMode is set to x", () => { let staggeredData = [ { y: 0, x: 0, x2: 1 }, { y: 1, x: 1, x2: 2 } ]; - xScale.padProportion(0); let plot = new Plottable.Plots.Segment(); plot.x((d) => d.x, xScale); @@ -98,7 +115,6 @@ describe("Plots", () => { { x: 0, y: 0, y2: 1 }, { x: 1, y: 1, y2: 2 } ]; - yScale.padProportion(0); let plot = new Plottable.Plots.Segment(); plot.x((d) => d.x, xScale); From 82327dc9fd500098598b93059f33c3647855699c Mon Sep 17 00:00:00 2001 From: Cassie Date: Thu, 20 Aug 2015 16:25:21 -0700 Subject: [PATCH 068/160] Had to change HTMLElement to Element because document.getElementById("render-to-test") was not an instanceof HTMLElement. --- plottable.d.ts | 2 +- plottable.js | 2 +- src/components/component.ts | 6 +++--- test/components/componentTests.ts | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plottable.d.ts b/plottable.d.ts index 575bcaeedb..069caaa43a 100644 --- a/plottable.d.ts +++ b/plottable.d.ts @@ -1449,7 +1449,7 @@ declare module Plottable { * @param {String|d3.Selection} element A selector-string for the , or a d3 selection containing an . * @returns {Component} The calling Component. */ - renderTo(element: String | HTMLElement | d3.Selection): Component; + renderTo(element: String | Element | d3.Selection): Component; /** * Gets the x alignment of the Component. */ diff --git a/plottable.js b/plottable.js index 40a4440831..8a8522d1ee 100644 --- a/plottable.js +++ b/plottable.js @@ -3161,7 +3161,7 @@ var Plottable; if (typeof (element) === "string") { selection = d3.select(element); } - else if (element instanceof HTMLElement) { + else if (element instanceof Element) { selection = d3.select(element); } else { diff --git a/src/components/component.ts b/src/components/component.ts index 7303d96ac1..a962dc1863 100644 --- a/src/components/component.ts +++ b/src/components/component.ts @@ -262,14 +262,14 @@ export class Component { * @param {String|d3.Selection} element A selector-string for the , or a d3 selection containing an . * @returns {Component} The calling Component. */ - public renderTo(element: String | HTMLElement | d3.Selection): Component { + public renderTo(element: String | Element | d3.Selection): Component { this.detach(); if (element != null) { let selection: d3.Selection; if (typeof(element) === "string") { selection = d3.select( element); - } else if (element instanceof HTMLElement) { - selection = d3.select( element); + } else if (element instanceof Element) { + selection = d3.select( element); } else { selection = > element; } diff --git a/test/components/componentTests.ts b/test/components/componentTests.ts index c777abcf51..3583ca775b 100644 --- a/test/components/componentTests.ts +++ b/test/components/componentTests.ts @@ -449,15 +449,15 @@ describe("Component behavior", () => { svg.attr("id", "render-to-test"); assert.doesNotThrow(() => c.renderTo("#render-to-test"), Error, "accepts strings that identify svgs"); assert.doesNotThrow(() => c.renderTo(svg), Error, "accepts selections that contain svgs"); - assert.doesNotThrow(() => c.renderTo( document.getElementById("render-to-test")), Error, "accepts svg elements"); + assert.doesNotThrow(() => c.renderTo(document.getElementById("render-to-test")), Error, "accepts svg elements"); let parent = TestMethods.getSVGParent(); let div = parent.append("div"); // HACKHACK #2614: chai-assert.d.ts has the wrong signature ( assert).throws(() => c.renderTo(div), Error, "", "rejects selections that don't contain svgs"); - ( assert).throws(() => c.renderTo( div[0][0]), Error, "", "rejects DOM nodes that are not svgs"); + ( assert).throws(() => c.renderTo( div.node()), Error, "", "rejects DOM nodes that are not svgs"); ( assert).throws(() => c.renderTo("#not-a-element"), Error, "", "rejects strings that don't correspond to DOM elements"); ( assert).throws(() => c.renderTo(d3.select(null)), Error, "", "rejects empty d3 selections"); - //svg.remove(); + svg.remove(); }); describe("origin methods", () => { From 2e96e4b2747f686a08e39925a7a0ed7ae7feb408 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 16:26:10 -0700 Subject: [PATCH 069/160] [refactorSegment] unsaved Changes --- test/plots/segmentPlotTests.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/plots/segmentPlotTests.ts b/test/plots/segmentPlotTests.ts index 48d96371a4..538fa8053c 100644 --- a/test/plots/segmentPlotTests.ts +++ b/test/plots/segmentPlotTests.ts @@ -141,7 +141,8 @@ describe("Plots", () => { { x: 1, x2: 1, y: 1, y2: 4 }, { x: 2, x2: 3, y: 4, y2: 3 }, { x: 4, x2: 5, y: 2, y2: 4 }, - { x: 2, x2: 4, y: 1, y2: 1 }]; + { x: 2, x2: 4, y: 1, y2: 1 } + ]; let svg: d3.Selection; let xScale: Plottable.Scales.Linear; @@ -161,7 +162,8 @@ describe("Plots", () => { it("retrieves the entities that intersect with the bounding box", () => { let entities = plot.entitiesIn({ topLeft: { x: xScale.scale(0), y: yScale.scale(4.5) }, - bottomRight: { x: xScale.scale(2.5), y: yScale.scale(3) } }); + bottomRight: { x: xScale.scale(2.5), y: yScale.scale(3) } + }); assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the box"); assert.strictEqual(entities[0].index, 0, "the entity of index 0 is retrieved"); assert.strictEqual(entities[1].index, 1, "the entity of index 1 is retrieved"); @@ -171,7 +173,8 @@ describe("Plots", () => { it("retrieves the entities that intersect with given ranges", () => { let entities = plot.entitiesIn( { min: xScale.scale(2.5), max: xScale.scale(4.5) }, - { min: yScale.scale(4.5), max: yScale.scale(2.5) }); + { min: yScale.scale(4.5), max: yScale.scale(2.5) } + ); assert.lengthOf(entities, 2, "retrieved 2 entities intersect with the ranges"); assert.strictEqual(entities[0].index, 1, "the entity of index 1 is retrieved"); assert.strictEqual(entities[1].index, 2, "the entity of index 2 is retrieved"); @@ -230,7 +233,8 @@ describe("Plots", () => { it("returns empty array when no entities intersect with the ranges", () => { let entities = plot.entitiesIn( { min: xScale.scale(1.5), max: xScale.scale(2.5) }, - { min: yScale.scale(2.5), max: yScale.scale(1.5) }); + { min: yScale.scale(2.5), max: yScale.scale(1.5) } + ); assert.lengthOf(entities, 0, "no entities intersects with the ranges"); svg.remove(); }); @@ -239,7 +243,8 @@ describe("Plots", () => { x1: number, x2: number, y1: number, y2: number) { let entities = plot.entitiesIn( { min: xScale.scale(x1), max: xScale.scale(x2) }, - { min: yScale.scale(y1), max: yScale.scale(y2) }); + { min: yScale.scale(y1), max: yScale.scale(y2) } + ); assert.lengthOf(entities, 1, "retrieved 1 entity that intersects with the box"); assert.strictEqual(entities[0].index, index, `the entity of index ${index} is retrieved`); } From 3e32442fbf269d0a5f5e7e7af5ed776b3c1c7170 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 16:28:49 -0700 Subject: [PATCH 070/160] [refactorDragBoxLayer] more test title changes --- test/components/dragBoxLayerTests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 1ad6ea0eb4..5ceb588ed5 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -25,7 +25,7 @@ describe("Interactive Components", () => { }; }); - it("correctly draws box on drag", () => { + it("draws box on drag", () => { dbl.renderTo(svg); assert.isFalse(dbl.boxVisible(), "box is hidden initially"); @@ -75,7 +75,7 @@ describe("Interactive Components", () => { svg.remove(); }); - it("applies the given detection radius", () => { + it("applies the given detection radius property", () => { dbl.renderTo("svg"); let radius = 5; From da04f08765be7d55844cdca6ad599fd1edf76f5e Mon Sep 17 00:00:00 2001 From: Cassie Date: Thu, 20 Aug 2015 16:40:07 -0700 Subject: [PATCH 071/160] updated tests to have expected error messages --- test/components/componentTests.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/components/componentTests.ts b/test/components/componentTests.ts index 3583ca775b..1b53ecf2ea 100644 --- a/test/components/componentTests.ts +++ b/test/components/componentTests.ts @@ -453,10 +453,14 @@ describe("Component behavior", () => { let parent = TestMethods.getSVGParent(); let div = parent.append("div"); // HACKHACK #2614: chai-assert.d.ts has the wrong signature - ( assert).throws(() => c.renderTo(div), Error, "", "rejects selections that don't contain svgs"); - ( assert).throws(() => c.renderTo( div.node()), Error, "", "rejects DOM nodes that are not svgs"); - ( assert).throws(() => c.renderTo("#not-a-element"), Error, "", "rejects strings that don't correspond to DOM elements"); - ( assert).throws(() => c.renderTo(d3.select(null)), Error, "", "rejects empty d3 selections"); + ( assert).throws(() => c.renderTo(div), Error, + "Plottable requires a valid SVG to renderTo", "rejects selections that don't contain svgs"); + ( assert).throws(() => c.renderTo( div.node()), Error, + "Plottable requires a valid SVG to renderTo", "rejects DOM nodes that are not svgs"); + ( assert).throws(() => c.renderTo("#not-a-element"), Error, + "Plottable requires a valid SVG to renderTo", "rejects strings that don't correspond to DOM elements"); + ( assert).throws(() => c.renderTo(d3.select(null)), Error, + "Plottable requires a valid SVG to renderTo", "rejects empty d3 selections"); svg.remove(); }); From affdd3447558ced4f557a308726a40909a3ef62c Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Thu, 20 Aug 2015 16:40:35 -0700 Subject: [PATCH 072/160] [refactorDragBoxLayer] forgotten save --- test/components/dragBoxLayerTests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/dragBoxLayerTests.ts b/test/components/dragBoxLayerTests.ts index 5ceb588ed5..6c418973cf 100644 --- a/test/components/dragBoxLayerTests.ts +++ b/test/components/dragBoxLayerTests.ts @@ -101,7 +101,7 @@ describe("Interactive Components", () => { svg.remove(); }); - it("does not error on destroy() if scales are not inputted", () => { + it("does not error on destroy() if scales are not added", () => { assert.doesNotThrow(() => dbl.destroy(), Error, "can destroy"); svg.remove(); }); From 318b60598220d0a0034c8fe2ade31c462e5183b6 Mon Sep 17 00:00:00 2001 From: Cassie Date: Thu, 20 Aug 2015 17:37:50 -0700 Subject: [PATCH 073/160] fixing style issues --- .../overlaying/tests/basic/negative_stacked_bar.js | 9 ++------- quicktests/overlaying/tests/basic/pies.js | 2 -- quicktests/overlaying/tests/interactions/dragbox.js | 2 -- .../overlaying/tests/interactions/dragbox_scales.js | 3 --- .../overlaying/tests/interactions/key_zoom_pointer.js | 2 -- 5 files changed, 2 insertions(+), 16 deletions(-) diff --git a/quicktests/overlaying/tests/basic/negative_stacked_bar.js b/quicktests/overlaying/tests/basic/negative_stacked_bar.js index f0ec50a5d4..f28b3b3541 100644 --- a/quicktests/overlaying/tests/basic/negative_stacked_bar.js +++ b/quicktests/overlaying/tests/basic/negative_stacked_bar.js @@ -26,14 +26,11 @@ function run(svg, data, Plottable) { var dataset2 = new Plottable.Dataset(data[1]); var dataset3 = new Plottable.Dataset(data[2]); - var verticalPlot = new Plottable.Plots.StackedBar("vertical") .x(function(d) { return d.quarter; }, xScale1) .y(function(d) { return d.earnings; }, yScale1) .attr("fill", function(d) { return d.team; }, colorScale) - .addDataset(dataset1) - .addDataset(dataset2) - .addDataset(dataset3) + .datasets([dataset1, dataset2, dataset3]) .labelsEnabled(true) .animated(true); @@ -47,9 +44,7 @@ function run(svg, data, Plottable) { horizontalPlot.x(function(d) { return d.earnings; }, xScale2) .y(function(d) { return d.quarter; }, yScale2) .attr("fill", function(d) { return d.team; }, colorScale) - .addDataset(dataset1) - .addDataset(dataset2) - .addDataset(dataset3) + .datasets([dataset1, dataset2, dataset3]) .labelsEnabled(true) .animated(true); diff --git a/quicktests/overlaying/tests/basic/pies.js b/quicktests/overlaying/tests/basic/pies.js index 97b066bbd2..2556cabfa8 100644 --- a/quicktests/overlaying/tests/basic/pies.js +++ b/quicktests/overlaying/tests/basic/pies.js @@ -33,8 +33,6 @@ function run(svg, data, Plottable){ .attr("opacity", .5) .attr("fill", function(d){ return d.key; }, cs); - - var outerPie = new Plottable.Plots.Pie(); outerPie.addDataset(new Plottable.Dataset(data[1])); outerPie.sectorValue(function(d){ return d.value; }) diff --git a/quicktests/overlaying/tests/interactions/dragbox.js b/quicktests/overlaying/tests/interactions/dragbox.js index 9c86558464..76ed08e7e7 100644 --- a/quicktests/overlaying/tests/interactions/dragbox.js +++ b/quicktests/overlaying/tests/interactions/dragbox.js @@ -1,8 +1,6 @@ function makeData() { "use strict"; var data = []; - - for (var i = 0; i < 250; i++) { data.push({ "x": i, "y": Math.random(), diff --git a/quicktests/overlaying/tests/interactions/dragbox_scales.js b/quicktests/overlaying/tests/interactions/dragbox_scales.js index 0922356ef7..bbfefd77a4 100644 --- a/quicktests/overlaying/tests/interactions/dragbox_scales.js +++ b/quicktests/overlaying/tests/interactions/dragbox_scales.js @@ -18,8 +18,6 @@ function makeData() { function run(svg, data, Plottable) { "use strict"; - - var xScale = new Plottable.Scales.Linear(); var yScale = new Plottable.Scales.Linear(); @@ -41,7 +39,6 @@ function run(svg, data, Plottable) { .attr("fill", "#dddddd") .addDataset(new Plottable.Dataset(data[1])); - var dbl = new Plottable.Components.DragBoxLayer() .onDrag(function(bounds){ segment.entities().forEach(function(e){ diff --git a/quicktests/overlaying/tests/interactions/key_zoom_pointer.js b/quicktests/overlaying/tests/interactions/key_zoom_pointer.js index 94916dedda..bd4232ca7c 100644 --- a/quicktests/overlaying/tests/interactions/key_zoom_pointer.js +++ b/quicktests/overlaying/tests/interactions/key_zoom_pointer.js @@ -53,7 +53,6 @@ function run(svg, data, Plottable) { [yAxis, plotGroup], [null, xAxisSquare], [null, squareLabel]]); - chart.renderTo(svg); var pointer = new Plottable.Interactions.Pointer(); @@ -74,7 +73,6 @@ function run(svg, data, Plottable) { pzi.attachTo(plotGroup); pzi.enabled(false); - var key = new Plottable.Interactions.Key(); key.onKeyPress(80, function(keycode) { pzi.enabled(true); From 612d2645a46e3d86a9399e3a8106f7b3f2d0dcf4 Mon Sep 17 00:00:00 2001 From: Andrei Cioara Date: Fri, 21 Aug 2015 12:15:12 -0700 Subject: [PATCH 074/160] [typings] Updated Mocha and Chai typings and libraries --- bower.json | 4 +- bower_components/chai/.bower.json | 10 +- bower_components/chai/CONTRIBUTING.md | 31 +- bower_components/chai/History.md | 206 +++- bower_components/chai/README.md | 123 +- bower_components/chai/ReleaseNotes.md | 344 +++++- bower_components/chai/bower.json | 50 +- bower_components/chai/chai.js | 1355 ++++++++++++++------ bower_components/chai/component.json | 5 +- bower_components/chai/package.json | 28 +- bower_components/mocha/.bower.json | 42 +- bower_components/mocha/.editorconfig | 18 + bower_components/mocha/.mailmap | 1 + bower_components/mocha/CONTRIBUTING.md | 49 + bower_components/mocha/History.md | 237 ++++ bower_components/mocha/LICENSE | 2 +- bower_components/mocha/Readme.md | 171 +-- bower_components/mocha/bower.json | 35 +- bower_components/mocha/media/logo.svg | 3 +- bower_components/mocha/mocha.js | 1560 ++++++++++++++++++------ bower_components/mocha/test.js | 9 + test/globalInitialization.ts | 2 +- test/plots/barPlotTests.ts | 2 +- test/testReference.ts | 2 +- tsd.json | 6 +- typings/chai/chai-assert.d.ts | 111 -- typings/chai/chai.d.ts | 308 +++++ typings/mocha/mocha.d.ts | 232 ++-- 28 files changed, 3578 insertions(+), 1368 deletions(-) create mode 100644 bower_components/mocha/.editorconfig create mode 100644 bower_components/mocha/.mailmap create mode 100644 bower_components/mocha/CONTRIBUTING.md create mode 100644 bower_components/mocha/test.js delete mode 100644 typings/chai/chai-assert.d.ts create mode 100644 typings/chai/chai.d.ts diff --git a/bower.json b/bower.json index b8f11913f3..ae52a7dff2 100644 --- a/bower.json +++ b/bower.json @@ -37,8 +37,8 @@ "url": "git://github.com/palantir/plottable.git" }, "devDependencies": { - "chai": "1.9.0", - "mocha": "1.17.1", + "chai": "2.0.0", + "mocha": "2.2.5", "jQuery": "2.1.0", "jquery.simulate": "1.2.0", "requirejs": "2.1.18" diff --git a/bower_components/chai/.bower.json b/bower_components/chai/.bower.json index 4464d6af57..595fc83ec6 100644 --- a/bower_components/chai/.bower.json +++ b/bower_components/chai/.bower.json @@ -1,6 +1,6 @@ { "name": "chai", - "version": "1.9.0", + "version": "2.0.0", "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.", "license": "MIT", "keywords": [ @@ -25,13 +25,13 @@ "dependencies": {}, "devDependencies": {}, "homepage": "https://github.com/chaijs/chai", - "_release": "1.9.0", + "_release": "2.0.0", "_resolution": { "type": "version", - "tag": "1.9.0", - "commit": "e26e576b5242b579f9f885c79388d0cdfc2bfa13" + "tag": "2.0.0", + "commit": "2147e1d49eb5caa27e0afb9e18208de2d8741f39" }, "_source": "git://github.com/chaijs/chai.git", - "_target": "1.9.0", + "_target": "2.0.0", "_originalSource": "chai" } \ No newline at end of file diff --git a/bower_components/chai/CONTRIBUTING.md b/bower_components/chai/CONTRIBUTING.md index 69fe27f9c1..6f65fbecea 100644 --- a/bower_components/chai/CONTRIBUTING.md +++ b/bower_components/chai/CONTRIBUTING.md @@ -11,6 +11,7 @@ Following these guidelines helps to communicate that you respect the time of the - [Bug Reports](#bugs) - [Feature Requests](#features) - [Pull Requests](#pull-requests) +- [Releasing](#releasing) - [Support](#support) - [Resources](#resources) - [Core Contributors](#contributors) @@ -31,7 +32,7 @@ Following these guidelines helps to communicate that you respect the time of the ## Contributing The issue tracker is the preferred channel for [bug reports](#bugs), -[features requests](#features) and [submitting pull +[feature requests](#features) and [submitting pull requests](#pull-requests), but please respect the following restrictions: * Please **do not** use the issue tracker for personal support requests (use @@ -75,7 +76,7 @@ Example: Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the project. It's up to *you* to make a strong case to convince the project's developers of the merits of this feature. Please provide as much detail and context as possible. -Furthermore, since Chai.js has a [robust plugin API](http://chaijs.com/guide/plugins/), we encourage you to publish **new Assertions** as plugins. If your feature is an enhancement to an **existing Assertion**, please propose your changes as an issue prior to opening a pull request. If the core Chai.js contributors feel your plugin would be better suited as a core assertion, they will invite you to open a PR in [chaijs/chai](https//github.com/chaijs/chai). +Furthermore, since Chai.js has a [robust plugin API](http://chaijs.com/guide/plugins/), we encourage you to publish **new Assertions** as plugins. If your feature is an enhancement to an **existing Assertion**, please propose your changes as an issue prior to opening a pull request. If the core Chai.js contributors feel your plugin would be better suited as a core assertion, they will invite you to open a PR in [chaijs/chai](https://github.com/chaijs/chai). ### Pull Requests @@ -90,7 +91,7 @@ Good pull requests - patches, improvements, new features - are a fantastic help. **Please ask first** before embarking on any significant pull request (e.g. implementing features, refactoring code), otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project. -Please adhere to the coding conventions used throughout a project (indentation, accurate comments, etc.) and any other requirements (such as test coverage). Please review the [Chai.js Codeing Style Guide](https://github.com/chaijs/chai/wiki/Chai-Coding-Style-Guide). +Please adhere to the coding conventions used throughout a project (indentation, accurate comments, etc.) and any other requirements (such as test coverage). Please review the [Chai.js Coding Style Guide](https://github.com/chaijs/chai/wiki/Chai-Coding-Style-Guide). Follow this process if you'd like your work considered for inclusion in the project: @@ -136,6 +137,30 @@ git push origin **IMPORTANT**: By submitting a patch, you agree to allow the project owner to license your work under the same license as that used by the project. + +## Releasing + +Releases can be prepared by any core-contributor or user whom has push access to +the `chaijs/chai` repository. + +This process requires [git-extras](https://github.com/tj/git-extras) for some steps. + +1. Ensure all tests pass. +2. Bump the version tag in-code and for all package managers. + - `lib/chai.js` + - `package.json` + - `component.json` + - `bower.json` +3. Build the browser version with `make`. +4. Append commit log to `HISTORY.md` using `git changelog` command. +5. Write human-friendly `ReleaseNotes.md` based on changelog. + - If breaking changes, write migration tutorial(s) and reasoning. + - Callouts for community contributions (PRs) with links to PR and contributing user. + - Callouts for other fixes made by core contributors with links to issue. +6. Update `README.md` with an updated contributors list using `git summary` command. +7. Push a tagged release using `git release x.x.x`. + - All tagged releases are published to NPM. + ## Support diff --git a/bower_components/chai/History.md b/bower_components/chai/History.md index 09cce25adb..6f9e990096 100644 --- a/bower_components/chai/History.md +++ b/bower_components/chai/History.md @@ -1,5 +1,125 @@ - -1.9.0 / 2014-01-29 +2.0.0 / 2015-02-09 +================== + + * Merge pull request #361 from gregglind/b265-keys-object + * fix #359. Add `.keys(object)` + * Merge pull request #359 from gregglind/b359-unexpected-keys-sort + * Fix #359 keys() sorts input unexpectedly + * contrib: publish release strategy and travis npm creds #337 + * Merge pull request #357 from danilovaz/master + * Update copyright date + * Merge pull request #349 from toastynerd/add-which-chain-method + * add the which chain method as per issue #347 + * Merge pull request #333 from cmpolis/change-assertions + * more `by` cleanup + * cleaned out `.by` for #333 + * Merge pull request #335 from DingoEatingFuzz/expose-util + * Expose chai util through the chai object + * cleanup (per notes on pr #333) + * updated `change` to work w/ non-number values + tests + * Merge pull request #334 from hurrymaplelad/patch-1 + * Typo, the flag is called 'contains' with an 's' + * updated assertion interface with `change` (#330) + * added `change`,`increase`,`decrease` assertions (#330) + * assert tests for `change`,`increase`,`decrease` + * expect/should tests for `change`,`increase`,`decrease` + * Merge pull request #328 from lo1tuma/issue-327 + * Add includes and contains alias (fixes #327) + * Merge pull request #325 from chasenlehara/overwriteChainableMethodDocs + * Fix docs for overwriteChainableMethod parameters + * Merge pull request #317 from jasonkarns/patch-2 + * Merge pull request #318 from jasonkarns/patch-3 + * Merge pull request #316 from jasonkarns/patch-1 + * typos in docs + * minor docs typo + * update docs: getAllFlags -> transferFlags + * Merge pull request #313 from cjqed/254-expect-any-all + * Added the all and any flags for keys assertion, with all being the default behavior + * Merge pull request #312 from cjqed/291-assert-same-deep-members + * Changed public comment of sameDeepMemebers to be more clear + * Fixes issue #291, adds assert.sameDeepMembers + * Merge pull request #311 from cjqed/305-above-below-on-assert + * Merge pull request #308 from prodatakey/hasproperty + * Issue #305 fixed, added assert.isAbove and assert.isBelow + * Fix typo + * More unit tests for new utility functions + * Refactor common functionality, document, test + * Refactor if statement out + * Small unit test fix + * Handle array indexing terminating paths + * Merge pull request #309 from ericdouglas/iterableEqual-couting-once + * couting variables just once + * Fix properties with `undefined` value pass property assertion + * Merge pull request #306 from chaijs/revert-297-noopchainfunc + * Revert "Allows writing lint-friendly tests" + +1.10.0 / 2014-11-10 +================== + + * Merge pull request #297 from prodatakey/noopchainfunc + * Merge pull request #300 from julienw/299-fix-getMessage-test + * Fix #299: the test is defining global variables + * Add a couple more unit tests + * Add unit tests for chained terminating property asserts + * Revise documentation wording + * Add docs for function style NOOP asserts + * Make the NOOP function a shared constant + * Merge pull request #298 from dasilvacontin/negativeZeroLogging + * why not more assertions + * added test for inspecting `-0` + * a more readable/simple condition statement, as pointed out by @keithamus + * added check for logging negative zero + * Change test to not trigger argument bug + * Allows writing lint-friendly tests + * readme: update contributors for 1.9.2 + +1.9.2 / 2014-09-29 +================== + + * Merge pull request #268 from charlierudolph/cr-lazyMessages + * Merge pull request #269 from charlierudolph/cr-codeCleanup + * Merge pull request #277 from charlierudolph/fix-doc + * Merge pull request #279 from mohayonao/fix-closeTo + * Merge pull request #292 from boneskull/mocha + * resolves #255: upgrade mocha + * Merge pull request #289 from charlierudolph/cr-dryUpCode + * Dry up code + * Merge pull request #275 from DrRataplan/master + * assert: .closeTo() verify value's type before assertion + * Rewrite pretty-printing HTML elements to prevent throwing internal errors Fixes errors occuring when using a non-native DOM implementation + * Fix assert documentation + * Remove unused argument + * Allow messages to be functions + * Merge pull request #267 from shinnn/master + * Use SVG badge + * Merge pull request #264 from cjthompson/keys_diff + * Show diff for keys assertion + +1.9.1 / 2014-03-19 +================== + + * deps update + * util: [getActual] select actual logic now allows undefined for actual. Closes #183 + * docs: [config] make public, express param type + * Merge pull request #251 from romario333/threshold3 + * Fix issue #166 - configurable threshold in objDisplay. + * Move configuration options to config.js. + * Merge pull request #233 from Empeeric/master + * Merge pull request #244 from leider/fix_for_contains + * Merge pull request #247 from didoarellano/typo-fixes + * Fix typos + * Merge pull request #245 from lfac-pt/patch-1 + * Update `exports.version` to 1.9.0 + * aborting loop on finding + * declaring variable only once + * additional test finds incomplete implementation + * simplified code + * fixing #239 (without changing chai.js) + * ssfi as it should be + * Merge pull request #228 from duncanbeevers/deep_members + * Deep equality check for collection membership + +1.9.0 / 2014-01-29 ================== * docs: add contributing.md #238 @@ -41,12 +161,12 @@ * test: updated for the new assertion errors * core: improve message for assertion errors (throw assertion) -1.8.1 / 2013-10-10 +1.8.1 / 2013-10-10 ================== * pkg: update deep-eql version -1.8.0 / 2013-09-18 +1.8.0 / 2013-09-18 ================== * test: [sauce] add a few more browsers @@ -61,7 +181,7 @@ * Merge pull request #181 from tricknotes/fix-highlight * Fix highlight for example code -1.7.2 / 2013-06-27 +1.7.2 / 2013-06-27 ================== * coverage: add coveralls badge @@ -74,14 +194,14 @@ * Fix to highlight code example * bower: granular ignores -1.7.1 / 2013-06-24 +1.7.1 / 2013-06-24 ================== * Merge branch 'feature/bower'. #175 * bower: add json file * build: browser -1.7.0 / 2013-06-17 +1.7.0 / 2013-06-17 ================== * error: remove internal assertion error constructor @@ -100,7 +220,7 @@ * Merge pull request #169 from katsgeorgeek/topics/master * Fix comparison objects. -1.6.1 / 2013-06-05 +1.6.1 / 2013-06-05 ================== * Merge pull request #168 from katsgeorgeek/topics/master @@ -111,7 +231,7 @@ * Merge pull request #161 from brandonpayton/master * Fix documented name for assert interfaces isDefined method -1.6.0 / 2013-04-29 +1.6.0 / 2013-04-29 ================== * build: browser @@ -134,7 +254,7 @@ * notes: migration notes for deep equal changes * test: for ever err() there must be a passing version -1.5.0 / 2013-02-03 +1.5.0 / 2013-02-03 ================== * docs: add Release Notes for non-gitlog summary of changes. @@ -190,14 +310,14 @@ * Add new getProperties and getEnumerableProperties utils. * showDiff: force true for equal and eql -1.4.2 / 2012-12-21 +1.4.2 / 2012-12-21 ================== * browser build: (object diff support when used with mocha) #106 * test: [display] array test for mocha object diff * browser: no longer need different AssertionError constructor -1.4.1 / 2012-12-21 +1.4.1 / 2012-12-21 ================== * showDiff: force diff for equal and eql. #106 @@ -206,7 +326,7 @@ * FIX: assert.Throw checks error type/message * TST: assert.Throw should check error type/message -1.4.0 / 2012-11-29 +1.4.0 / 2012-11-29 ================== * pre-release browser build @@ -222,7 +342,7 @@ * Check for 'actual' type * Added support for circular references when checking deep (in)equality. -1.3.0 / 2012-10-01 +1.3.0 / 2012-10-01 ================== * browser build w/ folio >= 0.3.4. Closes #99 @@ -243,7 +363,7 @@ * Make globalShould test work in browser too. * Add a setter for `Object.prototype.should`. Closes #86. -1.2.0 / 2012-08-07 +1.2.0 / 2012-08-07 ================== * Merge branch 'feature/errmsg' @@ -263,7 +383,7 @@ * Merge pull request #88 from pwnall/master * Don't inspect() assertion arguments if the assertion passes. -1.1.1 / 2012-07-09 +1.1.1 / 2012-07-09 ================== * improve commonjs support on browser build @@ -277,7 +397,7 @@ * clean up makefile * early folio 0.3.x support -1.1.0 / 2012-06-26 +1.1.0 / 2012-06-26 ================== * browser build @@ -302,7 +422,7 @@ * move core assertions to own file and refactor all using utils * rearrange folder structure -1.0.4 / 2012-06-03 +1.0.4 / 2012-06-03 ================== * Merge pull request #68 from fizker/itself @@ -310,7 +430,7 @@ * simplify error inspections for cross browser compatibility * fix safari `addChainableMethod` errors. Closes #69 -1.0.3 / 2012-05-27 +1.0.3 / 2012-05-27 ================== * Point Travis badge to the right place. @@ -318,7 +438,7 @@ * Fix .not.deep.equal. * contributors list -1.0.2 / 2012-05-26 +1.0.2 / 2012-05-26 ================== * Merge pull request #67 from chaijs/chaining-and-flags @@ -332,7 +452,7 @@ * Add .mailmap to .npmignore. * Add a .mailmap file to fix my name in shortlogs. -1.0.1 / 2012-05-18 +1.0.1 / 2012-05-18 ================== * browser build @@ -345,7 +465,7 @@ * Add npm-debug.log to .gitignore. * no reserved words as actuals. #62 -1.0.0 / 2012-05-15 +1.0.0 / 2012-05-15 ================== * readme cleanup @@ -364,7 +484,7 @@ * Use defined return value of Assertion extension functions * Update utility docs -1.0.0-rc3 / 2012-05-09 +1.0.0-rc3 / 2012-05-09 ================== * Merge branch 'feature/rc3' @@ -398,7 +518,7 @@ * Sinon–Chai has a dash * updated plugins list for docs -1.0.0-rc2 / 2012-05-06 +1.0.0-rc2 / 2012-05-06 ================== * Merge branch 'feature/test-cov' @@ -410,7 +530,7 @@ * overwrite Property and Method now ensure chain * version notes in readme -1.0.0-rc1 / 2012-05-04 +1.0.0-rc1 / 2012-05-04 ================== * browser build (rc1) @@ -517,7 +637,7 @@ * added 2012 to copyright headers * Added DeepEqual assertions -0.5.3 / 2012-04-21 +0.5.3 / 2012-04-21 ================== * Merge branch 'refs/heads/jgonera-oldbrowsers' @@ -532,7 +652,7 @@ * Support for expected and actual parameters in assert-style error object * chai as promised - readme -0.5.2 / 2012-03-21 +0.5.2 / 2012-03-21 ================== * browser build @@ -542,7 +662,7 @@ * better error message for assert.operator. Closes #39 * version notes -0.5.1 / 2012-03-14 +0.5.1 / 2012-03-14 ================== * chai.fail no longer exists @@ -550,7 +670,7 @@ * Added asset#isDefined. Closes #37. * dev docs update for Assertion#assert -0.5.0 / 2012-03-07 +0.5.0 / 2012-03-07 ================== * [bug] on inspect of reg on n 0.4.12 @@ -582,7 +702,7 @@ * Update the compiled version. * Add object & sane arguments support to `Assertion#empty`. -0.4.2 / 2012-02-28 +0.4.2 / 2012-02-28 ================== * fix for `process` not available in browser when used via browserify. Closes #28 @@ -614,7 +734,7 @@ * Add test for `assert.strictEqual`. * Add test for `assert.notEqual`. -0.4.1 / 2012-02-26 +0.4.1 / 2012-02-26 ================== * Merge pull request #27 from logicalparadox/type-fix @@ -625,7 +745,7 @@ * Add test for `new Number` type check. * Fix type of actual checks. -0.4.0 / 2012-02-25 +0.4.0 / 2012-02-25 ================== * docs and readme for upcoming 0.4.0 @@ -658,7 +778,7 @@ * doc contributors * README contributors -0.3.4 / 2012-02-23 +0.3.4 / 2012-02-23 ================== * inline comment typos for #15 @@ -673,25 +793,25 @@ * doc updates * read me updates include plugins -0.3.3 / 2012-02-12 +0.3.3 / 2012-02-12 ================== * Merge pull request #14 from jfirebaugh/configurable_properties * Make Assertion.prototype properties configurable -0.3.2 / 2012-02-10 +0.3.2 / 2012-02-10 ================== * codex version * docs * docs cleanup -0.3.1 / 2012-02-07 +0.3.1 / 2012-02-07 ================== * node 0.4.x compat -0.3.0 / 2012-02-07 +0.3.0 / 2012-02-07 ================== * Merge branch 'feature/03x' @@ -702,27 +822,27 @@ * Merge pull request #11 from domenic/master * Make `chai.use` a no-op if the function has already been used. -0.2.4 / 2012-02-02 +0.2.4 / 2012-02-02 ================== * added in past tense switch for `been` -0.2.3 / 2012-02-01 +0.2.3 / 2012-02-01 ================== * try that again -0.2.2 / 2012-02-01 +0.2.2 / 2012-02-01 ================== * added `been` (past of `be`) alias -0.2.1 / 2012-01-29 +0.2.1 / 2012-01-29 ================== * added Throw, with a capital T, as an alias to `throw` (#7) -0.2.0 / 2012-01-26 +0.2.0 / 2012-01-26 ================== * update gitignore for vim *.swp @@ -732,7 +852,7 @@ * simple .use function. See #9. * readme notice on browser compat -0.1.7 / 2012-01-25 +0.1.7 / 2012-01-25 ================== * added assert tests to browser test runner diff --git a/bower_components/chai/README.md b/bower_components/chai/README.md index 91a68d9ff5..c3cac1927e 100644 --- a/bower_components/chai/README.md +++ b/bower_components/chai/README.md @@ -5,10 +5,18 @@ can be delightfully paired with any javascript testing framework. For more information or to download plugins, view the [documentation](http://chaijs.com). -[![Build Status](https://travis-ci.org/chaijs/chai.png?branch=master)](https://travis-ci.org/chaijs/chai) +[![Build Status](https://travis-ci.org/chaijs/chai.svg?branch=master)](https://travis-ci.org/chaijs/chai) [![Selenium Test Status](https://saucelabs.com/browser-matrix/chaijs.svg)](https://saucelabs.com/u/chaijs) +### Plugins + +Chai offers a robust Plugin architecture for extending Chai's assertions and interfaces. + +- Need a plugin? View the [official plugin list](http://chaijs.com/plugins). +- Have a plugin and want it listed? Open a Pull Request at [chaijs/chai-docs:plugin.js](https://github.com/chaijs/chai-docs/blob/master/plugins.js#L1-L12). +- Want to build a plugin? Read the [plugin api documentation](http://chaijs.com/guide/plugins/). + ### Related Projects - [chaijs / assertion-error](https://github.com/chaijs/assertion-error): Custom `Error` constructor thrown upon an assertion failing. @@ -17,55 +25,82 @@ For more information or to download plugins, view the [documentation](http://cha ### Contributors project : chai - repo age : 2 years, 2 months ago - commits : 735 - active : 158 days - files : 56 + repo age : 3 years, 2 months + active : 220 days + commits : 845 + files : 59 authors : - 532 Jake Luer 72.4% - 79 Veselin Todorov 10.7% - 43 Domenic Denicola 5.9% - 6 Ruben Verborgh 0.8% - 5 George Kats 0.7% - 5 Jo Liss 0.7% - 5 Juliusz Gonera 0.7% - 5 Scott Nonnenberg 0.7% - 4 John Firebaugh 0.5% - 4 Max Edmands 0.5% - 4 Nick Heiner 0.5% - 4 josher19 0.5% - 3 Andrei Neculau 0.4% - 3 Jake Rosoman 0.4% - 3 Jeff Barczewski 0.4% - 3 Ryunosuke SATO 0.4% - 2 Bartvds 0.3% - 2 Duncan Beevers 0.3% - 2 Edwin Shao 0.3% - 2 Jakub Nešetřil 0.3% - 2 Teddy Cross 0.3% - 1 Anand Patil 0.1% - 1 Benjamin Horsleben 0.1% - 1 Brandon Payton 0.1% - 1 Chris Connelly 0.1% - 1 Chun-Yi 0.1% - 1 DD 0.1% - 1 Jeff Welch 0.1% - 1 Kilian Ciuffolo 0.1% - 1 Niklas Närhinen 0.1% - 1 Paul Miller 0.1% - 1 Sasha Koss 0.1% - 1 Veselin 0.1% - 1 Victor Costan 0.1% - 1 Vinay Pulim 0.1% - 1 Virginie BARDALES 0.1% - 1 laconbass 0.1% - 1 piecioshka 0.1% + 553 Jake Luer 65.4% + 79 Veselin Todorov 9.3% + 43 Domenic Denicola 5.1% + 23 Keith Cirkel 2.7% + 14 Joshua Perry 1.7% + 8 Chris Polis 0.9% + 6 Ruben Verborgh 0.7% + 5 Scott Nonnenberg 0.6% + 5 George Kats 0.6% + 5 Juliusz Gonera 0.6% + 5 leider 0.6% + 5 Jo Liss 0.6% + 4 Chris Jones 0.5% + 4 David da Silva 0.5% + 4 Nick Heiner 0.5% + 4 John Firebaugh 0.5% + 4 Veselin 0.5% + 4 Max Edmands 0.5% + 4 charlierudolph 0.5% + 4 josher19 0.5% + 3 Jake Rosoman 0.4% + 3 Jeff Barczewski 0.4% + 3 Andrei Neculau 0.4% + 3 Duncan Beevers 0.4% + 3 Jason Karns 0.4% + 3 Ryunosuke SATO 0.4% + 2 Gregg Lind 0.2% + 2 Teddy Cross 0.2% + 2 Bartvds 0.2% + 2 Jakub Nešetřil 0.2% + 2 Edwin Shao 0.2% + 2 Roman Masek 0.2% + 1 toastynerd 0.1% + 1 Anand Patil 0.1% + 1 Benjamin Horsleben 0.1% + 1 Brandon Payton 0.1% + 1 Chasen Le Hara 0.1% + 1 Chris Connelly 0.1% + 1 Chris Thompson 0.1% + 1 Christopher Hiller 0.1% + 1 Chun-Yi 0.1% + 1 DD 0.1% + 1 Danilo Vaz 0.1% + 1 Dido Arellano 0.1% + 1 Jeff Welch 0.1% + 1 Julien Wajsberg 0.1% + 1 Kilian Ciuffolo 0.1% + 1 Luís Cardoso 0.1% + 1 Martin Middel 0.1% + 1 Mathias Schreck 0.1% + 1 Michael Lange 0.1% + 1 Niklas Närhinen 0.1% + 1 Paul Miller 0.1% + 1 Refael Ackermann 0.1% + 1 Sasha Koss 0.1% + 1 Victor Costan 0.1% + 1 Vinay Pulim 0.1% + 1 Virginie BARDALES 0.1% + 1 ericdouglas 0.1% + 1 laconbass 0.1% + 1 mohayonao 0.1% + 1 piecioshka 0.1% + 1 shinnn 0.1% + 1 Adam Hull 0.1% + ## License (The MIT License) -Copyright (c) 2011-2014 Jake Luer +Copyright (c) 2011-2015 Jake Luer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bower_components/chai/ReleaseNotes.md b/bower_components/chai/ReleaseNotes.md index 322cabd636..ad21e4fdd4 100644 --- a/bower_components/chai/ReleaseNotes.md +++ b/bower_components/chai/ReleaseNotes.md @@ -1,15 +1,241 @@ # Release Notes -## 1.9.0 / 2014-01-29 +## 2.0.0 / 2015-02-09 + +Unfortunately with 1.10.0 - compatibility broke with older versions because of +the `addChainableNoop`. This change has been reverted. + +Any plugins using `addChainableNoop` should cease to do so. + +Any developers wishing for this behaviour can use [dirty-chai](https://www.npmjs.com/package/dirty-chai) +by [@joshperry](https://github.com/joshperry) + +### Community Contributions + +#### Code Features & Fixes + + * [#361](https://github.com/chaijs/chai/pull/361) `.keys()` now accepts Objects, extracting keys from them. By [@gregglind](https://github.com/gregglind) + * [#359](https://github.com/chaijs/chai/pull/359) `.keys()` no longer mutates passed arrays. By [@gregglind](https://github.com/gregglind) + * [#349](https://github.com/chaijs/chai/pull/349) Add a new chainable keyword - `.which`. By [@toastynerd](https://github.com/toastynerd) + * [#333](https://github.com/chaijs/chai/pull/333) Add `.change`, `.increase` and `.decrease` assertions. By [@cmpolis](https://github.com/cmpolis) + * [#335](https://github.com/chaijs/chai/pull/335) `chai.util` is now exposed [@DingoEatingFuzz](https://github.com/DingoEatingFuzz) + * [#328](https://github.com/chaijs/chai/pull/328) Add `.includes` and `.contains` aliases (for `.include` and `.contain`). By [@lo1tuma](https://github.com/lo1tuma) + * [#313](https://github.com/chaijs/chai/pull/313) Add `.any.keys()` and `.all.keys()` qualifiers. By [@cjqed](https://github.com/cjqed) + * [#312](https://github.com/chaijs/chai/pull/312) Add `assert.sameDeepMembers()`. By [@cjqed](https://github.com/cjqed) + * [#311](https://github.com/chaijs/chai/pull/311) Add `assert.isAbove()` and `assert.isBelow()`. By [@cjqed](https://github.com/cjqed) + * [#308](https://github.com/chaijs/chai/pull/308) `property` and `deep.property` now pass if a value is set to `undefined`. By [@prodatakey](https://github.com/prodatakey) + * [#309](https://github.com/chaijs/chai/pull/309) optimize deep equal in Arrays. By [@ericdouglas](https://github.com/ericdouglas) + * [#306](https://github.com/chaijs/chai/pull/306) revert #297 - allowing lint-friendly tests. By [@keithamus](https://github.com/keithamus) + +#### Documentation fixes + + * [#357](https://github.com/chaijs/chai/pull/357) Copyright year updated in docs. By [@danilovaz](https://github.com/danilovaz) + * [#325](https://github.com/chaijs/chai/pull/325) Fix documentation for overwriteChainableMethod. By [@chasenlehara](https://github.com/chasenlehara) + * [#334](https://github.com/chaijs/chai/pull/334) Typo fix. By [@hurrymaplelad](https://github.com/hurrymaplelad) + * [#317](https://github.com/chaijs/chai/pull/317) Typo fix. By [@jasonkarns](https://github.com/jasonkarns) + * [#318](https://github.com/chaijs/chai/pull/318) Typo fix. By [@jasonkarns](https://github.com/jasonkarns) + * [#316](https://github.com/chaijs/chai/pull/316) Typo fix. By [@jasonkarns](https://github.com/jasonkarns) + + +## 1.10.0 / 2014-11-10 + +The following changes are required if you are upgrading from the previous version: + +- **Users:** + - No changes required +- **Plugin Developers:** + - Review `addChainableNoop` notes below. +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. + +### Noop Function for Terminating Assertion Properties + +The following assertions can now also be used in the function-call form: + +* ok +* true +* false +* null +* undefined +* exist +* empty +* arguments +* Arguments + +The above list of assertions are property getters that assert immediately on +access. Because of that, they were written to be used by terminating the assertion +chain with a property access. + +```js +expect(true).to.be.true; +foo.should.be.ok; +``` + +This syntax is definitely aesthetically pleasing but, if you are linting your +test code, your linter will complain with an error something like "Expected an +assignment or function call and instead saw an expression." Since the linter +doesn't know about the property getter it assumes this line has no side-effects, +and throws a warning in case you made a mistake. + +Squelching these errors is not a good solution as test code is getting to be +just as important as, if not more than, production code. Catching syntactical +errors in tests using static analysis is a great tool to help make sure that your +tests are well-defined and free of typos. + +A better option was to provide a function-call form for these assertions so that +the code's intent is more clear and the linters stop complaining about something +looking off. This form is added in addition to the existing property access form +and does not impact existing test code. + +```js +expect(true).to.be.true(); +foo.should.be.ok(); +``` + +These forms can also be mixed in any way, these are all functionally identical: + +```js +expect(true).to.be.true.and.not.false(); +expect(true).to.be.true().and.not.false; +expect(true).to.be.true.and.not.false; +``` + +#### Plugin Authors + +If you would like to provide this function-call form for your terminating assertion +properties, there is a new function to register these types of asserts. Instead +of using `addProperty` to register terminating assertions, simply use `addChainableNoop` +instead; the arguments to both are identical. The latter will make the assertion +available in both the attribute and function-call forms and should have no impact +on existing users of your plugin. + +### Community Contributions + +- [#297](https://github.com/chaijs/chai/pull/297) Allow writing lint-friendly tests. [@joshperry](https://github.com/joshperry) +- [#298](https://github.com/chaijs/chai/pull/298) Add check for logging `-0`. [@dasilvacontin](https://github.com/dasilvacontin) +- [#300](https://github.com/chaijs/chai/pull/300) Fix #299: the test is defining global variables [@julienw](https://github.com/julienw) + +Thank you to all who took time to contribute! + +## 1.9.2 / 2014-09-29 + +The following changes are required if you are upgrading from the previous version: + +- **Users:** + - No changes required +- **Plugin Developers:** + - No changes required +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. + +### Community Contributions + +- [#264](https://github.com/chaijs/chai/pull/264) Show diff for keys assertions [@cjthompson](https://github.com/cjthompson) +- [#267](https://github.com/chaijs/chai/pull/267) Use SVG badges [@shinnn](https://github.com/shinnn) +- [#268](https://github.com/chaijs/chai/pull/268) Allow messages to be functions (sinon-compat) [@charlierudolph](https://github.com/charlierudolph) +- [#269](https://github.com/chaijs/chai/pull/269) Remove unused argument for #lengthOf [@charlierudolph](https://github.com/charlierudolph) +- [#275](https://github.com/chaijs/chai/pull/275) Rewrite pretty-printing HTML elements to prevent throwing internal errors [@DrRataplan](https://github.com/DrRataplan) +- [#277](https://github.com/chaijs/chai/pull/277) Fix assert documentation for #sameMembers [@charlierudolph](https://github.com/charlierudolph) +- [#279](https://github.com/chaijs/chai/pull/279) closeTo should check value's type before assertion [@mohayonao](https://github.com/mohayonao) +- [#289](https://github.com/chaijs/chai/pull/289) satisfy is called twice [@charlierudolph](https://github.com/charlierudolph) +- [#292](https://github.com/chaijs/chai/pull/292) resolve conflicts with node-webkit and global usage [@boneskull](https://github.com/boneskull) + +Thank you to all who took time to contribute! + +## 1.9.1 / 2014-03-19 + +The following changes are required if you are upgrading from the previous version: + +- **Users:** + - Migrate configuration options to new interface. (see notes) +- **Plugin Developers:** + - No changes required +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. + +### Configuration + +There have been requests for changes and additions to the configuration mechanisms +and their impact in the Chai architecture. As such, we have decoupled the +configuration from the `Assertion` constructor. This not only allows for centralized +configuration, but will allow us to shift the responsibility from the `Assertion` +constructor to the `assert` interface in future releases. + +These changes have been implemented in a non-breaking way, but a depretiation +warning will be presented to users until they migrate. The old config method will +be removed in either `v1.11.0` or `v2.0.0`, whichever comes first. + +#### Quick Migration + +```js +// change this: +chai.Assertion.includeStack = true; +chai.Assertion.showDiff = false; + +// ... to this: +chai.config.includeStack = true; +chai.config.showDiff = false; +``` + +#### All Config Options + +##### config.includeStack + +- **@param** _{Boolean}_ +- **@default** `false` + +User configurable property, influences whether stack trace is included in +Assertion error message. Default of `false` suppresses stack trace in the error +message. + +##### config.showDiff + +- **@param** _{Boolean}_ +- **@default** `true` + +User configurable property, influences whether or not the `showDiff` flag +should be included in the thrown AssertionErrors. `false` will always be `false`; +`true` will be true when the assertion has requested a diff be shown. + +##### config.truncateThreshold **(NEW)** + +- **@param** _{Number}_ +- **@default** `40` + +User configurable property, sets length threshold for actual and expected values +in assertion errors. If this threshold is exceeded, the value is truncated. + +Set it to zero if you want to disable truncating altogether. + +```js +chai.config.truncateThreshold = 0; // disable truncating +``` + +### Community Contributions + +- [#228](https://github.com/chaijs/chai/pull/228) Deep equality check for memebers. [@duncanbeevers](https://github.com/duncanbeevers) +- [#247](https://github.com/chaijs/chai/pull/247) Proofreading. [@didorellano](https://github.com/didoarellano) +- [#244](https://github.com/chaijs/chai/pull/244) Fix `contain`/`include` 1.9.0 regression. [@leider](https://github.com/leider) +- [#233](https://github.com/chaijs/chai/pull/233) Improvements to `ssfi` for `assert` interface. [@refack](https://github.com/refack) +- [#251](https://github.com/chaijs/chai/pull/251) New config option: object display threshold. [@romario333](https://github.com/romario333) + +Thank you to all who took time to contribute! + +### Other Bug Fixes + +- [#183](https://github.com/chaijs/chai/issues/183) Allow `undefined` for actual. (internal api) +- Update Karam(+plugins)/Istanbul to most recent versions. + +## 1.9.0 / 2014-01-29 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required -- **Plugin Developers:** +- **Plugin Developers:** - Review [#219](https://github.com/chaijs/chai/pull/219). -- **Core Contributors:** - - Refresh `node_modules` folder for updated dependencies. +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. ### Community Contributions @@ -31,42 +257,42 @@ Thank you to all who took time to contribute! - [#237](https://github.com/chaijs/chai/pull/237) Remove coveralls/jscoverage, include istanbul coverage report in travis test. - Update Karma and Sauce runner versions for consistent CI results. No more karma@canary. -## 1.8.1 / 2013-10-10 +## 1.8.1 / 2013-10-10 The following changes are required if you are upgrading from the previous version: - **Users:** - - Refresh `node_modules` folder for updated dependencies. -- **Plugin Developers:** + - Refresh `node_modules` folder for updated dependencies. +- **Plugin Developers:** - No changes required -- **Core Contributors:** - - Refresh `node_modules` folder for updated dependencies. +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. ### Browserify This is a small patch that updates the dependency tree so browserify users can install chai. (Remove conditional requires) -## 1.8.0 / 2013-09-18 +## 1.8.0 / 2013-09-18 The following changes are required if you are upgrading from the previous version: - **Users:** - See `deep.equal` notes. -- **Plugin Developers:** +- **Plugin Developers:** - No changes required -- **Core Contributors:** - - Refresh `node_modules` folder for updated dependencies. +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. ### Deep Equals This version of Chai focused on a overhaul to the deep equal utility. The code for this -tool has been removed from the core lib and can now be found at: +tool has been removed from the core lib and can now be found at: [chai / deep-eql](https://github.com/chaijs/deep-eql). As stated in previous releases, this is part of a larger initiative to provide transparency, independent testing, and coverage for -some of the more complicated internal tools. +some of the more complicated internal tools. -For the most part `.deep.equal` will behave the same as it has. However, in order to provide a +For the most part `.deep.equal` will behave the same as it has. However, in order to provide a consistent ruleset across all types being tested, the following changes have been made and _might_ require changes to your tests. @@ -94,7 +320,7 @@ expect(Array.prototype.slice.call(arguments)).to.deep.equal([]); ### CI and Browser Testing -Chai now runs the browser CI suite using [Karma](http://karma-runner.github.io/) directed at +Chai now runs the browser CI suite using [Karma](http://karma-runner.github.io/) directed at [SauceLabs](https://saucelabs.com/). This means we get to know where our browser support stands... and we get a cool badge: @@ -104,67 +330,67 @@ Look for the list of browsers/versions to expand over the coming releases. - [#195](https://github.com/chaijs/chai/issues/195) karma test framework -## 1.7.2 / 2013-06-27 +## 1.7.2 / 2013-06-27 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. -- **Plugin Developers:** +- **Plugin Developers:** - No changes required -- **Core Contributors:** - - Refresh `node_modules` folder for updated dependencies. +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. ### Coverage Reporting Coverage reporting has always been available for core-developers but the data has never been published for our end users. In our ongoing effort to improve accountability this data will now be published via the [coveralls.io](https://coveralls.io/) service. A badge has been added to the README and the full report -can be viewed online at the [chai coveralls project](https://coveralls.io/r/chaijs/chai). Furthermore, PRs +can be viewed online at the [chai coveralls project](https://coveralls.io/r/chaijs/chai). Furthermore, PRs will receive automated messages indicating how their PR impacts test coverage. This service is tied to TravisCI. ### Other Fixes - [#175](https://github.com/chaijs/chai/issues/175) Add `bower.json`. (Fix ignore all) -## 1.7.1 / 2013-06-24 +## 1.7.1 / 2013-06-24 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. -- **Plugin Developers:** +- **Plugin Developers:** - No changes required -- **Core Contributors:** - - Refresh `node_modules` folder for updated dependencies. +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. ### Official Bower Support Support has been added for the Bower Package Manager ([bower.io])(http://bower.io/). Though Chai could be installed via Bower in the past, this update adds official support via the `bower.json` -specification file. +specification file. - [#175](https://github.com/chaijs/chai/issues/175) Add `bower.json`. -## 1.7.0 / 2013-06-17 +## 1.7.0 / 2013-06-17 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. -- **Plugin Developers:** +- **Plugin Developers:** - Review AssertionError update notice. -- **Core Contributors:** - - Refresh `node_modules` folder for updated dependencies. +- **Core Contributors:** + - Refresh `node_modules` folder for updated dependencies. ### AssertionError Update Notice Chai now uses [chaijs/assertion-error](https://github.com/chaijs/assertion-error) instead an internal -constructor. This will allow for further iteration/experimentation of the AssertionError constructor -independant of Chai. Future plans include stack parsing for callsite support. +constructor. This will allow for further iteration/experimentation of the AssertionError constructor +independant of Chai. Future plans include stack parsing for callsite support. This update constructor has a different constructor param signature that conforms more with the standard -`Error` object. If your plugin throws and `AssertionError` directly you will need to update your plugin +`Error` object. If your plugin throws and `AssertionError` directly you will need to update your plugin with the new signature. ```js @@ -208,7 +434,7 @@ throw new AssertionError('An assertion error occurred', null, arguments.callee); This is the first non-developement dependency for Chai. As Chai continues to evolve we will begin adding more; the next will likely be improved type detection and deep equality. With Chai's userbase continually growing there is an higher need for accountability and documentation. External dependencies will allow us to iterate and -test on features independent from our interfaces. +test on features independent from our interfaces. Note: The browser packaged version `chai.js` will ALWAYS contain all dependencies needed to run Chai. @@ -220,16 +446,16 @@ Note: The browser packaged version `chai.js` will ALWAYS contain all dependencie Thank you to all who took the time to contribute! -## 1.6.1 / 2013-06-05 +## 1.6.1 / 2013-06-05 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. -- **Plugin Developers:** +- **Plugin Developers:** - No changes required. -- **Core Contributors:** - - Refresh `node_modules` folder for updated developement dependencies. +- **Core Contributors:** + - Refresh `node_modules` folder for updated developement dependencies. ### Deep Equality @@ -247,16 +473,16 @@ Thank you to all who took the time to contribute! - Mocha has been locked at version `1.8.x` to ensure `mocha-phantomjs` compatibility. -## 1.6.0 / 2013-04-29 +## 1.6.0 / 2013-04-29 The following changes are required if you are upgrading from the previous version: - **Users:** - No changes required. -- **Plugin Developers:** +- **Plugin Developers:** - No changes required. -- **Core Contributors:** - - Refresh `node_modules` folder for updated developement dependencies. +- **Core Contributors:** + - Refresh `node_modules` folder for updated developement dependencies. ### New Assertions @@ -277,14 +503,14 @@ expect([1, 2, 3]).to.not.include.members([3, 2, 8]); // (assert) full set assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members'); -// (assert) inclusion +// (assert) inclusion assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members'); ``` #### Non-inclusion for Assert Interface -Most `assert` functions have a negative version, like `instanceOf()` has a corresponding `notInstaceOf()`. +Most `assert` functions have a negative version, like `instanceOf()` has a corresponding `notInstaceOf()`. However `include()` did not have a corresponding `notInclude()`. This has been added. ```js @@ -305,19 +531,19 @@ Thank you to all who took time to contribute! - [#158](https://github.com/chaijs/chai/issues/158) `assert#notInclude` has been added. - Travis-CI now tests Node.js `v0.10.x`. Support for `v0.6.x` has been removed. `v0.8.x` is still tested as before. -## 1.5.0 / 2013-02-03 +## 1.5.0 / 2013-02-03 ### Migration Requirements The following changes are required if you are upgrading from the previous version: -- **Users:** - - _Update [2013-02-04]:_ Some users may notice a small subset of deep equality assertions will no longer pass. This is the result of +- **Users:** + - _Update [2013-02-04]:_ Some users may notice a small subset of deep equality assertions will no longer pass. This is the result of [#120](https://github.com/chaijs/chai/issues/120), an improvement to our deep equality algorithm. Users will need to revise their assertions to be more granular should this occur. Further information: [#139](https://github.com/chaijs/chai/issues/139). -- **Plugin Developers:** +- **Plugin Developers:** - No changes required. -- **Core Contributors:** +- **Core Contributors:** - Refresh `node_modules` folder for updated developement dependencies. ### Community Contributions @@ -341,10 +567,10 @@ Thank you to all who took time to contribute! #### For Users -**1. Component Support:** Chai now included the proper configuration to be installed as a +**1. Component Support:** Chai now included the proper configuration to be installed as a [component](https://github.com/component/component). Component users are encouraged to consult [chaijs.com](http://chaijs.com) for the latest version number as using the master branch -does not gaurantee stability. +does not gaurantee stability. ```js // relevant component.json @@ -357,9 +583,9 @@ Alternatively, bleeding-edge is available: $ component install chaijs/chai -**2. Configurable showDiff:** Some test runners (such as [mocha](http://visionmedia.github.com/mocha/)) -include support for showing the diff of strings and objects when an equality error occurs. Chai has -already included support for this, however some users may not prefer this display behavior. To revert to +**2. Configurable showDiff:** Some test runners (such as [mocha](http://visionmedia.github.com/mocha/)) +include support for showing the diff of strings and objects when an equality error occurs. Chai has +already included support for this, however some users may not prefer this display behavior. To revert to no diff display, the following configuration is available: ```js @@ -369,7 +595,7 @@ chai.Assertion.showDiff = true; // default, diff output enabled #### For Plugin Developers -**1. New Utility - type**: The new utility `.type()` is available as a better implementation of `typeof` +**1. New Utility - type**: The new utility `.type()` is available as a better implementation of `typeof` that can be used cross-browser. It handles the inconsistencies of Array, `null`, and `undefined` detection. - **@param** _{Mixed}_ object to detect type of @@ -387,9 +613,9 @@ chai.use(function (c, utils) { #### For Core Contributors -**1. Browser Testing**: Browser testing of the `./chai.js` file is now available in the command line -via PhantomJS. `make test` and Travis-CI will now also rebuild and test `./chai.js`. Consequently, all -pull requests will now be browser tested in this way. +**1. Browser Testing**: Browser testing of the `./chai.js` file is now available in the command line +via PhantomJS. `make test` and Travis-CI will now also rebuild and test `./chai.js`. Consequently, all +pull requests will now be browser tested in this way. _Note: Contributors opening pull requests should still NOT include the browser build._ diff --git a/bower_components/chai/bower.json b/bower_components/chai/bower.json index f38a5f10a2..8a656f42ab 100644 --- a/bower_components/chai/bower.json +++ b/bower_components/chai/bower.json @@ -1,27 +1,27 @@ { - "name": "chai" - , "version": "1.9.0" - , "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic." - , "license": "MIT" - , "keywords": [ - "test" - , "assertion" - , "assert" - , "testing" - , "chai" - ] - , "main": "chai.js" - , "ignore": [ - "build" - , "components" - , "lib" - , "node_modules" - , "support" - , "test" - , "index.js" - , "Makefile" - , ".*" - ] - , "dependencies": {} - , "devDependencies": {} + "name": "chai", + "version": "2.0.0", + "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.", + "license": "MIT", + "keywords": [ + "test", + "assertion", + "assert", + "testing", + "chai" + ], + "main": "chai.js", + "ignore": [ + "build", + "components", + "lib", + "node_modules", + "support", + "test", + "index.js", + "Makefile", + ".*" + ], + "dependencies": {}, + "devDependencies": {} } diff --git a/bower_components/chai/chai.js b/bower_components/chai/chai.js index 8a6339a1c7..57001bb3fd 100644 --- a/bower_components/chai/chai.js +++ b/bower_components/chai/chai.js @@ -1,206 +1,144 @@ + ;(function(){ /** - * Require the given path. + * Require the module at `name`. * - * @param {String} path + * @param {String} name * @return {Object} exports * @api public */ -function require(path, parent, orig) { - var resolved = require.resolve(path); - - // lookup failed - if (null == resolved) { - orig = orig || path; - parent = parent || 'root'; - var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); - err.path = orig; - err.parent = parent; - err.require = true; - throw err; - } +function require(name) { + var module = require.modules[name]; + if (!module) throw new Error('failed to require "' + name + '"'); - var module = require.modules[resolved]; - - // perform real require() - // by invoking the module's - // registered function - if (!module._resolving && !module.exports) { - var mod = {}; - mod.exports = {}; - mod.client = mod.component = true; - module._resolving = true; - module.call(this, mod.exports, require.relative(resolved), mod); - delete module._resolving; - module.exports = mod.exports; + if (!('exports' in module) && typeof module.definition === 'function') { + module.client = module.component = true; + module.definition.call(this, module.exports = {}, module); + delete module.definition; } return module.exports; } /** - * Registered modules. - */ - -require.modules = {}; - -/** - * Registered aliases. + * Meta info, accessible in the global scope unless you use AMD option. */ -require.aliases = {}; +require.loader = 'component'; /** - * Resolve `path`. - * - * Lookup: - * - * - PATH/index.js - * - PATH.js - * - PATH - * - * @param {String} path - * @return {String} path or null - * @api private + * Internal helper object, contains a sorting function for semantiv versioning */ - -require.resolve = function(path) { - if (path.charAt(0) === '/') path = path.slice(1); - - var paths = [ - path, - path + '.js', - path + '.json', - path + '/index.js', - path + '/index.json' - ]; - - for (var i = 0; i < paths.length; i++) { - var path = paths[i]; - if (require.modules.hasOwnProperty(path)) return path; - if (require.aliases.hasOwnProperty(path)) return require.aliases[path]; +require.helper = {}; +require.helper.semVerSort = function(a, b) { + var aArray = a.version.split('.'); + var bArray = b.version.split('.'); + for (var i=0; i bLex ? 1 : -1; + continue; + } else if (aInt > bInt) { + return 1; + } else { + return -1; + } } -}; + return 0; +} /** - * Normalize `path` relative to the current path. - * - * @param {String} curr - * @param {String} path - * @return {String} - * @api private - */ - -require.normalize = function(curr, path) { - var segs = []; + * Find and require a module which name starts with the provided name. + * If multiple modules exists, the highest semver is used. + * This function can only be used for remote dependencies. - if ('.' != path.charAt(0)) return path; - - curr = curr.split('/'); - path = path.split('/'); - - for (var i = 0; i < path.length; ++i) { - if ('..' == path[i]) { - curr.pop(); - } else if ('.' != path[i] && '' != path[i]) { - segs.push(path[i]); + * @param {String} name - module name: `user~repo` + * @param {Boolean} returnPath - returns the canonical require path if true, + * otherwise it returns the epxorted module + */ +require.latest = function (name, returnPath) { + function showError(name) { + throw new Error('failed to find latest module of "' + name + '"'); + } + // only remotes with semvers, ignore local files conataining a '/' + var versionRegexp = /(.*)~(.*)@v?(\d+\.\d+\.\d+[^\/]*)$/; + var remoteRegexp = /(.*)~(.*)/; + if (!remoteRegexp.test(name)) showError(name); + var moduleNames = Object.keys(require.modules); + var semVerCandidates = []; + var otherCandidates = []; // for instance: name of the git branch + for (var i=0; i 0) { + var module = semVerCandidates.sort(require.helper.semVerSort).pop().name; + if (returnPath === true) { + return module; + } + return require(module); + } + // if the build contains more than one branch of the same module + // you should not use this funciton + var module = otherCandidates.sort(function(a, b) {return a.name > b.name})[0].name; + if (returnPath === true) { + return module; + } + return require(module); +} /** - * Register module at `path` with callback `definition`. - * - * @param {String} path - * @param {Function} definition - * @api private + * Registered modules. */ -require.register = function(path, definition) { - require.modules[path] = definition; -}; +require.modules = {}; /** - * Alias a module definition. + * Register module at `name` with callback `definition`. * - * @param {String} from - * @param {String} to + * @param {String} name + * @param {Function} definition * @api private */ -require.alias = function(from, to) { - if (!require.modules.hasOwnProperty(from)) { - throw new Error('Failed to alias "' + from + '", it does not exist'); - } - require.aliases[to] = from; +require.register = function (name, definition) { + require.modules[name] = { + definition: definition + }; }; /** - * Return a require function relative to the `parent` path. + * Define a module's exports immediately with `exports`. * - * @param {String} parent - * @return {Function} + * @param {String} name + * @param {Generic} exports * @api private */ -require.relative = function(parent) { - var p = require.normalize(parent, '..'); - - /** - * lastIndexOf helper. - */ - - function lastIndexOf(arr, obj) { - var i = arr.length; - while (i--) { - if (arr[i] === obj) return i; - } - return -1; - } - - /** - * The relative require() itself. - */ - - function localRequire(path) { - var resolved = localRequire.resolve(path); - return require(resolved, parent, path); - } - - /** - * Resolve relative to the parent. - */ - - localRequire.resolve = function(path) { - var c = path.charAt(0); - if ('/' == c) return path.slice(1); - if ('.' == c) return require.normalize(p, path); - - // resolve deps by returning - // the dep in the nearest "deps" - // directory - var segs = parent.split('/'); - var i = lastIndexOf(segs, 'deps') + 1; - if (!i) i = 0; - path = segs.slice(0, i + 1).join('/') + '/deps/' + path; - return path; +require.define = function (name, exports) { + require.modules[name] = { + exports: exports }; - - /** - * Check if module is defined at `path`. - */ - - localRequire.exists = function(path) { - return require.modules.hasOwnProperty(localRequire.resolve(path)); - }; - - return localRequire; }; -require.register("chaijs-assertion-error/index.js", function(exports, require, module){ +require.register("chaijs~assertion-error@1.0.0", function (exports, module) { /*! * assertion-error * Copyright(c) 2013 Jake Luer @@ -313,7 +251,8 @@ AssertionError.prototype.toJSON = function (stack) { }; }); -require.register("chaijs-type-detect/lib/type.js", function(exports, require, module){ + +require.register("chaijs~type-detect@0.1.1", function (exports, module) { /*! * type-detect * Copyright(c) 2013 jake luer @@ -458,7 +397,8 @@ Library.prototype.test = function (obj, type) { }; }); -require.register("chaijs-deep-eql/lib/eql.js", function(exports, require, module){ + +require.register("chaijs~deep-eql@0.1.3", function (exports, module) { /*! * deep-eql * Copyright(c) 2013 Jake Luer @@ -469,7 +409,7 @@ require.register("chaijs-deep-eql/lib/eql.js", function(exports, require, module * Module dependencies */ -var type = require('type-detect'); +var type = require('chaijs~type-detect@0.1.1'); /*! * Buffer.isBuffer browser shim @@ -718,11 +658,13 @@ function objectEqual(a, b, m) { } }); -require.register("chai/index.js", function(exports, require, module){ -module.exports = require('./lib/chai'); + +require.register("chai", function (exports, module) { +module.exports = require('chai/lib/chai.js'); }); -require.register("chai/lib/chai.js", function(exports, require, module){ + +require.register("chai/lib/chai.js", function (exports, module) { /*! * chai * Copyright(c) 2011-2014 Jake Luer @@ -736,19 +678,19 @@ var used = [] * Chai version */ -exports.version = '1.8.1'; +exports.version = '1.10.0'; /*! * Assertion Error */ -exports.AssertionError = require('assertion-error'); +exports.AssertionError = require('chaijs~assertion-error@1.0.0'); /*! * Utils for plugins (not exported) */ -var util = require('./chai/utils'); +var util = require('chai/lib/chai/utils/index.js'); /** * # .use(function) @@ -769,43 +711,57 @@ exports.use = function (fn) { return this; }; +/*! + * Utility Functions + */ + +exports.util = util; + +/*! + * Configuration + */ + +var config = require('chai/lib/chai/config.js'); +exports.config = config; + /*! * Primary `Assertion` prototype */ -var assertion = require('./chai/assertion'); +var assertion = require('chai/lib/chai/assertion.js'); exports.use(assertion); /*! * Core Assertions */ -var core = require('./chai/core/assertions'); +var core = require('chai/lib/chai/core/assertions.js'); exports.use(core); /*! * Expect interface */ -var expect = require('./chai/interface/expect'); +var expect = require('chai/lib/chai/interface/expect.js'); exports.use(expect); /*! * Should interface */ -var should = require('./chai/interface/should'); +var should = require('chai/lib/chai/interface/should.js'); exports.use(should); /*! * Assert interface */ -var assert = require('./chai/interface/assert'); +var assert = require('chai/lib/chai/interface/assert.js'); exports.use(assert); }); -require.register("chai/lib/chai/assertion.js", function(exports, require, module){ + +require.register("chai/lib/chai/assertion.js", function (exports, module) { /*! * chai * http://chaijs.com @@ -813,6 +769,8 @@ require.register("chai/lib/chai/assertion.js", function(exports, require, module * MIT Licensed */ +var config = require('chai/lib/chai/config.js'); + module.exports = function (_chai, util) { /*! * Module dependencies. @@ -841,33 +799,27 @@ module.exports = function (_chai, util) { flag(this, 'message', msg); } - /*! - * ### Assertion.includeStack - * - * User configurable property, influences whether stack trace - * is included in Assertion error message. Default of false - * suppresses stack trace in the error message - * - * Assertion.includeStack = true; // enable stack on error - * - * @api public - */ - - Assertion.includeStack = false; - - /*! - * ### Assertion.showDiff - * - * User configurable property, influences whether or not - * the `showDiff` flag should be included in the thrown - * AssertionErrors. `false` will always be `false`; `true` - * will be true when the assertion has requested a diff - * be shown. - * - * @api public - */ + Object.defineProperty(Assertion, 'includeStack', { + get: function() { + console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); + return config.includeStack; + }, + set: function(value) { + console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); + config.includeStack = value; + } + }); - Assertion.showDiff = true; + Object.defineProperty(Assertion, 'showDiff', { + get: function() { + console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); + return config.showDiff; + }, + set: function(value) { + console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); + config.showDiff = value; + } + }); Assertion.addProperty = function (name, fn) { util.addProperty(this.prototype, name, fn); @@ -900,8 +852,8 @@ module.exports = function (_chai, util) { * * @name assert * @param {Philosophical} expression to be tested - * @param {String} message to display if fails - * @param {String} negatedMessage to display if negated expression fails + * @param {String or Function} message or function that returns message to display if fails + * @param {String or Function} negatedMessage or function that returns negatedMessage to display if negated expression fails * @param {Mixed} expected value (remember to check for negation) * @param {Mixed} actual (optional) will default to `this.obj` * @api private @@ -910,7 +862,7 @@ module.exports = function (_chai, util) { Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) { var ok = util.test(this, arguments); if (true !== showDiff) showDiff = false; - if (true !== Assertion.showDiff) showDiff = false; + if (true !== config.showDiff) showDiff = false; if (!ok) { var msg = util.getMessage(this, arguments) @@ -919,7 +871,7 @@ module.exports = function (_chai, util) { actual: actual , expected: expected , showDiff: showDiff - }, (Assertion.includeStack) ? this.assert : flag(this, 'ssfi')); + }, (config.includeStack) ? this.assert : flag(this, 'ssfi')); } }; @@ -942,7 +894,62 @@ module.exports = function (_chai, util) { }; }); -require.register("chai/lib/chai/core/assertions.js", function(exports, require, module){ + +require.register("chai/lib/chai/config.js", function (exports, module) { +module.exports = { + + /** + * ### config.includeStack + * + * User configurable property, influences whether stack trace + * is included in Assertion error message. Default of false + * suppresses stack trace in the error message. + * + * chai.config.includeStack = true; // enable stack on error + * + * @param {Boolean} + * @api public + */ + + includeStack: false, + + /** + * ### config.showDiff + * + * User configurable property, influences whether or not + * the `showDiff` flag should be included in the thrown + * AssertionErrors. `false` will always be `false`; `true` + * will be true when the assertion has requested a diff + * be shown. + * + * @param {Boolean} + * @api public + */ + + showDiff: true, + + /** + * ### config.truncateThreshold + * + * User configurable property, sets length threshold for actual and + * expected values in assertion errors. If this threshold is exceeded, + * the value is truncated. + * + * Set it to zero if you want to disable truncating altogether. + * + * chai.config.truncateThreshold = 0; // disable truncating + * + * @param {Number} + * @api public + */ + + truncateThreshold: 40 + +}; + +}); + +require.register("chai/lib/chai/core/assertions.js", function (exports, module) { /*! * chai * http://chaijs.com @@ -960,7 +967,7 @@ module.exports = function (chai, _) { * * The following are provided as chainable getters to * improve the readability of your assertions. They - * do not provide an testing capability unless they + * do not provide testing capabilities unless they * have been overwritten by a plugin. * * **Chains** @@ -970,6 +977,7 @@ module.exports = function (chai, _) { * - been * - is * - that + * - which * - and * - has * - have @@ -984,7 +992,7 @@ module.exports = function (chai, _) { [ 'to', 'be', 'been' , 'is', 'and', 'has', 'have' - , 'with', 'that', 'at' + , 'with', 'that', 'which', 'at' , 'of', 'same' ].forEach(function (chain) { Assertion.addProperty(chain, function () { return this; @@ -1027,6 +1035,41 @@ module.exports = function (chai, _) { flag(this, 'deep', true); }); + /** + * ### .any + * + * Sets the `any` flag, (opposite of the `all` flag) + * later used in the `keys` assertion. + * + * expect(foo).to.have.any.keys('bar', 'baz'); + * + * @name any + * @api public + */ + + Assertion.addProperty('any', function () { + flag(this, 'any', true); + flag(this, 'all', false) + }); + + + /** + * ### .all + * + * Sets the `all` flag (opposite of the `any` flag) + * later used by the `keys` assertion. + * + * expect(foo).to.have.all.keys('bar', 'baz'); + * + * @name all + * @api public + */ + + Assertion.addProperty('all', function () { + flag(this, 'all', true); + flag(this, 'any', false); + }); + /** * ### .a(type) * @@ -1072,7 +1115,7 @@ module.exports = function (chai, _) { * The `include` and `contain` assertions can be used as either property * based language chains or as methods to assert the inclusion of an object * in an array or a substring in a string. When used as language chains, - * they toggle the `contain` flag for the `keys` assertion. + * they toggle the `contains` flag for the `keys` assertion. * * expect([1,2,3]).to.include(2); * expect('foobar').to.contain('foo'); @@ -1080,6 +1123,8 @@ module.exports = function (chai, _) { * * @name include * @alias contain + * @alias includes + * @alias contains * @param {Object|String|Number} obj * @param {String} message _optional_ * @api public @@ -1092,17 +1137,24 @@ module.exports = function (chai, _) { function include (val, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); - - if (_.type(val) === 'object') { + var expected = false; + if (_.type(obj) === 'array' && _.type(val) === 'object') { + for (var i in obj) { + if (_.eql(obj[i], val)) { + expected = true; + break; + } + } + } else if (_.type(val) === 'object') { if (!flag(this, 'negate')) { for (var k in val) new Assertion(obj).property(k, val[k]); return; } - var subset = {} - for (var k in val) subset[k] = obj[k] - var expected = _.eql(subset, val); + var subset = {}; + for (var k in val) subset[k] = obj[k]; + expected = _.eql(subset, val); } else { - var expected = obj && ~obj.indexOf(val) + expected = obj && ~obj.indexOf(val); } this.assert( expected @@ -1112,6 +1164,8 @@ module.exports = function (chai, _) { Assertion.addChainableMethod('include', include, includeChainingBehavior); Assertion.addChainableMethod('contain', include, includeChainingBehavior); + Assertion.addChainableMethod('contains', include, includeChainingBehavior); + Assertion.addChainableMethod('includes', include, includeChainingBehavior); /** * ### .ok @@ -1703,11 +1757,16 @@ module.exports = function (chai, _) { Assertion.addMethod('property', function (name, val, msg) { if (msg) flag(this, 'message', msg); - var descriptor = flag(this, 'deep') ? 'deep property ' : 'property ' + var isDeep = !!flag(this, 'deep') + , descriptor = isDeep ? 'deep property ' : 'property ' , negate = flag(this, 'negate') , obj = flag(this, 'object') - , value = flag(this, 'deep') - ? _.getPathValue(name, obj) + , pathInfo = isDeep ? _.getPathInfo(name, obj) : null + , hasProperty = isDeep + ? pathInfo.exists + : _.hasProperty(name, obj) + , value = isDeep + ? pathInfo.value : obj[name]; if (negate && undefined !== val) { @@ -1717,7 +1776,7 @@ module.exports = function (chai, _) { } } else { this.assert( - undefined !== value + hasProperty , 'expected #{this} to have a ' + descriptor + _.inspect(name) , 'expected #{this} to not have ' + descriptor + _.inspect(name)); } @@ -1809,7 +1868,7 @@ module.exports = function (chai, _) { } Assertion.addChainableMethod('length', assertLength, assertLengthChain); - Assertion.addMethod('lengthOf', assertLength, assertLengthChain); + Assertion.addMethod('lengthOf', assertLength); /** * ### .match(regexp) @@ -1863,41 +1922,87 @@ module.exports = function (chai, _) { /** * ### .keys(key1, [key2], [...]) * - * Asserts that the target has exactly the given keys, or - * asserts the inclusion of some keys when using the - * `include` or `contain` modifiers. + * Asserts that the target contains any or all of the passed-in keys. + * Use in combination with `any`, `all`, `contains`, or `have` will affect + * what will pass. + * + * When used in conjunction with `any`, at least one key that is passed + * in must exist in the target object. This is regardless whether or not + * the `have` or `contain` qualifiers are used. Note, either `any` or `all` + * should be used in the assertion. If neither are used, the assertion is + * defaulted to `all`. + * + * When both `all` and `contain` are used, the target object must have at + * least all of the passed-in keys but may have more keys not listed. + * + * When both `all` and `have` are used, the target object must both contain + * all of the passed-in keys AND the number of keys in the target object must + * match the number of keys passed in (in other words, a target object must + * have all and only all of the passed-in keys). + * + * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz'); + * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo'); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz'); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6}); + * expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']); + * expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo', 7}); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys([{'bar': 6}}]); * - * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); - * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); * * @name keys * @alias key - * @param {String...|Array} keys + * @param {String...|Array|Object} keys * @api public */ function assertKeys (keys) { var obj = flag(this, 'object') , str - , ok = true; - - keys = keys instanceof Array - ? keys - : Array.prototype.slice.call(arguments); + , ok = true + , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments'; + + switch (_.type(keys)) { + case "array": + if (arguments.length > 1) throw (new Error(mixedArgsMsg)); + break; + case "object": + if (arguments.length > 1) throw (new Error(mixedArgsMsg)); + keys = Object.keys(keys); + break; + default: + keys = Array.prototype.slice.call(arguments); + } if (!keys.length) throw new Error('keys required'); var actual = Object.keys(obj) - , len = keys.length; + , expected = keys + , len = keys.length + , any = flag(this, 'any') + , all = flag(this, 'all'); - // Inclusion - ok = keys.every(function(key){ - return ~actual.indexOf(key); - }); + if (!any && !all) { + all = true; + } + + // Has any + if (any) { + var intersection = expected.filter(function(key) { + return ~actual.indexOf(key); + }); + ok = intersection.length > 0; + } - // Strict - if (!flag(this, 'negate') && !flag(this, 'contains')) { - ok = ok && keys.length == actual.length; + // Has all + if (all) { + ok = keys.every(function(key){ + return ~actual.indexOf(key); + }); + if (!flag(this, 'negate') && !flag(this, 'contains')) { + ok = ok && keys.length == actual.length; + } } // Key string @@ -1906,7 +2011,12 @@ module.exports = function (chai, _) { return _.inspect(key); }); var last = keys.pop(); - str = keys.join(', ') + ', and ' + last; + if (all) { + str = keys.join(', ') + ', and ' + last; + } + if (any) { + str = keys.join(', ') + ', or ' + last; + } } else { str = _.inspect(keys[0]); } @@ -1922,6 +2032,9 @@ module.exports = function (chai, _) { ok , 'expected #{this} to ' + str , 'expected #{this} to not ' + str + , expected.slice(0).sort() + , actual.sort() + , true ); } @@ -2157,12 +2270,13 @@ module.exports = function (chai, _) { Assertion.addMethod('satisfy', function (matcher, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); + var result = matcher(obj); this.assert( - matcher(obj) + result , 'expected #{this} to satisfy ' + _.objDisplay(matcher) , 'expected #{this} to not satisfy' + _.objDisplay(matcher) , this.negate ? false : true - , matcher(obj) + , result ); }); @@ -2183,6 +2297,12 @@ module.exports = function (chai, _) { Assertion.addMethod('closeTo', function (expected, delta, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); + + new Assertion(obj, msg).is.a('number'); + if (_.type(expected) !== 'number' || _.type(delta) !== 'number') { + throw new Error('the arguments to closeTo must be numbers'); + } + this.assert( Math.abs(obj - expected) <= delta , 'expected #{this} to be close to ' + expected + ' +/- ' + delta @@ -2190,9 +2310,13 @@ module.exports = function (chai, _) { ); }); - function isSubsetOf(subset, superset) { + function isSubsetOf(subset, superset, cmp) { return subset.every(function(elem) { - return superset.indexOf(elem) !== -1; + if (!cmp) return superset.indexOf(elem) !== -1; + + return superset.some(function(elem2) { + return cmp(elem, elem2); + }); }) } @@ -2200,7 +2324,9 @@ module.exports = function (chai, _) { * ### .members(set) * * Asserts that the target is a superset of `set`, - * or that the target and `set` have the same members. + * or that the target and `set` have the same strictly-equal (===) members. + * Alternately, if the `deep` flag is set, set members are compared for deep + * equality. * * expect([1, 2, 3]).to.include.members([3, 2]); * expect([1, 2, 3]).to.not.include.members([3, 2, 8]); @@ -2208,6 +2334,8 @@ module.exports = function (chai, _) { * expect([4, 2]).to.have.members([2, 4]); * expect([5, 2]).to.not.have.members([5, 2, 1]); * + * expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]); + * * @name members * @param {Array} set * @param {String} message _optional_ @@ -2221,9 +2349,11 @@ module.exports = function (chai, _) { new Assertion(obj).to.be.an('array'); new Assertion(subset).to.be.an('array'); + var cmp = flag(this, 'deep') ? _.eql : undefined; + if (flag(this, 'contains')) { return this.assert( - isSubsetOf(subset, obj) + isSubsetOf(subset, obj, cmp) , 'expected #{this} to be a superset of #{act}' , 'expected #{this} to not be a superset of #{act}' , obj @@ -2232,17 +2362,132 @@ module.exports = function (chai, _) { } this.assert( - isSubsetOf(obj, subset) && isSubsetOf(subset, obj) + isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp) , 'expected #{this} to have the same members as #{act}' , 'expected #{this} to not have the same members as #{act}' , obj , subset ); }); + + /** + * ### .change(function) + * + * Asserts that a function changes an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 3 }; + * var noChangeFn = function() { return 'foo' + 'bar'; } + * expect(fn).to.change(obj, 'val'); + * expect(noChangFn).to.not.change(obj, 'val') + * + * @name change + * @alias changes + * @alias Change + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + function assertChanges (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + initial !== object[prop] + , 'expected .' + prop + ' to change' + , 'expected .' + prop + ' to not change' + ); + } + + Assertion.addChainableMethod('change', assertChanges); + Assertion.addChainableMethod('changes', assertChanges); + + /** + * ### .increase(function) + * + * Asserts that a function increases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * expect(fn).to.increase(obj, 'val'); + * + * @name increase + * @alias increases + * @alias Increase + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + function assertIncreases (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + object[prop] - initial > 0 + , 'expected .' + prop + ' to increase' + , 'expected .' + prop + ' to not increase' + ); + } + + Assertion.addChainableMethod('increase', assertIncreases); + Assertion.addChainableMethod('increases', assertIncreases); + + /** + * ### .decrease(function) + * + * Asserts that a function decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * expect(fn).to.decrease(obj, 'val'); + * + * @name decrease + * @alias decreases + * @alias Decrease + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + function assertDecreases (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + object[prop] - initial < 0 + , 'expected .' + prop + ' to decrease' + , 'expected .' + prop + ' to not decrease' + ); + } + + Assertion.addChainableMethod('decrease', assertDecreases); + Assertion.addChainableMethod('decreases', assertDecreases); + }; }); -require.register("chai/lib/chai/interface/assert.js", function(exports, require, module){ + +require.register("chai/lib/chai/interface/assert.js", function (exports, module) { /*! * chai * Copyright(c) 2011-2014 Jake Luer @@ -2278,7 +2523,7 @@ module.exports = function (chai, util) { */ var assert = chai.assert = function (express, errmsg) { - var test = new Assertion(null); + var test = new Assertion(null, null, chai.assert); test.assert( express , errmsg @@ -2359,7 +2604,7 @@ module.exports = function (chai, util) { */ assert.equal = function (act, exp, msg) { - var test = new Assertion(act, msg); + var test = new Assertion(act, msg, assert.equal); test.assert( exp == flag(test, 'object') @@ -2385,7 +2630,7 @@ module.exports = function (chai, util) { */ assert.notEqual = function (act, exp, msg) { - var test = new Assertion(act, msg); + var test = new Assertion(act, msg, assert.notEqual); test.assert( exp != flag(test, 'object') @@ -2482,6 +2727,42 @@ module.exports = function (chai, util) { * @api public */ + assert.isAbove = function (val, abv, msg) { + new Assertion(val, msg).to.be.above(abv); + }; + + /** + * ### .isAbove(valueToCheck, valueToBeAbove, [message]) + * + * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove` + * + * assert.isAbove(5, 2, '5 is strictly greater than 2'); + * + * @name isAbove + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAbove + * @param {String} message + * @api public + */ + + assert.isBelow = function (val, blw, msg) { + new Assertion(val, msg).to.be.below(blw); + }; + + /** + * ### .isBelow(valueToCheck, valueToBeBelow, [message]) + * + * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow` + * + * assert.isBelow(3, 6, '3 is strictly less than 6'); + * + * @name isBelow + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeBelow + * @param {String} message + * @api public + */ + assert.isTrue = function (val, msg) { new Assertion(val, msg).is['true']; }; @@ -2636,8 +2917,8 @@ module.exports = function (chai, util) { * Asserts that `value` is _not_ an object. * * var selection = 'chai' - * assert.isObject(selection, 'tea selection is not an object'); - * assert.isObject(null, 'null is not an object'); + * assert.isNotObject(selection, 'tea selection is not an object'); + * assert.isNotObject(null, 'null is not an object'); * * @name isNotObject * @param {Mixed} value @@ -2901,7 +3182,7 @@ module.exports = function (chai, util) { */ assert.include = function (exp, inc, msg) { - new Assertion(exp, msg).include(inc); + new Assertion(exp, msg, assert.include).include(inc); }; /** @@ -2921,7 +3202,7 @@ module.exports = function (chai, util) { */ assert.notInclude = function (exp, inc, msg) { - new Assertion(exp, msg).not.include(inc); + new Assertion(exp, msg, assert.notInclude).not.include(inc); }; /** @@ -3251,8 +3532,8 @@ module.exports = function (chai, util) { * assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members'); * * @name sameMembers - * @param {Array} superset - * @param {Array} subset + * @param {Array} set1 + * @param {Array} set2 * @param {String} message * @api public */ @@ -3261,6 +3542,25 @@ module.exports = function (chai, util) { new Assertion(set1, msg).to.have.same.members(set2); } + /** + * ### .sameDeepMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members - using a deep equality checking. + * Order is not taken into account. + * + * assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members'); + * + * @name sameDeepMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @api public + */ + + assert.sameDeepMembers = function (set1, set2, msg) { + new Assertion(set1, msg).to.have.same.deep.members(set2); + } + /** * ### .includeMembers(superset, subset, [message]) * @@ -3280,6 +3580,132 @@ module.exports = function (chai, util) { new Assertion(superset, msg).to.include.members(subset); } + /** + * ### .changes(function, object, property) + * + * Asserts that a function changes the value of a property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 22 }; + * assert.changes(fn, obj, 'val'); + * + * @name changes + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.changes = function (fn, obj, prop) { + new Assertion(fn).to.change(obj, prop); + } + + /** + * ### .doesNotChange(function, object, property) + * + * Asserts that a function does not changes the value of a property + * + * var obj = { val: 10 }; + * var fn = function() { console.log('foo'); }; + * assert.doesNotChange(fn, obj, 'val'); + * + * @name doesNotChange + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.doesNotChange = function (fn, obj, prop) { + new Assertion(fn).to.not.change(obj, prop); + } + + /** + * ### .increases(function, object, property) + * + * Asserts that a function increases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 13 }; + * assert.increases(fn, obj, 'val'); + * + * @name increases + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.increases = function (fn, obj, prop) { + new Assertion(fn).to.increase(obj, prop); + } + + /** + * ### .doesNotIncrease(function, object, property) + * + * Asserts that a function does not increase object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 8 }; + * assert.doesNotIncrease(fn, obj, 'val'); + * + * @name doesNotIncrease + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.doesNotIncrease = function (fn, obj, prop) { + new Assertion(fn).to.not.increase(obj, prop); + } + + /** + * ### .decreases(function, object, property) + * + * Asserts that a function decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.decreases(fn, obj, 'val'); + * + * @name decreases + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.decreases = function (fn, obj, prop) { + new Assertion(fn).to.decrease(obj, prop); + } + + /** + * ### .doesNotDecrease(function, object, property) + * + * Asserts that a function does not decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * assert.doesNotDecrease(fn, obj, 'val'); + * + * @name doesNotDecrease + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.doesNotDecrease = function (fn, obj, prop) { + new Assertion(fn).to.not.decrease(obj, prop); + } + /*! * Undocumented / untested */ @@ -3301,7 +3727,8 @@ module.exports = function (chai, util) { }; }); -require.register("chai/lib/chai/interface/expect.js", function(exports, require, module){ + +require.register("chai/lib/chai/interface/expect.js", function (exports, module) { /*! * chai * Copyright(c) 2011-2014 Jake Luer @@ -3316,7 +3743,8 @@ module.exports = function (chai, util) { }); -require.register("chai/lib/chai/interface/should.js", function(exports, require, module){ + +require.register("chai/lib/chai/interface/should.js", function (exports, module) { /*! * chai * Copyright(c) 2011-2014 Jake Luer @@ -3327,31 +3755,33 @@ module.exports = function (chai, util) { var Assertion = chai.Assertion; function loadShould () { + // explicitly define this method as function as to have it's name to include as `ssfi` + function shouldGetter() { + if (this instanceof String || this instanceof Number) { + return new Assertion(this.constructor(this), null, shouldGetter); + } else if (this instanceof Boolean) { + return new Assertion(this == true, null, shouldGetter); + } + return new Assertion(this, null, shouldGetter); + } + function shouldSetter(value) { + // See https://github.com/chaijs/chai/issues/86: this makes + // `whatever.should = someValue` actually set `someValue`, which is + // especially useful for `global.should = require('chai').should()`. + // + // Note that we have to use [[DefineProperty]] instead of [[Put]] + // since otherwise we would trigger this very setter! + Object.defineProperty(this, 'should', { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } // modify Object.prototype to have `should` - Object.defineProperty(Object.prototype, 'should', - { - set: function (value) { - // See https://github.com/chaijs/chai/issues/86: this makes - // `whatever.should = someValue` actually set `someValue`, which is - // especially useful for `global.should = require('chai').should()`. - // - // Note that we have to use [[DefineProperty]] instead of [[Put]] - // since otherwise we would trigger this very setter! - Object.defineProperty(this, 'should', { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } - , get: function(){ - if (this instanceof String || this instanceof Number) { - return new Assertion(this.constructor(this)); - } else if (this instanceof Boolean) { - return new Assertion(this == true); - } - return new Assertion(this); - } + Object.defineProperty(Object.prototype, 'should', { + set: shouldSetter + , get: shouldGetter , configurable: true }); @@ -3395,7 +3825,8 @@ module.exports = function (chai, util) { }; }); -require.register("chai/lib/chai/utils/addChainableMethod.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/addChainableMethod.js", function (exports, module) { /*! * Chai - addChainingMethod utility * Copyright(c) 2012-2014 Jake Luer @@ -3406,7 +3837,9 @@ require.register("chai/lib/chai/utils/addChainableMethod.js", function(exports, * Module dependencies */ -var transferFlags = require('./transferFlags'); +var transferFlags = require('chai/lib/chai/utils/transferFlags.js'); +var flag = require('chai/lib/chai/utils/flag.js'); +var config = require('chai/lib/chai/config.js'); /*! * Module variables @@ -3472,7 +3905,10 @@ module.exports = function (ctx, name, method, chainingBehavior) { { get: function () { chainableBehavior.chainingBehavior.call(this); - var assert = function () { + var assert = function assert() { + var old_ssfi = flag(this, 'ssfi'); + if (old_ssfi && config.includeStack === false) + flag(this, 'ssfi', assert); var result = chainableBehavior.method.apply(this, arguments); return result === undefined ? this : result; }; @@ -3504,13 +3940,16 @@ module.exports = function (ctx, name, method, chainingBehavior) { }; }); -require.register("chai/lib/chai/utils/addMethod.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/addMethod.js", function (exports, module) { /*! * Chai - addMethod utility * Copyright(c) 2012-2014 Jake Luer * MIT Licensed */ +var config = require('chai/lib/chai/config.js'); + /** * ### .addMethod (ctx, name, method) * @@ -3535,16 +3974,21 @@ require.register("chai/lib/chai/utils/addMethod.js", function(exports, require, * @name addMethod * @api public */ +var flag = require('chai/lib/chai/utils/flag.js'); module.exports = function (ctx, name, method) { ctx[name] = function () { + var old_ssfi = flag(this, 'ssfi'); + if (old_ssfi && config.includeStack === false) + flag(this, 'ssfi', ctx[name]); var result = method.apply(this, arguments); return result === undefined ? this : result; }; }; }); -require.register("chai/lib/chai/utils/addProperty.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/addProperty.js", function (exports, module) { /*! * Chai - addProperty utility * Copyright(c) 2012-2014 Jake Luer @@ -3587,7 +4031,8 @@ module.exports = function (ctx, name, getter) { }; }); -require.register("chai/lib/chai/utils/flag.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/flag.js", function (exports, module) { /*! * Chai - flag utility * Copyright(c) 2012-2014 Jake Luer @@ -3595,7 +4040,7 @@ require.register("chai/lib/chai/utils/flag.js", function(exports, require, modul */ /** - * ### flag(object ,key, [value]) + * ### flag(object, key, [value]) * * Get or set a flag value on an object. If a * value is provided it will be set, else it will @@ -3605,7 +4050,7 @@ require.register("chai/lib/chai/utils/flag.js", function(exports, require, modul * utils.flag(this, 'foo', 'bar'); // setter * utils.flag(this, 'foo'); // getter, returns `bar` * - * @param {Object} object (constructed Assertion + * @param {Object} object constructed Assertion * @param {String} key * @param {Mixed} value (optional) * @name flag @@ -3622,7 +4067,8 @@ module.exports = function (obj, key, value) { }; }); -require.register("chai/lib/chai/utils/getActual.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/getActual.js", function (exports, module) { /*! * Chai - getActual utility * Copyright(c) 2012-2014 Jake Luer @@ -3639,12 +4085,12 @@ require.register("chai/lib/chai/utils/getActual.js", function(exports, require, */ module.exports = function (obj, args) { - var actual = args[4]; - return 'undefined' !== typeof actual ? actual : obj._obj; + return args.length > 4 ? args[4] : obj._obj; }; }); -require.register("chai/lib/chai/utils/getEnumerableProperties.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/getEnumerableProperties.js", function (exports, module) { /*! * Chai - getEnumerableProperties utility * Copyright(c) 2012-2014 Jake Luer @@ -3672,7 +4118,8 @@ module.exports = function getEnumerableProperties(object) { }; }); -require.register("chai/lib/chai/utils/getMessage.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/getMessage.js", function (exports, module) { /*! * Chai - message composition utility * Copyright(c) 2012-2014 Jake Luer @@ -3683,10 +4130,10 @@ require.register("chai/lib/chai/utils/getMessage.js", function(exports, require, * Module dependancies */ -var flag = require('./flag') - , getActual = require('./getActual') - , inspect = require('./inspect') - , objDisplay = require('./objDisplay'); +var flag = require('chai/lib/chai/utils/flag.js') + , getActual = require('chai/lib/chai/utils/getActual.js') + , inspect = require('chai/lib/chai/utils/inspect.js') + , objDisplay = require('chai/lib/chai/utils/objDisplay.js'); /** * ### .getMessage(object, message, negateMessage) @@ -3714,6 +4161,7 @@ module.exports = function (obj, args) { , msg = negate ? args[2] : args[1] , flagMsg = flag(obj, 'message'); + if(typeof msg === "function") msg = msg(); msg = msg || ''; msg = msg .replace(/#{this}/g, objDisplay(val)) @@ -3724,7 +4172,8 @@ module.exports = function (obj, args) { }; }); -require.register("chai/lib/chai/utils/getName.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/getName.js", function (exports, module) { /*! * Chai - getName utility * Copyright(c) 2012-2014 Jake Luer @@ -3747,7 +4196,8 @@ module.exports = function (func) { }; }); -require.register("chai/lib/chai/utils/getPathValue.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/getPathValue.js", function (exports, module) { /*! * Chai - getPathValue utility * Copyright(c) 2012-2014 Jake Luer @@ -3755,6 +4205,8 @@ require.register("chai/lib/chai/utils/getPathValue.js", function(exports, requir * MIT Licensed */ +var getPathInfo = require('chai/lib/chai/utils/getPathInfo.js'); + /** * ### .getPathValue(path, object) * @@ -3784,12 +4236,58 @@ require.register("chai/lib/chai/utils/getPathValue.js", function(exports, requir * @name getPathValue * @api public */ +module.exports = function(path, obj) { + var info = getPathInfo(path, obj); + return info.value; +}; + +}); -var getPathValue = module.exports = function (path, obj) { - var parsed = parsePath(path); - return _getPathValue(parsed, obj); +require.register("chai/lib/chai/utils/getPathInfo.js", function (exports, module) { +/*! + * Chai - getPathInfo utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +var hasProperty = require('chai/lib/chai/utils/hasProperty.js'); + +/** + * ### .getPathInfo(path, object) + * + * This allows the retrieval of property info in an + * object given a string path. + * + * The path info consists of an object with the + * following properties: + * + * * parent - The parent object of the property referenced by `path` + * * name - The name of the final property, a number if it was an array indexer + * * value - The value of the property, if it exists, otherwise `undefined` + * * exists - Whether the property exists or not + * + * @param {String} path + * @param {Object} object + * @returns {Object} info + * @name getPathInfo + * @api public + */ + +module.exports = function getPathInfo(path, obj) { + var parsed = parsePath(path), + last = parsed[parsed.length - 1]; + + var info = { + parent: _getPathValue(parsed, obj, parsed.length - 1), + name: last.p || last.i, + value: _getPathValue(parsed, obj), + }; + info.exists = hasProperty(info.name, info.parent); + + return info; }; + /*! * ## parsePath(path) * @@ -3813,11 +4311,12 @@ function parsePath (path) { , parts = str.match(/(\\\.|[^.]+?)+/g); return parts.map(function (value) { var re = /\[(\d+)\]$/ - , mArr = re.exec(value) + , mArr = re.exec(value); if (mArr) return { i: parseFloat(mArr[1]) }; else return { p: value }; }); -}; +} + /*! * ## _getPathValue(parsed, obj) @@ -3829,14 +4328,18 @@ function parsePath (path) { * * @param {Object} parsed definition from `parsePath`. * @param {Object} object to search against + * @param {Number} object to search against * @returns {Object|Undefined} value * @api private */ -function _getPathValue (parsed, obj) { +function _getPathValue (parsed, obj, index) { var tmp = obj , res; - for (var i = 0, l = parsed.length; i < l; i++) { + + index = (index === undefined ? parsed.length : index); + + for (var i = 0, l = index; i < l; i++) { var part = parsed[i]; if (tmp) { if ('undefined' !== typeof part.p) @@ -3849,10 +4352,78 @@ function _getPathValue (parsed, obj) { } } return res; +} + +}); + +require.register("chai/lib/chai/utils/hasProperty.js", function (exports, module) { +/*! + * Chai - hasProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +var type = require('chai/lib/chai/utils/type.js'); + +/** + * ### .hasProperty(object, name) + * + * This allows checking whether an object has + * named property or numeric array index. + * + * Basically does the same thing as the `in` + * operator but works properly with natives + * and null/undefined values. + * + * var obj = { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * + * The following would be the results. + * + * hasProperty('str', obj); // true + * hasProperty('constructor', obj); // true + * hasProperty('bar', obj); // false + * + * hasProperty('length', obj.str); // true + * hasProperty(1, obj.str); // true + * hasProperty(5, obj.str); // false + * + * hasProperty('length', obj.arr); // true + * hasProperty(2, obj.arr); // true + * hasProperty(3, obj.arr); // false + * + * @param {Objuect} object + * @param {String|Number} name + * @returns {Boolean} whether it exists + * @name getPathInfo + * @api public + */ + +var literals = { + 'number': Number + , 'string': String +}; + +module.exports = function hasProperty(name, obj) { + var ot = type(obj); + + // Bad Object, obviously no props at all + if(ot === 'null' || ot === 'undefined') + return false; + + // The `in` operator does not work with certain literals + // box these before the check + if(literals[ot] && typeof obj !== 'object') + obj = new literals[ot](obj); + + return name in obj; }; }); -require.register("chai/lib/chai/utils/getProperties.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/getProperties.js", function (exports, module) { /*! * Chai - getProperties utility * Copyright(c) 2012-2014 Jake Luer @@ -3890,7 +4461,8 @@ module.exports = function getProperties(object) { }; }); -require.register("chai/lib/chai/utils/index.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/index.js", function (exports, module) { /*! * chai * Copyright(c) 2011 Jake Luer @@ -3907,113 +4479,126 @@ var exports = module.exports = {}; * test utility */ -exports.test = require('./test'); +exports.test = require('chai/lib/chai/utils/test.js'); /*! * type utility */ -exports.type = require('./type'); +exports.type = require('chai/lib/chai/utils/type.js'); /*! * message utility */ -exports.getMessage = require('./getMessage'); +exports.getMessage = require('chai/lib/chai/utils/getMessage.js'); /*! * actual utility */ -exports.getActual = require('./getActual'); +exports.getActual = require('chai/lib/chai/utils/getActual.js'); /*! * Inspect util */ -exports.inspect = require('./inspect'); +exports.inspect = require('chai/lib/chai/utils/inspect.js'); /*! * Object Display util */ -exports.objDisplay = require('./objDisplay'); +exports.objDisplay = require('chai/lib/chai/utils/objDisplay.js'); /*! * Flag utility */ -exports.flag = require('./flag'); +exports.flag = require('chai/lib/chai/utils/flag.js'); /*! * Flag transferring utility */ -exports.transferFlags = require('./transferFlags'); +exports.transferFlags = require('chai/lib/chai/utils/transferFlags.js'); /*! * Deep equal utility */ -exports.eql = require('deep-eql'); +exports.eql = require('chaijs~deep-eql@0.1.3'); /*! * Deep path value */ -exports.getPathValue = require('./getPathValue'); +exports.getPathValue = require('chai/lib/chai/utils/getPathValue.js'); + +/*! + * Deep path info + */ + +exports.getPathInfo = require('chai/lib/chai/utils/getPathInfo.js'); + +/*! + * Check if a property exists + */ + +exports.hasProperty = require('chai/lib/chai/utils/hasProperty.js'); /*! * Function name */ -exports.getName = require('./getName'); +exports.getName = require('chai/lib/chai/utils/getName.js'); /*! * add Property */ -exports.addProperty = require('./addProperty'); +exports.addProperty = require('chai/lib/chai/utils/addProperty.js'); /*! * add Method */ -exports.addMethod = require('./addMethod'); +exports.addMethod = require('chai/lib/chai/utils/addMethod.js'); /*! * overwrite Property */ -exports.overwriteProperty = require('./overwriteProperty'); +exports.overwriteProperty = require('chai/lib/chai/utils/overwriteProperty.js'); /*! * overwrite Method */ -exports.overwriteMethod = require('./overwriteMethod'); +exports.overwriteMethod = require('chai/lib/chai/utils/overwriteMethod.js'); /*! * Add a chainable method */ -exports.addChainableMethod = require('./addChainableMethod'); +exports.addChainableMethod = require('chai/lib/chai/utils/addChainableMethod.js'); /*! * Overwrite chainable method */ -exports.overwriteChainableMethod = require('./overwriteChainableMethod'); +exports.overwriteChainableMethod = require('chai/lib/chai/utils/overwriteChainableMethod.js'); }); -require.register("chai/lib/chai/utils/inspect.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/inspect.js", function (exports, module) { // This is (almost) directly from Node.js utils // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js -var getName = require('./getName'); -var getProperties = require('./getProperties'); -var getEnumerableProperties = require('./getEnumerableProperties'); +var getName = require('chai/lib/chai/utils/getName.js'); +var getProperties = require('chai/lib/chai/utils/getProperties.js'); +var getEnumerableProperties = require('chai/lib/chai/utils/getEnumerableProperties.js'); module.exports = inspect; @@ -4037,24 +4622,6 @@ function inspect(obj, showHidden, depth, colors) { return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth)); } -// https://gist.github.com/1044128/ -var getOuterHTML = function(element) { - if ('outerHTML' in element) return element.outerHTML; - var ns = "http://www.w3.org/1999/xhtml"; - var container = document.createElementNS(ns, '_'); - var elemProto = (window.HTMLElement || window.Element).prototype; - var xmlSerializer = new XMLSerializer(); - var html; - if (document.xmlVersion) { - return xmlSerializer.serializeToString(element); - } else { - container.appendChild(element.cloneNode(false)); - html = container.innerHTML.replace('><', '>' + element.innerHTML + '<'); - container.innerHTML = ''; - return html; - } -}; - // Returns true if object is a DOM element. var isDOMElement = function (object) { if (typeof HTMLElement === 'object') { @@ -4088,9 +4655,37 @@ function formatValue(ctx, value, recurseTimes) { return primitive; } - // If it's DOM elem, get outer HTML. + // If this is a DOM element, try to get the outer HTML. if (isDOMElement(value)) { - return getOuterHTML(value); + if ('outerHTML' in value) { + return value.outerHTML; + // This value does not have an outerHTML attribute, + // it could still be an XML element + } else { + // Attempt to serialize it + try { + if (document.xmlVersion) { + var xmlSerializer = new XMLSerializer(); + return xmlSerializer.serializeToString(value); + } else { + // Firefox 11- do not support outerHTML + // It does, however, support innerHTML + // Use the following to render the element + var ns = "http://www.w3.org/1999/xhtml"; + var container = document.createElementNS(ns, '_'); + + container.appendChild(value.cloneNode(false)); + html = container.innerHTML + .replace('><', '>' + value.innerHTML + '<'); + container.innerHTML = ''; + return html; + } + } catch (err) { + // This could be a non-native DOM implementation, + // continue with the normal flow: + // printing the element as if it is an object. + } + } } // Look up the keys of the object. @@ -4191,6 +4786,9 @@ function formatPrimitive(ctx, value) { return ctx.stylize(simple, 'string'); case 'number': + if (value === 0 && (1/value) === -Infinity) { + return ctx.stylize('-0', 'number'); + } return ctx.stylize('' + value, 'number'); case 'boolean': @@ -4330,7 +4928,8 @@ function objectToString(o) { } }); -require.register("chai/lib/chai/utils/objDisplay.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/objDisplay.js", function (exports, module) { /*! * Chai - flag utility * Copyright(c) 2012-2014 Jake Luer @@ -4341,7 +4940,8 @@ require.register("chai/lib/chai/utils/objDisplay.js", function(exports, require, * Module dependancies */ -var inspect = require('./inspect'); +var inspect = require('chai/lib/chai/utils/inspect.js'); +var config = require('chai/lib/chai/config.js'); /** * ### .objDisplay (object) @@ -4359,7 +4959,7 @@ module.exports = function (obj) { var str = inspect(obj) , type = Object.prototype.toString.call(obj); - if (str.length >= 40) { + if (config.truncateThreshold && str.length >= config.truncateThreshold) { if (type === '[object Function]') { return !obj.name || obj.name === '' ? '[Function]' @@ -4381,7 +4981,8 @@ module.exports = function (obj) { }; }); -require.register("chai/lib/chai/utils/overwriteMethod.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/overwriteMethod.js", function (exports, module) { /*! * Chai - overwriteMethod utility * Copyright(c) 2012-2014 Jake Luer @@ -4435,7 +5036,8 @@ module.exports = function (ctx, name, method) { }; }); -require.register("chai/lib/chai/utils/overwriteProperty.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/overwriteProperty.js", function (exports, module) { /*! * Chai - overwriteProperty utility * Copyright(c) 2012-2014 Jake Luer @@ -4492,7 +5094,8 @@ module.exports = function (ctx, name, getter) { }; }); -require.register("chai/lib/chai/utils/overwriteChainableMethod.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/overwriteChainableMethod.js", function (exports, module) { /*! * Chai - overwriteChainableMethod utility * Copyright(c) 2012-2014 Jake Luer @@ -4500,7 +5103,7 @@ require.register("chai/lib/chai/utils/overwriteChainableMethod.js", function(exp */ /** - * ### overwriteChainableMethod (ctx, name, fn) + * ### overwriteChainableMethod (ctx, name, method, chainingBehavior) * * Overwites an already existing chainable method * and provides access to the previous function or @@ -4548,7 +5151,8 @@ module.exports = function (ctx, name, method, chainingBehavior) { }; }); -require.register("chai/lib/chai/utils/test.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/test.js", function (exports, module) { /*! * Chai - test utility * Copyright(c) 2012-2014 Jake Luer @@ -4559,7 +5163,7 @@ require.register("chai/lib/chai/utils/test.js", function(exports, require, modul * Module dependancies */ -var flag = require('./flag'); +var flag = require('chai/lib/chai/utils/flag.js'); /** * # test(object, expression) @@ -4577,7 +5181,8 @@ module.exports = function (obj, args) { }; }); -require.register("chai/lib/chai/utils/transferFlags.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/transferFlags.js", function (exports, module) { /*! * Chai - transferFlags utility * Copyright(c) 2012-2014 Jake Luer @@ -4600,9 +5205,9 @@ require.register("chai/lib/chai/utils/transferFlags.js", function(exports, requi * utils.transferFlags(assertion, anotherAssertion, false); * * @param {Assertion} assertion the assertion to transfer the flags from - * @param {Object} object the object to transfer the flags too; usually a new assertion + * @param {Object} object the object to transfer the flags to; usually a new assertion * @param {Boolean} includeAll - * @name getAllFlags + * @name transferFlags * @api private */ @@ -4624,7 +5229,8 @@ module.exports = function (assertion, object, includeAll) { }; }); -require.register("chai/lib/chai/utils/type.js", function(exports, require, module){ + +require.register("chai/lib/chai/utils/type.js", function (exports, module) { /*! * Chai - type utility * Copyright(c) 2012-2014 Jake Luer @@ -4673,24 +5279,11 @@ module.exports = function (obj) { }); - - - -require.alias("chaijs-assertion-error/index.js", "chai/deps/assertion-error/index.js"); -require.alias("chaijs-assertion-error/index.js", "chai/deps/assertion-error/index.js"); -require.alias("chaijs-assertion-error/index.js", "assertion-error/index.js"); -require.alias("chaijs-assertion-error/index.js", "chaijs-assertion-error/index.js"); -require.alias("chaijs-deep-eql/lib/eql.js", "chai/deps/deep-eql/lib/eql.js"); -require.alias("chaijs-deep-eql/lib/eql.js", "chai/deps/deep-eql/index.js"); -require.alias("chaijs-deep-eql/lib/eql.js", "deep-eql/index.js"); -require.alias("chaijs-type-detect/lib/type.js", "chaijs-deep-eql/deps/type-detect/lib/type.js"); -require.alias("chaijs-type-detect/lib/type.js", "chaijs-deep-eql/deps/type-detect/index.js"); -require.alias("chaijs-type-detect/lib/type.js", "chaijs-type-detect/index.js"); -require.alias("chaijs-deep-eql/lib/eql.js", "chaijs-deep-eql/index.js"); -require.alias("chai/index.js", "chai/index.js");if (typeof exports == "object") { +if (typeof exports == "object") { module.exports = require("chai"); } else if (typeof define == "function" && define.amd) { - define([], function(){ return require("chai"); }); + define("chai", [], function(){ return require("chai"); }); } else { - this["chai"] = require("chai"); -}})(); \ No newline at end of file + (this || window)["chai"] = require("chai"); +} +})() diff --git a/bower_components/chai/component.json b/bower_components/chai/component.json index f0c1ddbe2f..ae2b6ac009 100644 --- a/bower_components/chai/component.json +++ b/bower_components/chai/component.json @@ -1,7 +1,7 @@ { "name": "chai" , "repo": "chaijs/chai" - , "version": "1.9.0" + , "version": "2.0.0" , "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic." , "license": "MIT" , "keywords": [ @@ -16,6 +16,7 @@ "index.js" , "lib/chai.js" , "lib/chai/assertion.js" + , "lib/chai/config.js" , "lib/chai/core/assertions.js" , "lib/chai/interface/assert.js" , "lib/chai/interface/expect.js" @@ -29,6 +30,8 @@ , "lib/chai/utils/getMessage.js" , "lib/chai/utils/getName.js" , "lib/chai/utils/getPathValue.js" + , "lib/chai/utils/getPathInfo.js" + , "lib/chai/utils/hasProperty.js" , "lib/chai/utils/getProperties.js" , "lib/chai/utils/index.js" , "lib/chai/utils/inspect.js" diff --git a/bower_components/chai/package.json b/bower_components/chai/package.json index 27d6a1fea6..f8febf958c 100644 --- a/bower_components/chai/package.json +++ b/bower_components/chai/package.json @@ -2,7 +2,13 @@ "author": "Jake Luer ", "name": "chai", "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.", - "keywords": [ "test", "assertion", "assert", "testing", "chai" ], + "keywords": [ + "test", + "assertion", + "assert", + "testing", + "chai" + ], "homepage": "http://chaijs.com", "license": "MIT", "contributors": [ @@ -11,7 +17,7 @@ "Veselin Todorov ", "John Firebaugh " ], - "version": "1.9.0", + "version": "2.0.0", "repository": { "type": "git", "url": "https://github.com/chaijs/chai" @@ -27,16 +33,16 @@ "node": ">= 0.4.0" }, "dependencies": { - "assertion-error": "1.0.0" - , "deep-eql": "0.1.3" + "assertion-error": "1.0.0", + "deep-eql": "0.1.3" }, "devDependencies": { - "component": "*" - , "karma": "0.11.12" - , "karma-mocha": "*" - , "karma-sauce-launcher": "0.2.0" - , "karma-phantomjs-launcher": "0.1.1" - , "mocha": "1.8.2" - , "istanbul": "~0.1.44" + "component": "*", + "karma": "0.12.x", + "karma-mocha": "*", + "karma-sauce-launcher": "0.2.x", + "karma-phantomjs-launcher": "0.1.1", + "mocha": "1.21.x", + "istanbul": "0.2.x" } } diff --git a/bower_components/mocha/.bower.json b/bower_components/mocha/.bower.json index 92ea3affb9..50df0b6b12 100644 --- a/bower_components/mocha/.bower.json +++ b/bower_components/mocha/.bower.json @@ -1,7 +1,26 @@ { "name": "mocha", - "version": "1.17.1", - "main": "mocha.js", + "version": "2.2.5", + "homepage": "http://mocha.github.io/mocha", + "description": "simple, flexible, fun test framework", + "authors": [ + "TJ Holowaychuk ", + "Joshua Appelman ", + "Oleg Gaidarenko ", + "Christoffer Hallas ", + "Christopher Hiller ", + "Travis Jeffery ", + "Johnathan Ong ", + "Guillermo Rauch " + ], + "repository": { + "type": "git", + "url": "git://github.com/mochajs/mocha.git" + }, + "main": [ + "mocha.js", + "mocha.css" + ], "ignore": [ "bin", "editors", @@ -17,14 +36,21 @@ "Makefile", "package.json" ], - "homepage": "https://github.com/visionmedia/mocha", - "_release": "1.17.1", + "keywords": [ + "mocha", + "test", + "bdd", + "tdd", + "tap" + ], + "license": "MIT", + "_release": "2.2.5", "_resolution": { "type": "version", - "tag": "1.17.1", - "commit": "7fc565ee3e225cb7a66bf39ae9c2c05b346675c1" + "tag": "2.2.5", + "commit": "cb841cac0e14a65317fec5db6ea9e835e6c9b771" }, - "_source": "git://github.com/visionmedia/mocha.git", - "_target": "1.17.1", + "_source": "git://github.com/mochajs/mocha.git", + "_target": "2.2.5", "_originalSource": "mocha" } \ No newline at end of file diff --git a/bower_components/mocha/.editorconfig b/bower_components/mocha/.editorconfig new file mode 100644 index 0000000000..e3a4859eeb --- /dev/null +++ b/bower_components/mocha/.editorconfig @@ -0,0 +1,18 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +root = true + +[*] +end_of_line = lf +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[Makefile] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false diff --git a/bower_components/mocha/.mailmap b/bower_components/mocha/.mailmap new file mode 100644 index 0000000000..704013125b --- /dev/null +++ b/bower_components/mocha/.mailmap @@ -0,0 +1 @@ +TJ Holowaychuk \ No newline at end of file diff --git a/bower_components/mocha/CONTRIBUTING.md b/bower_components/mocha/CONTRIBUTING.md new file mode 100644 index 0000000000..6d172f0800 --- /dev/null +++ b/bower_components/mocha/CONTRIBUTING.md @@ -0,0 +1,49 @@ +# Contributing to Mocha + +Hi! We could use your help. Let us help you help us. Or something. + +## General + +1. If you are looking for a place to begin, **please send PRs for bugfixes instead of new features**, and/or **look for issues labeled `PR PLEASE`.** + +2. **Help with documentation and the wiki is always appreciated**. + +3. Please **be courteous and constructive** when commenting on issues, commits, and pull requests. + +## Bug Reports & Issues + +1. When reporting a bug, please **provide steps to reproduce**. If possible, show code. + +2. Please **show all code in JavaScript**. We don't all read ``. If you do not, you will be asked to. + +3. Because Mocha works with many third-party libraries and tools, **ensure the bug you are reporting is actually within Mocha**. + +4. If you report a bug, and it is inactive for a significant amount of time, it may be closed. **Please respond promptly to requests for more information**. + +## Pull Requests + +1. Before sending a large PR, it's recommended to **create an issue to propose the change**. Nobody wants to write a book of code and throw it away. + +2. Because Mocha should be kept as maintainable as possible, its codebase must be kept slim. Historically, *most PRs for new features are not merged*. New features inevitably increase the size of the codebase, and thus reduce maintainability. Only features *deemed essential* are likely to be merged--this is at the discretion of the maintainer(s). If your PR for a feature is not merged, this doesn't necessarily mean your PR was a bad idea, wouldn't be used, or otherwise sucks. It just means **only essential PRs for new features are likely to be merged**. + +3. Due to the above, before creating a PR for a new feature, **create an issue to propose the feature.** + +4. Please **respect existing coding conventions**, whatever those may be. + +5. If your PR has been waiting in limbo for some time, it's very helpful to **rebase against master**, which will make it easier to merge. + +6. Please **add tests for new code**. + +7. **Always run `npm test` before sending a PR.** If you break the tests, your PR will not be accepted until they are fixed. + +## Source Control + +1. Please **squash your commits** when sending a pull request. If you are unfamiliar with this process, see [this guide](https://help.github.com/articles/about-git-rebase/). If you have already pushed your changesets and are squashing thereafter, this may necessitate the use of a "force push". Please [read the docs](http://git-scm.com/docs/git-push) before you attempt this. + +2. Please **follow the commit message conventions [outlined here](https://medium.com/code-adventures/git-conventions-a940ee20862d).** + +## TL;DR + +**Be kind, be diligent, look before you leap into a PR, and follow common community conventions**. + +*- The Mocha Team* diff --git a/bower_components/mocha/History.md b/bower_components/mocha/History.md index 1347a2ac7d..9f7db2314e 100644 --- a/bower_components/mocha/History.md +++ b/bower_components/mocha/History.md @@ -1,3 +1,240 @@ + +2.2.5 / 2015-05-14 +================== + + * Merge pull request #1699 from nylen/upgrade/jsdiff + * Upgrade jsdiff to v1.4.0 + * Merge pull request #1648 from nylen/fix/diff-colors + * Merge pull request #1686 from danielstjules/1327-regression + * Sanity check: update fixtures/regression/issue-1327.js to be closer to orig test + * Fix diff colors + * Merge pull request #1675 from danielstjules/integration-tests + * Merge pull request #1682 from kemitchell/spdx-license + * use a valid SPDX license identifier + * Add integration tests + * Merge pull request #1655 from a8m/fix-issue-1241 + * Merge pull request #1661 from a8m/fix-issue-1660 + * fix(utils/stringify): fix issue #1660 + * fix(reporter/base): issue #1241 + +2.2.4 / 2015-04-08 +================== + + * Load mocha.opts in _mocha for now (close #1645) + +2.2.3 / 2015-04-07 +================== + + * fix(reporter/base): string diff - issue #1241 + * fix(reporter/base): string diff - issue #1241 + * fix(reporter/base): don't show diffs for errors without expectation + * fix(reporter/base): don't assume error message is first line of stack + * improve: dry up reporter/base test + * fix(reporter/base): explicitly ignore showDiff #1614 + * Add iojs to travis build + * Pass `--allow-natives-syntax` flag to node. + * Support --harmony_classes flag for io.js + * Fix 1556: Update utils.clean to handle newlines in func declarations + * Fix 1606: fix err handling in IE <= 8 and non-ES5 browsers + * Fix 1585: make _mocha executable again + * chore(package.json): add a8m as a contributor + * Fixed broken link on html-cov reporter + * support --es_staging flag + * fix issue where menu overlaps content. + * update contributors in package.json + * Remove trailing whitespace from reporter output + * Remove contributors list from readme + * log third-party reporter errors + * [Fix] Exclude not own properties when looping on options + * fix: support node args in mocha.opts (close #1573) + * fix(reporter/base): string diff - issue #1241 + +2.2.1 / 2015-03-09 +================== + + * Fix passing of args intended for node/iojs. + +2.2.0 / 2015-03-06 +================== + + * Update mocha.js + * Add --fgrep. Use grep for RegExp, fgrep for str + * Ignore async global errors after spec resolution + * Fixing errors that prevent mocha.js from loading in the browser - fixes #1558 + * fix(utils): issue #1558 + make + * add ability to delay root suite; closes #362, closes #1124 + * fix insanity in http tests + * update travis: add node 0.12, add gitter, remove slack + * building + * resolve #1548: ensure the environment's "node" executable is used + * reporters/base: use supports-color to detect colorable term + * travis: use docker containers + * small fix: commander option for --expose-gc + * Ignore asynchronous errors after global failure + * Improve error output when a test fails with a non-error + * updated travis badge, uses svg instead of img + * Allow skip from test context for #332 + * [JSHINT] Unnecessary semicolon fixed in bin/_mocha + * Added a reminder about the done() callback to test timeout error messages + * fixes #1496, in Mocha.run(fn), check if fn exists before executing it, added tests too + * Add Harmony Proxy flag for iojs + * test(utils|ms|*): test existing units + * add support for some iojs flags + * fix(utils.stringify): issue #1229, diff viewer + * Remove slack link + * Prevent multiple 'grep=' querystring params in html reporter + * Use grep as regexp (close #1381) + * utils.stringify should handle objects without an Object prototype + * in runnable test, comparing to undefined error's message rather than a literal + * Fix test running output truncation on async STDIO + * ammended for deprecated customFds option in child_process + +2.1.0 / 2014-12-23 +================== + + * showDiff: don’t stringify strings + * Clean up unused module dependencies. + * Filter zero-length strings from mocha.opts + * only write to stdout in reporters + * Revert "only write to stdout in reporters" + * Print colored output only to a tty + * update summary in README.md + * rename Readme.md/History.md to README.md/HISTORY.md because neurotic + * add .mailmap to fix "git shortlog" or "git summary" output + * fixes #1461: nyan-reporter now respects Base.useColors, fixed bug where Base.color would not return a string when str wasn't a string. + * Use existing test URL builder in failed replay links + * modify .travis.yml: use travis_retry; closes #1449 + * fix -t 0 behavior; closes #1446 + * fix tests (whoops) + * improve diff behavior + * Preserve pathname when linking to individual tests + * Fix test + * Tiny typo in comments fixed + * after hooks now being called on failed tests when using bail, fixes #1093 + * fix throwing undefined/null now makes tests fail, fixes #1395 + * compiler extensions are added as watched extensions, removed non-standard extensions from watch regex, resolves #1221 + * prefix/namespace for suite titles in markdown reporter, fixes #554 + * fix more bad markdown in CONTRIBUTING.md + * fix bad markdown in CONTRIBUTING.md + * add setImmediate/clearImmediate to globals; closes #1435 + * Fix buffer diffs (closes #1132, closes #1433) + * add a CONTRIBUTING.md. closes #882 + * fix intermittent build failures (maybe). closes #1407 + * add Slack notification to .travis.yml + * Fix slack link + * Add slack room to readme + * Update maintainers + * update maintainers and contributors + * resolves #1393: kill children with more effort on SIGINT + * xunit reporter support for optionally writing to a file + * if a reporter has a .done method, call it before exiting + * add support for reporter options + * only write to stdout in reporters + +2.0.0 / 2014-10-21 +================== + + * remove: support for node 0.6.x, 0.4.x + * fix: landing reporter with non ansi characters (#211) + * fix: html reporter - preserve query params when navigating to suites/tests (#1358) + * fix: json stream reporter add error message to failed test + * fix: fixes for visionmedia -> mochajs + * fix: use stdio, fixes node deprecation warnings (#1391) + +1.21.5 / 2014-10-11 +================== + + * fix: build for NodeJS v0.6.x + * fix: do not attempt to highlight syntax when non-HTML reporter is used + * update: escape-string-regexp to 1.0.2. + * fix: botched indentation in canonicalize() + * fix: .gitignore: ignore .patch and .diff files + * fix: changed 'Catched' to 'Caught' in uncaught exception error handler messages + * add: `pending` field for json reporter + * fix: Runner.prototype.uncaught: don't double-end runnables that already have a state. + * fix: --recursive, broken by f0facd2e + * update: replaces escapeRegexp with the escape-string-regexp package. + * update: commander to 2.3.0. + * update: diff to 1.0.8. + * fix: ability to disable syntax highlighting (#1329) + * fix: added empty object to errorJSON() call to catch when no error is present + * fix: never time out after calling enableTimeouts(false) + * fix: timeout(0) will work at suite level (#1300) + * Fix for --watch+only() issue (#888 ) + * fix: respect err.showDiff, add Base reporter test (#810) + +1.22.1-3 / 2014-07-27 +================== + + * fix: disabling timeouts with this.timeout(0) (#1301) + +1.22.1-3 / 2014-07-27 +================== + + * fix: local uis and reporters (#1288) + * fix: building 1.21.0's changes in the browser (#1284) + +1.21.0 / 2014-07-23 +================== + + * add: --no-timeouts option (#1262, #1268) + * add: --*- deprecation node flags (#1217) + * add: --watch-extensions argument (#1247) + * change: spec reporter is default (#1228) + * fix: diff output showing incorrect +/- (#1182) + * fix: diffs of circular structures (#1179) + * fix: re-render the progress bar when progress has changed only (#1151) + * fix support for environments with global and window (#1159) + * fix: reverting to previously defined onerror handler (#1178) + * fix: stringify non error objects passed to done() (#1270) + * fix: using local ui, reporters (#1267) + * fix: cleaning es6 arrows (#1176) + * fix: don't include attrs in failure tag for xunit (#1244) + * fix: fail tests that return a promise if promise is rejected w/o a reason (#1224) + * fix: showing failed tests in doc reporter (#1117) + * fix: dot reporter dots being off (#1204) + * fix: catch empty throws (#1219) + * fix: honoring timeout for sync operations (#1242) + * update: growl to 1.8.0 + +1.20.1 / 2014-06-03 +================== + + * update: should dev dependency to ~4.0.0 (#1231) + +1.20.0 / 2014-05-28 +================== + + * add: filenames to suite objects (#1222) + +1.19.0 / 2014-05-17 +================== + + * add: browser script option to package.json + * add: export file in Mocha.Test objects (#1174) + * add: add docs for wrapped node flags + * fix: mocha.run() to return error status in browser (#1216) + * fix: clean() to show failure details (#1205) + * fix: regex that generates html for new keyword (#1201) + * fix: sibling suites have inherited but separate contexts (#1164) + + +1.18.2 / 2014-03-18 +================== + + * fix: html runner was prevented from using #mocha as the default root el (#1162) + +1.18.1 / 2014-03-18 +================== + + * fix: named before/after hooks in bdd, tdd, qunit interfaces (#1161) + +1.18.0 / 2014-03-13 +================== + + * add: promise support (#329) + * add: named before/after hooks (#966) + 1.17.1 / 2014-01-22 ================== diff --git a/bower_components/mocha/LICENSE b/bower_components/mocha/LICENSE index 00e9a0c3cc..ca47f261b3 100644 --- a/bower_components/mocha/LICENSE +++ b/bower_components/mocha/LICENSE @@ -1,6 +1,6 @@ (The MIT License) -Copyright (c) 2011-2013 TJ Holowaychuk +Copyright (c) 2011-2015 TJ Holowaychuk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/bower_components/mocha/Readme.md b/bower_components/mocha/Readme.md index 9340cacfda..44692d3514 100644 --- a/bower_components/mocha/Readme.md +++ b/bower_components/mocha/Readme.md @@ -1,172 +1,11 @@ - [![Build Status](https://secure.travis-ci.org/visionmedia/mocha.png)](http://travis-ci.org/visionmedia/mocha) +[![Build Status](https://api.travis-ci.org/mochajs/mocha.svg?branch=master)](http://travis-ci.org/mochajs/mocha) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mochajs/mocha?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - [![Mocha test framework](http://f.cl.ly/items/3l1k0n2A1U3M1I1L210p/Screen%20Shot%202012-02-24%20at%202.21.43%20PM.png)](http://visionmedia.github.io/mocha) + [![Mocha test framework](http://f.cl.ly/items/3l1k0n2A1U3M1I1L210p/Screen%20Shot%202012-02-24%20at%202.21.43%20PM.png)](http://mochajs.org) - Mocha is a simple, flexible, fun JavaScript test framework for node.js and the browser. For more information view the [documentation](http://visionmedia.github.io/mocha). - -## Contributors - -``` - - project : mocha - repo age : 2 years, 4 months ago - commits : 1314 - active : 372 days - files : 141 - authors : - 582 TJ Holowaychuk 44.3% - 389 Tj Holowaychuk 29.6% - 46 Travis Jeffery 3.5% - 31 Guillermo Rauch 2.4% - 13 Attila Domokos 1.0% - 10 John Firebaugh 0.8% - 8 Jo Liss 0.6% - 7 Nathan Rajlich 0.5% - 6 Mike Pennisi 0.5% - 6 James Carr 0.5% - 6 Brendan Nee 0.5% - 5 Aaron Heckmann 0.4% - 5 Ryunosuke SATO 0.4% - 4 hokaccha 0.3% - 4 Joshua Krall 0.3% - 4 Xavier Antoviaque 0.3% - 3 Jesse Dailey 0.2% - 3 Forbes Lindesay 0.2% - 3 Sindre Sorhus 0.2% - 3 Cory Thomas 0.2% - 3 Fredrik Enestad 0.2% - 3 Ben Lindsey 0.2% - 3 Tyson Tate 0.2% - 3 Mathieu Desvé 0.2% - 3 Valentin Agachi 0.2% - 3 Wil Moore III 0.2% - 3 Merrick Christensen 0.2% - 3 eiji.ienaga 0.2% - 3 fool2fish 0.2% - 3 Nathan Bowser 0.2% - 3 Paul Miller 0.2% - 2 Juzer Ali 0.2% - 2 Pete Hawkins 0.2% - 2 Jonas Westerlund 0.2% - 2 Arian Stolwijk 0.2% - 2 Quang Van 0.2% - 2 Glen Mailer 0.2% - 2 Justin DuJardin 0.2% - 2 FARKAS Máté 0.2% - 2 Raynos 0.2% - 2 Michael Riley 0.2% - 2 Michael Schoonmaker 0.2% - 2 Domenic Denicola 0.2% - 2 Simon Gaeremynck 0.2% - 2 Konstantin Käfer 0.2% - 2 domenic 0.2% - 2 Paul Armstrong 0.2% - 2 fcrisci 0.2% - 2 Alexander Early 0.2% - 2 Shawn Krisman 0.2% - 2 Brian Beck 0.2% - 2 Nathan Alderson 0.2% - 2 David Henderson 0.2% - 2 Timo Tijhof 0.2% - 2 Ian Storm Taylor 0.2% - 2 travis jeffery 0.2% - 1 Matt Smith 0.1% - 1 Matthew Shanley 0.1% - 1 Nathan Black 0.1% - 1 Phil Sung 0.1% - 1 R56 0.1% - 1 Refael Ackermann 0.1% - 1 Richard Dingwall 0.1% - 1 Romain Prieto 0.1% - 1 Roman Neuhauser 0.1% - 1 Roman Shtylman 0.1% - 1 Russ Bradberry 0.1% - 1 Russell Munson 0.1% - 1 Rustem Mustafin 0.1% - 1 Salehen Shovon Rahman 0.1% - 1 Sasha Koss 0.1% - 1 Seiya Konno 0.1% - 1 Simon Goumaz 0.1% - 1 Standa Opichal 0.1% - 1 Stephen Mathieson 0.1% - 1 Steve Mason 0.1% - 1 Tapiwa Kelvin 0.1% - 1 Teddy Zeenny 0.1% - 1 Tim Ehat 0.1% - 1 Vadim Nikitin 0.1% - 1 Victor Costan 0.1% - 1 Will Langstroth 0.1% - 1 Yanis Wang 0.1% - 1 Yuest Wang 0.1% - 1 abrkn 0.1% - 1 airportyh 0.1% - 1 badunk 0.1% - 1 fengmk2 0.1% - 1 grasGendarme 0.1% - 1 lodr 0.1% - 1 tgautier@yahoo.com 0.1% - 1 traleig1 0.1% - 1 vlad 0.1% - 1 yuitest 0.1% - 1 Adam Crabtree 0.1% - 1 Andreas Brekken 0.1% - 1 Andreas Lind Petersen 0.1% - 1 Andrew Nesbitt 0.1% - 1 Andrey Popp 0.1% - 1 Arnaud Brousseau 0.1% - 1 Atsuya Takagi 0.1% - 1 Austin Birch 0.1% - 1 Bjørge Næss 0.1% - 1 Brian Lalor 0.1% - 1 Brian M. Carlson 0.1% - 1 Brian Moore 0.1% - 1 Bryan Donovan 0.1% - 1 Casey Foster 0.1% - 1 ChrisWren 0.1% - 1 Corey Butler 0.1% - 1 Daniel Stockman 0.1% - 1 Dave McKenna 0.1% - 1 Di Wu 0.1% - 1 Dmitry Shirokov 0.1% - 1 Fedor Indutny 0.1% - 1 Florian Margaine 0.1% - 1 Frederico Silva 0.1% - 1 Fredrik Lindin 0.1% - 1 Gareth Murphy 0.1% - 1 Gavin Mogan 0.1% - 1 Glen Huang 0.1% - 1 Greg Perkins 0.1% - 1 Harry Brundage 0.1% - 1 Herman Junge 0.1% - 1 Ian Young 0.1% - 1 Ivan 0.1% - 1 JP Bochi 0.1% - 1 Jaakko Salonen 0.1% - 1 Jakub Nešetřil 0.1% - 1 James Bowes 0.1% - 1 James Lal 0.1% - 1 Jason Barry 0.1% - 1 Javier Aranda 0.1% - 1 Jeff Kunkle 0.1% - 1 Jeremy Martin 0.1% - 1 Jimmy Cuadra 0.1% - 1 Jonathan Creamer 0.1% - 1 Jussi Virtanen 0.1% - 1 Katie Gengler 0.1% - 1 Kazuhito Hokamura 0.1% - 1 Kirill Korolyov 0.1% - 1 Koen Punt 0.1% - 1 Laszlo Bacsi 0.1% - 1 Liam Newman 0.1% - 1 László Bácsi 0.1% - 1 Maciej Małecki 0.1% - 1 Mal Graty 0.1% - 1 Marc Kuo 0.1% - 1 Matt Robenolt 0.1% -``` + Mocha is a simple, flexible, fun JavaScript test framework for node.js and the browser. For more information view the [documentation](http://mochajs.org). ## Links - [Google Group](http://groups.google.com/group/mochajs) - - [Wiki](https://github.com/visionmedia/mocha/wiki) - - Mocha [Extensions and reporters](https://github.com/visionmedia/mocha/wiki) + - [Wiki](https://github.com/mochajs/mocha/wiki) + - Mocha [Extensions and reporters](https://github.com/mochajs/mocha/wiki) diff --git a/bower_components/mocha/bower.json b/bower_components/mocha/bower.json index 84becdabb9..f03b076d09 100644 --- a/bower_components/mocha/bower.json +++ b/bower_components/mocha/bower.json @@ -1,7 +1,26 @@ { "name": "mocha", - "version": "1.17.1", - "main": "mocha.js", + "version": "2.2.5", + "homepage": "http://mocha.github.io/mocha", + "description": "simple, flexible, fun test framework", + "authors": [ + "TJ Holowaychuk ", + "Joshua Appelman ", + "Oleg Gaidarenko ", + "Christoffer Hallas ", + "Christopher Hiller ", + "Travis Jeffery ", + "Johnathan Ong ", + "Guillermo Rauch " + ], + "repository": { + "type": "git", + "url": "git://github.com/mochajs/mocha.git" + }, + "main": [ + "mocha.js", + "mocha.css" + ], "ignore": [ "bin", "editors", @@ -16,5 +35,13 @@ "index.js", "Makefile", "package.json" - ] -} + ], + "keywords": [ + "mocha", + "test", + "bdd", + "tdd", + "tap" + ], + "license": "MIT" +} \ No newline at end of file diff --git a/bower_components/mocha/media/logo.svg b/bower_components/mocha/media/logo.svg index 88d3713080..1bed0ce1d1 100644 --- a/bower_components/mocha/media/logo.svg +++ b/bower_components/mocha/media/logo.svg @@ -1,8 +1,7 @@ - + mocha diff --git a/bower_components/mocha/mocha.js b/bower_components/mocha/mocha.js index 3dcdae6c1b..5ff1385758 100644 --- a/bower_components/mocha/mocha.js +++ b/bower_components/mocha/mocha.js @@ -48,7 +48,6 @@ require.relative = function (parent) { require.register("browser/debug.js", function(module, exports, require){ - module.exports = function(type){ return function(){ } @@ -224,7 +223,22 @@ var JsDiff = (function() { var LineDiff = new Diff(); LineDiff.tokenize = function(value) { - return value.split(/^/m); + var retLines = [], + lines = value.split(/^/m); + + for(var i = 0; i < lines.length; i++) { + var line = lines[i], + lastLine = lines[i - 1]; + + // Merge lines that may contain windows new lines + if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') { + retLines[retLines.length - 1] += '\n'; + } else if (line) { + retLines.push(line); + } + } + + return retLines; }; return { @@ -414,8 +428,22 @@ if (typeof module !== 'undefined') { }); // module: browser/diff.js -require.register("browser/events.js", function(module, exports, require){ +require.register("browser/escape-string-regexp.js", function(module, exports, require){ +'use strict'; + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; + +module.exports = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + return str.replace(matchOperatorsRe, '\\$&'); +}; + +}); // module: browser/escape-string-regexp.js + +require.register("browser/events.js", function(module, exports, require){ /** * Module exports. */ @@ -593,12 +621,17 @@ EventEmitter.prototype.emit = function (name) { return true; }; + }); // module: browser/events.js require.register("browser/fs.js", function(module, exports, require){ }); // module: browser/fs.js +require.register("browser/glob.js", function(module, exports, require){ + +}); // module: browser/glob.js + require.register("browser/path.js", function(module, exports, require){ }); // module: browser/path.js @@ -700,28 +733,28 @@ Progress.prototype.draw = function(ctx){ , y = half , rad = half - 1 , fontSize = this._fontSize; - + ctx.font = fontSize + 'px ' + this._font; - + var angle = Math.PI * 2 * (percent / 100); ctx.clearRect(0, 0, size, size); - + // outer circle ctx.strokeStyle = '#9f9f9f'; ctx.beginPath(); ctx.arc(x, y, rad, 0, angle, false); ctx.stroke(); - + // inner circle ctx.strokeStyle = '#eee'; ctx.beginPath(); ctx.arc(x, y, rad - 1, 0, angle, true); ctx.stroke(); - + // text var text = this._text || (percent | 0) + '%' , w = ctx.measureText(text).width; - + ctx.fillText( text , x - w / 2 + 1 @@ -733,7 +766,6 @@ Progress.prototype.draw = function(ctx){ }); // module: browser/progress.js require.register("browser/tty.js", function(module, exports, require){ - exports.isatty = function(){ return true; }; @@ -750,7 +782,6 @@ exports.getWindowSize = function(){ }); // module: browser/tty.js require.register("context.js", function(module, exports, require){ - /** * Expose `Context`. */ @@ -788,10 +819,25 @@ Context.prototype.runnable = function(runnable){ */ Context.prototype.timeout = function(ms){ + if (arguments.length === 0) return this.runnable().timeout(); this.runnable().timeout(ms); return this; }; +/** + * Set test timeout `enabled`. + * + * @param {Boolean} enabled + * @return {Context} self + * @api private + */ + +Context.prototype.enableTimeouts = function (enabled) { + this.runnable().enableTimeouts(enabled); + return this; +}; + + /** * Set test slowness threshold `ms`. * @@ -805,6 +851,18 @@ Context.prototype.slow = function(ms){ return this; }; +/** + * Mark a test as skipped. + * + * @return {Context} self + * @api private + */ + +Context.prototype.skip = function(){ + this.runnable().skip(); + return this; +}; + /** * Inspect the context void of `._runnable`. * @@ -823,7 +881,6 @@ Context.prototype.inspect = function(){ }); // module: context.js require.register("hook.js", function(module, exports, require){ - /** * Module dependencies. */ @@ -880,14 +937,14 @@ Hook.prototype.error = function(err){ }); // module: hook.js require.register("interfaces/bdd.js", function(module, exports, require){ - /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') - , utils = require('../utils'); + , utils = require('../utils') + , escapeRe = require('browser/escape-string-regexp'); /** * BDD-style interface: @@ -911,38 +968,13 @@ module.exports = function(suite){ suite.on('pre-require', function(context, file, mocha){ - /** - * Execute before running tests. - */ - - context.before = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after running tests. - */ - - context.after = function(fn){ - suites[0].afterAll(fn); - }; - - /** - * Execute before each test case. - */ - - context.beforeEach = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.afterEach = function(fn){ - suites[0].afterEach(fn); - }; + var common = require('./common')(suites, context); + context.before = common.before; + context.after = common.after; + context.beforeEach = common.beforeEach; + context.afterEach = common.afterEach; + context.run = mocha.options.delay && common.runWithSuite(suite); /** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites @@ -951,6 +983,7 @@ module.exports = function(suite){ context.describe = context.context = function(title, fn){ var suite = Suite.create(suites[0], title); + suite.file = file; suites.unshift(suite); fn.call(suite); suites.shift(); @@ -989,8 +1022,9 @@ module.exports = function(suite){ context.it = context.specify = function(title, fn){ var suite = suites[0]; - if (suite.pending) var fn = null; + if (suite.pending) fn = null; var test = new Test(title, fn); + test.file = file; suite.addTest(test); return test; }; @@ -1001,7 +1035,7 @@ module.exports = function(suite){ context.it.only = function(title, fn){ var test = context.it(title, fn); - var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; + var reString = '^' + escapeRe(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); return test; }; @@ -1015,13 +1049,75 @@ module.exports = function(suite){ context.it.skip = function(title){ context.it(title); }; + }); }; }); // module: interfaces/bdd.js -require.register("interfaces/exports.js", function(module, exports, require){ +require.register("interfaces/common.js", function(module, exports, require){ +/** + * Functions common to more than one interface + * @module lib/interfaces/common + */ + +'use strict'; + +module.exports = function (suites, context) { + + return { + /** + * This is only present if flag --delay is passed into Mocha. It triggers + * root suite execution. Returns a function which runs the root suite. + */ + runWithSuite: function runWithSuite(suite) { + return function run() { + suite.run(); + }; + }, + + /** + * Execute before running tests. + */ + before: function (name, fn) { + suites[0].beforeAll(name, fn); + }, + + /** + * Execute after running tests. + */ + after: function (name, fn) { + suites[0].afterAll(name, fn); + }, + + /** + * Execute before each test case. + */ + beforeEach: function (name, fn) { + suites[0].beforeEach(name, fn); + }, + + /** + * Execute after each test case. + */ + afterEach: function (name, fn) { + suites[0].afterEach(name, fn); + }, + + test: { + /** + * Pending test case. + */ + skip: function (title) { + context.test(title); + } + } + } +}; + +}); // module: interfaces/common.js +require.register("interfaces/exports.js", function(module, exports, require){ /** * Module dependencies. */ @@ -1051,7 +1147,7 @@ module.exports = function(suite){ suite.on('require', visit); - function visit(obj) { + function visit(obj, file) { var suite; for (var key in obj) { if ('function' == typeof obj[key]) { @@ -1070,10 +1166,12 @@ module.exports = function(suite){ suites[0].afterEach(fn); break; default: - suites[0].addTest(new Test(key, fn)); + var test = new Test(key, fn); + test.file = file; + suites[0].addTest(test); } } else { - var suite = Suite.create(suites[0], key); + suite = Suite.create(suites[0], key); suites.unshift(suite); visit(obj[key]); suites.shift(); @@ -1085,7 +1183,6 @@ module.exports = function(suite){ }); // module: interfaces/exports.js require.register("interfaces/index.js", function(module, exports, require){ - exports.bdd = require('./bdd'); exports.tdd = require('./tdd'); exports.qunit = require('./qunit'); @@ -1094,13 +1191,13 @@ exports.exports = require('./exports'); }); // module: interfaces/index.js require.register("interfaces/qunit.js", function(module, exports, require){ - /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') + , escapeRe = require('browser/escape-string-regexp') , utils = require('../utils'); /** @@ -1133,38 +1230,13 @@ module.exports = function(suite){ suite.on('pre-require', function(context, file, mocha){ - /** - * Execute before running tests. - */ - - context.before = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after running tests. - */ - - context.after = function(fn){ - suites[0].afterAll(fn); - }; - - /** - * Execute before each test case. - */ - - context.beforeEach = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.afterEach = function(fn){ - suites[0].afterEach(fn); - }; + var common = require('./common')(suites, context); + context.before = common.before; + context.after = common.after; + context.beforeEach = common.beforeEach; + context.afterEach = common.afterEach; + context.run = mocha.options.delay && common.runWithSuite(suite); /** * Describe a "suite" with the given `title`. */ @@ -1172,6 +1244,7 @@ module.exports = function(suite){ context.suite = function(title){ if (suites.length > 1) suites.shift(); var suite = Suite.create(suites[0], title); + suite.file = file; suites.unshift(suite); return suite; }; @@ -1193,6 +1266,7 @@ module.exports = function(suite){ context.test = function(title, fn){ var test = new Test(title, fn); + test.file = file; suites[0].addTest(test); return test; }; @@ -1203,31 +1277,26 @@ module.exports = function(suite){ context.test.only = function(title, fn){ var test = context.test(title, fn); - var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; + var reString = '^' + escapeRe(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); }; - /** - * Pending test case. - */ + context.test.skip = common.test.skip; - context.test.skip = function(title){ - context.test(title); - }; }); }; }); // module: interfaces/qunit.js require.register("interfaces/tdd.js", function(module, exports, require){ - /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') - , utils = require('../utils');; + , escapeRe = require('browser/escape-string-regexp') + , utils = require('../utils'); /** * TDD-style interface: @@ -1259,38 +1328,13 @@ module.exports = function(suite){ suite.on('pre-require', function(context, file, mocha){ - /** - * Execute before each test case. - */ - - context.setup = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.teardown = function(fn){ - suites[0].afterEach(fn); - }; - - /** - * Execute before the suite. - */ - - context.suiteSetup = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after the suite. - */ - - context.suiteTeardown = function(fn){ - suites[0].afterAll(fn); - }; + var common = require('./common')(suites, context); + context.setup = common.beforeEach; + context.teardown = common.afterEach; + context.suiteSetup = common.before; + context.suiteTeardown = common.after; + context.run = mocha.options.delay && common.runWithSuite(suite); /** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites @@ -1299,6 +1343,7 @@ module.exports = function(suite){ context.suite = function(title, fn){ var suite = Suite.create(suites[0], title); + suite.file = file; suites.unshift(suite); fn.call(suite); suites.shift(); @@ -1333,8 +1378,9 @@ module.exports = function(suite){ context.test = function(title, fn){ var suite = suites[0]; - if (suite.pending) var fn = null; + if (suite.pending) fn = null; var test = new Test(title, fn); + test.file = file; suite.addTest(test); return test; }; @@ -1345,17 +1391,11 @@ module.exports = function(suite){ context.test.only = function(title, fn){ var test = context.test(title, fn); - var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; + var reString = '^' + escapeRe(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); }; - /** - * Pending test case. - */ - - context.test.skip = function(title){ - context.test(title); - }; + context.test.skip = common.test.skip; }); }; @@ -1373,6 +1413,7 @@ require.register("mocha.js", function(module, exports, require){ */ var path = require('browser/path') + , escapeRe = require('browser/escape-string-regexp') , utils = require('./utils'); /** @@ -1381,6 +1422,16 @@ var path = require('browser/path') exports = module.exports = Mocha; +/** + * To require local UIs and reporters when running in node. + */ + +if (typeof process !== 'undefined' && typeof process.cwd === 'function') { + var join = path.join + , cwd = process.cwd(); + module.paths.push(cwd, join(cwd, 'node_modules')); +} + /** * Expose internals. */ @@ -1413,12 +1464,13 @@ function image(name) { * Options: * * - `ui` name "bdd", "tdd", "exports" etc - * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` + * - `reporter` reporter instance, defaults to `mocha.reporters.spec` * - `globals` array of accepted globals * - `timeout` timeout in milliseconds * - `bail` bail on the first test failure * - `slow` milliseconds to wait before considering a test slow * - `ignoreLeaks` ignore global leaks + * - `fullTrace` display the full stack-trace on failing * - `grep` string or regexp to filter tests with * * @param {Object} options @@ -1429,13 +1481,15 @@ function Mocha(options) { options = options || {}; this.files = []; this.options = options; - this.grep(options.grep); + if (options.grep) this.grep(new RegExp(options.grep)); + if (options.fgrep) this.grep(options.fgrep); this.suite = new exports.Suite('', new exports.Context); this.ui(options.ui); this.bail(options.bail); - this.reporter(options.reporter); + this.reporter(options.reporter, options.reporterOptions); if (null != options.timeout) this.timeout(options.timeout); - this.useColors(options.useColors) + this.useColors(options.useColors); + if (options.enableTimeouts !== null) this.enableTimeouts(options.enableTimeouts); if (options.slow) this.slow(options.slow); this.suite.on('pre-require', function (context) { @@ -1451,6 +1505,7 @@ function Mocha(options) { exports.suite = context.suite || context.describe; exports.teardown = context.teardown || context.afterEach; exports.test = context.test || context.it; + exports.run = context.run; }); } @@ -1480,20 +1535,24 @@ Mocha.prototype.addFile = function(file){ }; /** - * Set reporter to `reporter`, defaults to "dot". + * Set reporter to `reporter`, defaults to "spec". * * @param {String|Function} reporter name or constructor + * @param {Object} reporterOptions optional options * @api public */ - -Mocha.prototype.reporter = function(reporter){ +Mocha.prototype.reporter = function(reporter, reporterOptions){ if ('function' == typeof reporter) { this._reporter = reporter; } else { - reporter = reporter || 'dot'; + reporter = reporter || 'spec'; var _reporter; - try { _reporter = require('./reporters/' + reporter); } catch (err) {}; - if (!_reporter) try { _reporter = require(reporter); } catch (err) {}; + try { _reporter = require('./reporters/' + reporter); } catch (err) {} + if (!_reporter) try { _reporter = require(reporter); } catch (err) { + err.message.indexOf('Cannot find module') !== -1 + ? console.warn('"' + reporter + '" reporter not found') + : console.warn('"' + reporter + '" reporter blew up with error:\n' + err.stack); + } if (!_reporter && reporter === 'teamcity') console.warn('The Teamcity reporter was moved to a package named ' + 'mocha-teamcity-reporter ' + @@ -1501,6 +1560,7 @@ Mocha.prototype.reporter = function(reporter){ if (!_reporter) throw new Error('invalid reporter "' + reporter + '"'); this._reporter = _reporter; } + this.options.reporterOptions = reporterOptions; return this; }; @@ -1514,7 +1574,7 @@ Mocha.prototype.reporter = function(reporter){ Mocha.prototype.ui = function(name){ name = name || 'bdd'; this._ui = exports.interfaces[name]; - if (!this._ui) try { this._ui = require(name); } catch (err) {}; + if (!this._ui) try { this._ui = require(name); } catch (err) {} if (!this._ui) throw new Error('invalid interface "' + name + '"'); this._ui = this._ui(this.suite); return this; @@ -1573,7 +1633,7 @@ Mocha.prototype._growl = function(runner, reporter) { Mocha.prototype.grep = function(re){ this.options.grep = 'string' == typeof re - ? new RegExp(utils.escapeRegexp(re)) + ? new RegExp(escapeRe(re)) : re; return this; }; @@ -1615,6 +1675,18 @@ Mocha.prototype.checkLeaks = function(){ return this; }; +/** + * Display long stack-trace on failing + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.fullTrace = function() { + this.options.fullStackTrace = true; + return this; +}; + /** * Enable growl support. * @@ -1649,9 +1721,9 @@ Mocha.prototype.globals = function(globals){ */ Mocha.prototype.useColors = function(colors){ - this.options.useColors = arguments.length && colors != undefined - ? colors - : true; + if (colors !== undefined) { + this.options.useColors = colors; + } return this; }; @@ -1696,6 +1768,21 @@ Mocha.prototype.slow = function(slow){ return this; }; +/** + * Enable timeouts. + * + * @param {Boolean} enabled + * @return {Mocha} + * @api public + */ + +Mocha.prototype.enableTimeouts = function(enabled) { + this.suite.enableTimeouts(arguments.length && enabled !== undefined + ? enabled + : true); + return this +}; + /** * Makes all tests async (accepting a callback) * @@ -1708,6 +1795,26 @@ Mocha.prototype.asyncOnly = function(){ return this; }; +/** + * Disable syntax highlighting (in browser). + * @returns {Mocha} + * @api public + */ +Mocha.prototype.noHighlighting = function() { + this.options.noHighlighting = true; + return this; +}; + +/** + * Delay root suite execution. + * @returns {Mocha} + * @api public + */ +Mocha.prototype.delay = function delay() { + this.options.delay = true; + return this; +}; + /** * Run tests and invoke `fn()` when complete. * @@ -1715,21 +1822,31 @@ Mocha.prototype.asyncOnly = function(){ * @return {Runner} * @api public */ - Mocha.prototype.run = function(fn){ if (this.files.length) this.loadFiles(); var suite = this.suite; var options = this.options; - var runner = new exports.Runner(suite); - var reporter = new this._reporter(runner); + options.files = this.files; + var runner = new exports.Runner(suite, options.delay); + var reporter = new this._reporter(runner, options); runner.ignoreLeaks = false !== options.ignoreLeaks; + runner.fullStackTrace = options.fullStackTrace; runner.asyncOnly = options.asyncOnly; if (options.grep) runner.grep(options.grep, options.invert); if (options.globals) runner.globals(options.globals); if (options.growl) this._growl(runner, reporter); - exports.reporters.Base.useColors = options.useColors; + if (options.useColors !== undefined) { + exports.reporters.Base.useColors = options.useColors; + } exports.reporters.Base.inlineDiffs = options.useInlineDiffs; - return runner.run(fn); + + function done(failures) { + if (reporter.done) { + reporter.done(failures, fn); + } else fn && fn(failures); + } + + return runner.run(done); }; }); // module: mocha.js @@ -1761,7 +1878,7 @@ var y = d * 365.25; module.exports = function(val, options){ options = options || {}; if ('string' == typeof val) return parse(val); - return options.long ? longFormat(val) : shortFormat(val); + return options['long'] ? longFormat(val) : shortFormat(val); }; /** @@ -1847,8 +1964,27 @@ function plural(ms, n, name) { }); // module: ms.js -require.register("reporters/base.js", function(module, exports, require){ +require.register("pending.js", function(module, exports, require){ + +/** + * Expose `Pending`. + */ + +module.exports = Pending; + +/** + * Initialize a new `Pending` error with the given message. + * + * @param {String} message + */ + +function Pending(message) { + this.message = message; +} + +}); // module: pending.js +require.register("reporters/base.js", function(module, exports, require){ /** * Module dependencies. */ @@ -1856,7 +1992,8 @@ require.register("reporters/base.js", function(module, exports, require){ var tty = require('browser/tty') , diff = require('browser/diff') , ms = require('../ms') - , utils = require('../utils'); + , utils = require('../utils') + , supportsColor = process.env ? require('supports-color') : null; /** * Save timer references to avoid Sinon interfering (see GH-237). @@ -1881,10 +2018,12 @@ var isatty = tty.isatty(1) && tty.isatty(2); exports = module.exports = Base; /** - * Enable coloring by default. + * Enable coloring by default, except in the browser interface. */ -exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined); +exports.useColors = process.env + ? (supportsColor || (process.env.MOCHA_COLORS !== undefined)) + : false; /** * Inline diffs instead of +/- @@ -1948,7 +2087,7 @@ if ('win32' == process.platform) { */ var color = exports.color = function(type, str) { - if (!exports.useColors) return str; + if (!exports.useColors) return String(str); return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; }; @@ -2005,7 +2144,7 @@ exports.cursor = { */ exports.list = function(failures){ - console.error(); + console.log(); failures.forEach(function(test, i){ // format var fmt = color('error title', ' %s) %s:\n') @@ -2016,26 +2155,33 @@ exports.list = function(failures){ var err = test.err , message = err.message || '' , stack = err.stack || message - , index = stack.indexOf(message) + message.length - , msg = stack.slice(0, index) + , index = stack.indexOf(message) , actual = err.actual , expected = err.expected , escape = true; + if (index === -1) { + msg = message; + } else { + index += message.length; + msg = stack.slice(0, index); + // remove msg from stack + stack = stack.slice(index + 1); + } // uncaught if (err.uncaught) { msg = 'Uncaught ' + msg; } - // explicitly show diff - if (err.showDiff && sameType(actual, expected)) { - escape = false; - err.actual = actual = stringify(canonicalize(actual)); - err.expected = expected = stringify(canonicalize(expected)); - } + if (err.showDiff !== false && sameType(actual, expected) + && expected !== undefined) { + + if ('string' !== typeof actual) { + escape = false; + err.actual = actual = utils.stringify(actual); + err.expected = expected = utils.stringify(expected); + } - // actual / expected diff - if ('string' == typeof actual && 'string' == typeof expected) { fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n'); var match = message.match(/^([^:]+): expected/); msg = '\n ' + color('error message', match ? match[1] : msg); @@ -2047,11 +2193,10 @@ exports.list = function(failures){ } } - // indent stack trace without msg - stack = stack.slice(index ? index + 1 : index) - .replace(/^/gm, ' '); + // indent stack trace + stack = stack.replace(/^/gm, ' '); - console.error(fmt, (i + 1), test.fullTitle(), msg, stack); + console.log(fmt, (i + 1), test.fullTitle(), msg, stack); }); }; @@ -2156,11 +2301,10 @@ Base.prototype.epilogue = function(){ if (stats.failures) { fmt = color('fail', ' %d failing'); - console.error(fmt, - stats.failures); + console.log(fmt, stats.failures); Base.list(this.failures); - console.error(); + console.log(); } console.log(); @@ -2238,7 +2382,7 @@ function unifiedDiff(err, escape) { function notBlank(line) { return line != null; } - msg = diff.createPatch('string', err.actual, err.expected); + var msg = diff.createPatch('string', err.actual, err.expected); var lines = msg.split('\n').splice(4); return '\n ' + colorLines('diff added', '+ expected') + ' ' @@ -2293,53 +2437,6 @@ function colorLines(name, str) { }).join('\n'); } -/** - * Stringify `obj`. - * - * @param {Object} obj - * @return {String} - * @api private - */ - -function stringify(obj) { - if (obj instanceof RegExp) return obj.toString(); - return JSON.stringify(obj, null, 2); -} - -/** - * Return a new object that has the keys in sorted order. - * @param {Object} obj - * @return {Object} - * @api private - */ - - function canonicalize(obj, stack) { - stack = stack || []; - - if (utils.indexOf(stack, obj) !== -1) return obj; - - var canonicalizedObj; - - if ('[object Array]' == {}.toString.call(obj)) { - stack.push(obj); - canonicalizedObj = utils.map(obj, function(item) { - return canonicalize(item, stack); - }); - stack.pop(); - } else if (typeof obj === 'object' && obj !== null) { - stack.push(obj); - canonicalizedObj = {}; - utils.forEach(utils.keys(obj).sort(), function(key) { - canonicalizedObj[key] = canonicalize(obj[key], stack); - }); - stack.pop(); - } else { - canonicalizedObj = obj; - } - - return canonicalizedObj; - } - /** * Check that a / b have the same type. * @@ -2355,11 +2452,9 @@ function sameType(a, b) { return a == b; } - }); // module: reporters/base.js require.register("reporters/doc.js", function(module, exports, require){ - /** * Module dependencies. */ @@ -2414,12 +2509,18 @@ function Doc(runner) { var code = utils.escape(utils.clean(test.fn.toString())); console.log('%s
%s
', indent(), code); }); + + runner.on('fail', function(test, err){ + console.log('%s
%s
', indent(), utils.escape(test.title)); + var code = utils.escape(utils.clean(test.fn.toString())); + console.log('%s
%s
', indent(), code); + console.log('%s
%s
', indent(), utils.escape(err)); + }); } }); // module: reporters/doc.js require.register("reporters/dot.js", function(module, exports, require){ - /** * Module dependencies. */ @@ -2446,13 +2547,14 @@ function Dot(runner) { var self = this , stats = this.stats , width = Base.window.width * .75 | 0 - , n = 0; + , n = -1; runner.on('start', function(){ - process.stdout.write('\n '); + process.stdout.write('\n'); }); runner.on('pending', function(test){ + if (++n % width == 0) process.stdout.write('\n '); process.stdout.write(color('pending', Base.symbols.dot)); }); @@ -2485,10 +2587,10 @@ F.prototype = Base.prototype; Dot.prototype = new F; Dot.prototype.constructor = Dot; + }); // module: reporters/dot.js require.register("reporters/html-cov.js", function(module, exports, require){ - /** * Module dependencies. */ @@ -2539,10 +2641,10 @@ function coverageClass(n) { if (n >= 25) return 'low'; return 'terrible'; } + }); // module: reporters/html-cov.js require.register("reporters/html.js", function(module, exports, require){ - /** * Module dependencies. */ @@ -2586,7 +2688,7 @@ var statsTemplate = '