{"action":"created","comment":{"url":"https://api.github.com/repos/palantir/plottable/pulls/comments/37589772","id":37589772,"diff_hunk":"@@ -2,511 +2,486 @@\n \n describe(\"Plots\", () => {\n   describe(\"RectanglePlot\", () => {\n-    let SVG_WIDTH = 300;\n-    let SVG_HEIGHT = 300;\n-    let DATA = [\n-      { x: 0, y: 0, x2: 1, y2: 1 },\n-      { x: 1, y: 1, x2: 2, y2: 2 },\n-      { x: 2, y: 2, x2: 3, y2: 3 },\n-      { x: 3, y: 3, x2: 4, y2: 4 },\n-      { x: 4, y: 4, x2: 5, y2: 5 }\n-    ];\n-    let VERIFY_CELLS = (cells: d3.Selection<any>) => {\n-      assert.strictEqual(cells[0].length, 5);\n-      cells.each(function(d: any, i: number) {\n-        let cell = d3.select(this);\n-        assert.closeTo(+cell.attr(\"height\"), 50, 0.5, \"Cell height is correct\");\n-        assert.closeTo(+cell.attr(\"width\"), 50, 0.5, \"Cell width is correct\");\n-        assert.closeTo(+cell.attr(\"x\"), 25 + 50 * i, 0.5, \"Cell x coordinate is correct\");\n-        assert.closeTo(+cell.attr(\"y\"), 25 + 50 * (cells[0].length - i - 1), 0.5, \"Cell y coordinate is correct\");\n+    describe(\"Basic usage\", () => {\n+      let data = [\n+        { x: 0, y: 0, x2: 1, y2: 1 },\n+        { x: 1, y: 1, x2: 2, y2: 2 },\n+        { x: 2, y: 2, x2: 3, y2: 3 },\n+        { x: 3, y: 3, x2: 4, y2: 4 },\n+        { x: 4, y: 4, x2: 5, y2: 5 }\n+      ];\n+      let verifyCells = (cells: d3.Selection<any>) => {\n+        assert.strictEqual(cells[0].length, 5);\n+        cells.each(function(d, i) {\n+          let cell = d3.select(this);\n+          assert.closeTo(+cell.attr(\"height\"), 50, 0.5, \"Cell height is correct\");\n+          assert.closeTo(+cell.attr(\"width\"), 50, 0.5, \"Cell width is correct\");\n+          assert.closeTo(+cell.attr(\"x\"), 25 + 50 * i, 0.5, \"Cell x coordinate is correct\");\n+          assert.closeTo(+cell.attr(\"y\"), 25 + 50 * (cells[0].length - i - 1), 0.5, \"Cell y coordinate is correct\");\n+        });\n+      };\n+\n+      let svg: d3.Selection<void>;\n+      let xScale: Plottable.Scales.Linear;\n+      let yScale: Plottable.Scales.Linear;\n+      let plot: Plottable.Plots.Rectangle<number, number>;\n+\n+      beforeEach(() => {\n+        svg = TestMethods.generateSVG(300, 300);\n+        xScale = new Plottable.Scales.Linear();\n+        yScale = new Plottable.Scales.Linear();\n+        plot = new Plottable.Plots.Rectangle<number, number>();\n+        plot.x((d) => d.x, xScale).x2((d) => d.x2);\n+        plot.y((d) => d.y, yScale).y2((d) => d.y2);\n       });\n-    };\n-\n-    it(\"renders correctly\", () => {\n-      let xScale = new Plottable.Scales.Linear();\n-      let yScale = new Plottable.Scales.Linear();\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      let rectanglePlot = new Plottable.Plots.Rectangle();\n-      rectanglePlot.addDataset(new Plottable.Dataset(DATA));\n-      rectanglePlot.x((d) => d.x, xScale)\n-                   .y((d) => d.y, yScale)\n-                   .x2((d) => d.x2)\n-                   .y2((d) => d.y2)\n-                   .renderTo(svg);\n-      VERIFY_CELLS((<any> rectanglePlot)._renderArea.selectAll(\"rect\"));\n-      svg.remove();\n-    });\n \n-    it(\"retrieves the correct entity under a point\", () => {\n-      let xScale = new Plottable.Scales.Linear();\n-      let yScale = new Plottable.Scales.Linear();\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      let dataset = new Plottable.Dataset(DATA);\n-      let plot = new Plottable.Plots.Rectangle()\n-        .x((d) => d.x, xScale).x2((d) => d.x2)\n-        .y((d) => d.y, yScale).y2((d) => d.y2);\n-      plot.addDataset(dataset).renderTo(svg);\n-      let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) });\n-      assert.lengthOf(entities, 1, \"found only one entity when querying a point inside the third rectangle\");\n-      assert.strictEqual(entities[0].index, 2, \"entity retrieved is at index 2\");\n-      svg.remove();\n-    });\n+      it(\"has correct rectangle heights and positions (renders correctly)\", () => {\n+        plot.addDataset(new Plottable.Dataset(data));\n+        plot.renderTo(svg);\n \n-    it(\"retrieves correct entities under a point\", () => {\n-      let xScale = new Plottable.Scales.Linear();\n-      let yScale = new Plottable.Scales.Linear();\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      let dataset = new Plottable.Dataset([\n-        { x: 1, y: 1, x2: 3, y2: 3 },\n-        { x: 4, y: 2, x2: 2, y2: 4 }\n-      ]);\n-      let plot = new Plottable.Plots.Rectangle()\n-        .x((d) => d.x, xScale).x2((d) => d.x2)\n-        .y((d) => d.y, yScale).y2((d) => d.y2);\n-      plot.addDataset(dataset).renderTo(svg);\n-      let entities = plot.entitiesAt({ x: xScale.scale(2), y: xScale.scale(2) });\n-      assert.lengthOf(entities, 2, \"two entities when querying a point in both\");\n-      assert.strictEqual(entities[0].index, 0, \"entity retrieved is at index 0\");\n-      assert.strictEqual(entities[1].index, 1, \"entity retrieved is at index 1\");\n-      entities = plot.entitiesAt({ x: xScale.scale(4), y: yScale.scale(4) });\n-      assert.lengthOf(entities, 1, \"found only one entity when querying a point inside the second rectangle\");\n-      assert.strictEqual(entities[0].index, 1, \"entity retrieved is at index 1\");\n-      entities = plot.entitiesAt({ x: xScale.scale(1), y: yScale.scale(1) });\n-      assert.lengthOf(entities, 1, \"found only one entity when querying a point inside the first rectangle\");\n-      assert.strictEqual(entities[0].index, 0, \"entity retrieved is at index 0\");\n-      svg.remove();\n-    });\n+        verifyCells(plot.content().selectAll(\"rect\"));\n+        svg.remove();\n+      });\n \n-    it(\"retrieves the entities that intersect with the bounding box\", () => {\n-      let xScale = new Plottable.Scales.Linear();\n-      let yScale = new Plottable.Scales.Linear();\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      let dataset = new Plottable.Dataset(DATA);\n-      let plot = new Plottable.Plots.Rectangle()\n-        .x((d) => d.x, xScale).x2((d) => d.x2)\n-        .y((d) => d.y, yScale).y2((d) => d.y2);\n-      plot.addDataset(dataset).renderTo(svg);\n-\n-      let entities = plot.entitiesIn({\n-        topLeft: { x: xScale.scale(1.5), y: yScale.scale(2.5) },\n-        bottomRight: { x: xScale.scale(2.5), y: yScale.scale(1.5) } });\n-      assert.lengthOf(entities, 2, \"retrieved 2 entities intersect with the box\");\n-      assert.strictEqual(entities[0].index, 1, \"the entity of index 1 is retrieved\");\n-      assert.strictEqual(entities[1].index, 2, \"the entity of index 2 is retrieved\");\n-      svg.remove();\n-    });\n+      it(\"retrieves the correct entity under a point\", () => {\n+        plot.addDataset(new Plottable.Dataset(data));\n+        plot.renderTo(svg);\n+\n+        let entities = plot.entitiesAt({ x: xScale.scale(2.5), y: yScale.scale(2.5) });\n+        assert.lengthOf(entities, 1, \"found only one entity when querying a point inside the third rectangle\");\n+        assert.strictEqual(entities[0].index, 2, \"entity retrieved is at index 2\");\n+        svg.remove();\n+      });\n+\n+      it(\"retrieves correct entities under a point when rectangles intersect\", () => {\n+        let dataset = new Plottable.Dataset([\n+          { x: 1, y: 1, x2: 3, y2: 3 },\n+          { x: 4, y: 2, x2: 2, y2: 4 }\n+        ]);\n+        plot.addDataset(dataset);\n+        plot.renderTo(svg);\n+\n+        let entities = plot.entitiesAt({ x: xScale.scale(2), y: xScale.scale(2) });\n+        assert.lengthOf(entities, 2, \"two entities when querying a point in both\");\n+        assert.strictEqual(entities[0].index, 0, \"entity retrieved is at index 0\");\n+        assert.strictEqual(entities[1].index, 1, \"entity retrieved is at index 1\");\n+        entities = plot.entitiesAt({ x: xScale.scale(4), y: yScale.scale(4) });\n+        assert.lengthOf(entities, 1, \"found only one entity when querying a point inside the second rectangle\");\n+        assert.strictEqual(entities[0].index, 1, \"entity retrieved is at index 1\");\n+        entities = plot.entitiesAt({ x: xScale.scale(1), y: yScale.scale(1) });\n+        assert.lengthOf(entities, 1, \"found only one entity when querying a point inside the first rectangle\");\n+        assert.strictEqual(entities[0].index, 0, \"entity retrieved is at index 0\");\n+        svg.remove();\n+      });\n+\n+      it(\"retrieves the entities that intersect with the bounding box\", () => {\n+        plot.addDataset(new Plottable.Dataset(data));\n+        plot.renderTo(svg);\n+\n+        let entities = plot.entitiesIn({\n+          topLeft: { x: xScale.scale(1.5), y: yScale.scale(2.5) },\n+          bottomRight: { x: xScale.scale(2.5), y: yScale.scale(1.5) } });\n+        assert.lengthOf(entities, 2, \"retrieved 2 entities intersect with the box\");\n+        assert.strictEqual(entities[0].index, 1, \"the entity of index 1 is retrieved\");\n+        assert.strictEqual(entities[1].index, 2, \"the entity of index 2 is retrieved\");\n+        svg.remove();\n+      });\n \n-    it(\"retrieves the entities that intersect with the given ranges\", () => {\n-      let xScale = new Plottable.Scales.Linear();\n-      let yScale = new Plottable.Scales.Linear();\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      let dataset = new Plottable.Dataset(DATA);\n-      let plot = new Plottable.Plots.Rectangle()\n-        .x((d) => d.x, xScale).x2((d) => d.x2)\n-        .y((d) => d.y, yScale).y2((d) => d.y2);\n-      plot.addDataset(dataset).renderTo(svg);\n-\n-      let entities = plot.entitiesIn(\n-        {min: xScale.scale(1.5), max: xScale.scale(2.5)},\n-        {min: yScale.scale(2.5), max: yScale.scale(1.5)});\n-      assert.lengthOf(entities, 2, \"retrieved 2 entities intersect with the box\");\n-      assert.strictEqual(entities[0].index, 1, \"the entity of index 1 is retrieved\");\n-      assert.strictEqual(entities[1].index, 2, \"the entity of index 2 is retrieved\");\n-      svg.remove();\n+      it(\"retrieves the entities that intersect with the given ranges\", () => {\n+        plot.addDataset(new Plottable.Dataset(data));\n+        plot.renderTo(svg);\n+\n+        let entities = plot.entitiesIn(\n+          {min: xScale.scale(1.5), max: xScale.scale(2.5)},\n+          {min: yScale.scale(2.5), max: yScale.scale(1.5)});\n+        assert.lengthOf(entities, 2, \"retrieved 2 entities intersect with the box\");\n+        assert.strictEqual(entities[0].index, 1, \"the entity of index 1 is retrieved\");\n+        assert.strictEqual(entities[1].index, 2, \"the entity of index 2 is retrieved\");\n+        svg.remove();\n+      });\n     });\n \n-    it(\"autorangeMode(\\\"x\\\")\", () => {\n-      let staggeredData = [\n-        { y: \"A\", x: 0, x2: 1 },\n-        { y: \"B\", x: 1, x2: 2 }\n-      ];\n+    describe(\"autorangeMode()\", () => {\n+      let svg: d3.Selection<void>;\n \n-      let xScale = new Plottable.Scales.Linear();\n-      let yScale = new Plottable.Scales.Category();\n-      xScale.padProportion(0);\n+      beforeEach(() => {\n+        svg = TestMethods.generateSVG(300, 300);\n+      });\n \n-      let plot = new Plottable.Plots.Rectangle();\n-      plot.x(function(d) { return d.x; }, xScale);\n-      plot.x2(function(d) { return d.x2; });\n-      plot.y(function(d) { return d.y; }, yScale);\n-      plot.addDataset(new Plottable.Dataset(staggeredData));\n-      plot.autorangeMode(\"x\");\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      plot.renderTo(svg);\n+      it(\"adjusts the xScale domain with respect to the yScale domain when autorangeMode on x\", () => {\n+        let data = [\n+          { y: \"A\", x: 0, x2: 1 },\n+          { y: \"B\", x: 1, x2: 2 }\n+        ];\n \n-      assert.deepEqual(xScale.domain(), [0, 2], \"y domain includes both visible segments\");\n+        let xScale = new Plottable.Scales.Linear();\n+        let yScale = new Plottable.Scales.Category();\n+        xScale.padProportion(0);\n \n-      yScale.domain([\"A\"]);\n-      assert.deepEqual(xScale.domain(), [0, 1], \"y domain includes only the visible segment (first)\");\n+        let plot = new Plottable.Plots.Rectangle();\n+        plot.x((d) => d.x, xScale);\n+        plot.x2((d) => d.x2);\n+        plot.y((d) => d.y, yScale);\n+        plot.addDataset(new Plottable.Dataset(data));\n+        plot.autorangeMode(\"x\");\n+        plot.renderTo(svg);\n \n-      yScale.domain([\"B\"]);\n-      assert.deepEqual(xScale.domain(), [1, 2], \"y domain includes only the visible segment (second)\");\n+        assert.deepEqual(xScale.domain(), [0, 2], \"x domain includes both visible segments\");\n \n-      svg.remove();\n-    });\n+        yScale.domain([\"A\"]);\n+        assert.deepEqual(xScale.domain(), [0, 1], \"x domain includes only the visible segment (first)\");\n \n-    it(\"autorangeMode(\\\"y\\\")\", () => {\n-      let staggeredData = [\n-        { x: \"A\", y: 0, y2: 1 },\n-        { x: \"B\", y: 1, y2: 2 }\n-      ];\n+        yScale.domain([\"B\"]);\n+        assert.deepEqual(xScale.domain(), [1, 2], \"x domain includes only the visible segment (second)\");\n+        svg.remove();\n+      });\n \n-      let xScale = new Plottable.Scales.Category();\n-      let yScale = new Plottable.Scales.Linear();\n-      yScale.padProportion(0);\n+      it(\"adjusts the yScale domain with respect to the xScale domain when autorangeMode on y\", () => {\n+        let data = [\n+          { x: \"A\", y: 0, y2: 1 },\n+          { x: \"B\", y: 1, y2: 2 }\n+        ];\n \n-      let plot = new Plottable.Plots.Rectangle();\n-      plot.x(function(d) { return d.x; }, xScale);\n-      plot.y(function(d) { return d.y; }, yScale);\n-      plot.y2(function(d) { return d.y2; });\n-      plot.addDataset(new Plottable.Dataset(staggeredData));\n-      plot.autorangeMode(\"y\");\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      plot.renderTo(svg);\n+        let xScale = new Plottable.Scales.Category();\n+        let yScale = new Plottable.Scales.Linear();\n+        yScale.padProportion(0);\n \n-      assert.deepEqual(yScale.domain(), [0, 2], \"y domain includes both visible segments\");\n+        let plot = new Plottable.Plots.Rectangle();\n+        plot.x((d) => d.x, xScale);\n+        plot.y((d) => d.y, yScale);\n+        plot.y2((d) => d.y2);\n+        plot.addDataset(new Plottable.Dataset(data));\n+        plot.autorangeMode(\"y\");\n+        plot.renderTo(svg);\n \n-      xScale.domain([\"A\"]);\n-      assert.deepEqual(yScale.domain(), [0, 1], \"y domain includes only the visible segment (first)\");\n+        assert.deepEqual(yScale.domain(), [0, 2], \"y domain includes both visible segments\");\n \n-      xScale.domain([\"B\"]);\n-      assert.deepEqual(yScale.domain(), [1, 2], \"y domain includes only the visible segment (second)\");\n+        xScale.domain([\"A\"]);\n+        assert.deepEqual(yScale.domain(), [0, 1], \"y domain includes only the visible segment (first)\");\n \n-      svg.remove();\n+        xScale.domain([\"B\"]);\n+        assert.deepEqual(yScale.domain(), [1, 2], \"y domain includes only the visible segment (second)\");\n+        svg.remove();\n+      });\n     });\n \n-  });\n+    describe(\"Fail safe tests\", () => {\n+      it(\"does not draw rectangles for invalid data points\", () => {\n+        let svg = TestMethods.generateSVG();\n+\n+        let data1 = [\n+          { x: \"A\", y: 1, y2: 2, v: 1 },\n+          { x: \"B\", y: 2, y2: 3, v: 2 },\n+          { x: \"C\", y: 3, y2: NaN, v: 3 },\n+          { x: \"D\", y: 4, y2: 5, v: 4 },\n+          { x: \"E\", y: 5, y2: 6, v: 5 },\n+          { x: \"F\", y: 6, y2: 7, v: 6 }\n+        ];\n \n-  describe(\"fail safe tests\", () => {\n-    it(\"illegal rectangles don't get displayed\", () => {\n-      let svg = TestMethods.generateSVG();\n-\n-      let data1 = [\n-        { x: \"A\", y: 1, y2: 2, v: 1 },\n-        { x: \"B\", y: 2, y2: 3, v: 2 },\n-        { x: \"C\", y: 3, y2: NaN, v: 3 },\n-        { x: \"D\", y: 4, y2: 5, v: 4 },\n-        { x: \"E\", y: 5, y2: 6, v: 5 },\n-        { x: \"F\", y: 6, y2: 7, v: 6 }\n+        let xScale = new Plottable.Scales.Category();\n+        let yScale = new Plottable.Scales.Linear();\n+\n+        let plot = new Plottable.Plots.Rectangle();\n+        plot.x((d: any) => d.x, xScale);\n+        plot.y((d: any) => d.y, yScale);\n+        plot.y2((d: any) => d.y2);\n+        plot.addDataset(new Plottable.Dataset(data1));\n+\n+        plot.renderTo(svg);\n+\n+        let rectanglesSelection = plot.selections();\n+\n+        assert.strictEqual(rectanglesSelection.size(), 5,\n+          \"only 5 rectangles should be displayed\");\n+\n+        rectanglesSelection.each(function(d: any, i: number) {\n+          let sel = d3.select(this);\n+          assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr(\"x\")),\n+            \"x attribute should be valid for rectangle # \" + i + \". Currently \" + sel.attr(\"x\"));\n+          assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr(\"y\")),\n+            \"y attribute should be valid for rectangle # \" + i + \". Currently \" + sel.attr(\"y\"));\n+          assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr(\"height\")),\n+            \"height attribute should be valid for rectangle # \" + i + \". Currently \" + sel.attr(\"height\"));\n+          assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr(\"width\")),\n+            \"width attribute should be valid for rectangle # \" + i + \". Currently \" + sel.attr(\"width\"));\n+        });\n+\n+        svg.remove();\n+      });\n+    });\n+\n+    describe(\"Grids\", () => {\n+      let SVG_WIDTH = 400;\n+      let SVG_HEIGHT = 200;\n+      let data = [\n+        {x: \"A\", y: \"U\", magnitude: 0},\n+        {x: \"B\", y: \"U\", magnitude: 2},\n+        {x: \"A\", y: \"V\", magnitude: 16},\n+        {x: \"B\", y: \"V\", magnitude: 8},\n       ];\n \n-      let xScale = new Plottable.Scales.Category();\n-      let yScale = new Plottable.Scales.Linear();\n-\n-      let plot = new Plottable.Plots.Rectangle();\n-      plot\n-        .x((d: any) => d.x, xScale)\n-        .y((d: any) => d.y, yScale)\n-        .y2((d: any) => d.y2);\n-      plot.addDataset(new Plottable.Dataset(data1));\n-\n-      plot.renderTo(svg);\n-\n-      let rectanglesSelection = plot.selections();\n-\n-      assert.strictEqual(rectanglesSelection.size(), 5,\n-        \"only 5 rectangles should be displayed\");\n-\n-      rectanglesSelection.each(function(d: any, i: number) {\n-        let sel = d3.select(this);\n-        assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr(\"x\")),\n-          \"x attribute should be valid for rectangle # \" + i + \". Currently \" + sel.attr(\"x\"));\n-        assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr(\"y\")),\n-          \"y attribute should be valid for rectangle # \" + i + \". Currently \" + sel.attr(\"y\"));\n-        assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr(\"height\")),\n-          \"height attribute should be valid for rectangle # \" + i + \". Currently \" + sel.attr(\"height\"));\n-        assert.isFalse(Plottable.Utils.Math.isNaN(+sel.attr(\"width\")),\n-          \"width attribute should be valid for rectangle # \" + i + \". Currently \" + sel.attr(\"width\"));\n+      let verifyCells = (cells: any[]) => {\n+        assert.strictEqual(cells.length, 4);\n+\n+        let cellAU = d3.select(cells[0]);\n+        let cellBU = d3.select(cells[1]);\n+        let cellAV = d3.select(cells[2]);\n+        let cellBV = d3.select(cells[3]);\n+\n+        assert.strictEqual(cellAU.attr(\"height\"), \"100\", \"cell 'AU' height is correct\");\n+        assert.strictEqual(cellAU.attr(\"width\"), \"200\", \"cell 'AU' width is correct\");\n+        assert.strictEqual(cellAU.attr(\"x\"), \"0\", \"cell 'AU' x coord is correct\");\n+        assert.strictEqual(cellAU.attr(\"y\"), \"0\", \"cell 'AU' y coord is correct\");\n+        assert.strictEqual(cellAU.attr(\"fill\"), \"#000000\", \"cell 'AU' color is correct\");\n+\n+        assert.strictEqual(cellBU.attr(\"height\"), \"100\", \"cell 'BU' height is correct\");\n+        assert.strictEqual(cellBU.attr(\"width\"), \"200\", \"cell 'BU' width is correct\");\n+        assert.strictEqual(cellBU.attr(\"x\"), \"200\", \"cell 'BU' x coord is correct\");\n+        assert.strictEqual(cellBU.attr(\"y\"), \"0\", \"cell 'BU' y coord is correct\");\n+        assert.strictEqual(cellBU.attr(\"fill\"), \"#212121\", \"cell 'BU' color is correct\");\n+\n+        assert.strictEqual(cellAV.attr(\"height\"), \"100\", \"cell 'AV' height is correct\");\n+        assert.strictEqual(cellAV.attr(\"width\"), \"200\", \"cell 'AV' width is correct\");\n+        assert.strictEqual(cellAV.attr(\"x\"), \"0\", \"cell 'AV' x coord is correct\");\n+        assert.strictEqual(cellAV.attr(\"y\"), \"100\", \"cell 'AV' y coord is correct\");\n+        assert.strictEqual(cellAV.attr(\"fill\"), \"#ffffff\", \"cell 'AV' color is correct\");\n+\n+        assert.strictEqual(cellBV.attr(\"height\"), \"100\", \"cell 'BV' height is correct\");\n+        assert.strictEqual(cellBV.attr(\"width\"), \"200\", \"cell 'BV' width is correct\");\n+        assert.strictEqual(cellBV.attr(\"x\"), \"200\", \"cell 'BV' x coord is correct\");\n+        assert.strictEqual(cellBV.attr(\"y\"), \"100\", \"cell 'BV' y coord is correct\");\n+        assert.strictEqual(cellBV.attr(\"fill\"), \"#777777\", \"cell 'BV' color is correct\");\n+      };\n+\n+      let svg: d3.Selection<void>;\n+      let xScale: Plottable.Scales.Category;\n+      let yScale: Plottable.Scales.Category;\n+      let colorScale: Plottable.Scales.InterpolatedColor;\n+\n+      beforeEach(() => {\n+        svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n+        xScale = new Plottable.Scales.Category();\n+        yScale = new Plottable.Scales.Category();\n+        colorScale = new Plottable.Scales.InterpolatedColor();\n+        colorScale.range([\"black\", \"white\"]);\n       });\n \n-      svg.remove();\n-    });\n-  });\n+      it(\"renders correctly\", () => {\n+        let plot = new Plottable.Plots.Rectangle();\n+        plot.addDataset(new Plottable.Dataset(data));\n+        plot.attr(\"fill\", (d) => d.magnitude, colorScale);\n+        plot.x((d: any) => d.x, xScale);\n+        plot.y((d: any) => d.y, yScale);\n+        plot.renderTo(svg);\n+        verifyCells(plot.content().selectAll(\"rect\")[0]);\n+        svg.remove();\n+      });\n \n-  describe(\"RectanglePlot - Grids\", () => {\n-    let SVG_WIDTH = 400;\n-    let SVG_HEIGHT = 200;\n-    let DATA = [\n-      {x: \"A\", y: \"U\", magnitude: 0},\n-      {x: \"B\", y: \"U\", magnitude: 2},\n-      {x: \"A\", y: \"V\", magnitude: 16},\n-      {x: \"B\", y: \"V\", magnitude: 8},\n-    ];\n-\n-    let VERIFY_CELLS = (cells: any[]) => {\n-      assert.strictEqual(cells.length, 4);\n-\n-      let cellAU = d3.select(cells[0]);\n-      let cellBU = d3.select(cells[1]);\n-      let cellAV = d3.select(cells[2]);\n-      let cellBV = d3.select(cells[3]);\n-\n-      assert.strictEqual(cellAU.attr(\"height\"), \"100\", \"cell 'AU' height is correct\");\n-      assert.strictEqual(cellAU.attr(\"width\"), \"200\", \"cell 'AU' width is correct\");\n-      assert.strictEqual(cellAU.attr(\"x\"), \"0\", \"cell 'AU' x coord is correct\");\n-      assert.strictEqual(cellAU.attr(\"y\"), \"0\", \"cell 'AU' y coord is correct\");\n-      assert.strictEqual(cellAU.attr(\"fill\"), \"#000000\", \"cell 'AU' color is correct\");\n-\n-      assert.strictEqual(cellBU.attr(\"height\"), \"100\", \"cell 'BU' height is correct\");\n-      assert.strictEqual(cellBU.attr(\"width\"), \"200\", \"cell 'BU' width is correct\");\n-      assert.strictEqual(cellBU.attr(\"x\"), \"200\", \"cell 'BU' x coord is correct\");\n-      assert.strictEqual(cellBU.attr(\"y\"), \"0\", \"cell 'BU' y coord is correct\");\n-      assert.strictEqual(cellBU.attr(\"fill\"), \"#212121\", \"cell 'BU' color is correct\");\n-\n-      assert.strictEqual(cellAV.attr(\"height\"), \"100\", \"cell 'AV' height is correct\");\n-      assert.strictEqual(cellAV.attr(\"width\"), \"200\", \"cell 'AV' width is correct\");\n-      assert.strictEqual(cellAV.attr(\"x\"), \"0\", \"cell 'AV' x coord is correct\");\n-      assert.strictEqual(cellAV.attr(\"y\"), \"100\", \"cell 'AV' y coord is correct\");\n-      assert.strictEqual(cellAV.attr(\"fill\"), \"#ffffff\", \"cell 'AV' color is correct\");\n-\n-      assert.strictEqual(cellBV.attr(\"height\"), \"100\", \"cell 'BV' height is correct\");\n-      assert.strictEqual(cellBV.attr(\"width\"), \"200\", \"cell 'BV' width is correct\");\n-      assert.strictEqual(cellBV.attr(\"x\"), \"200\", \"cell 'BV' x coord is correct\");\n-      assert.strictEqual(cellBV.attr(\"y\"), \"100\", \"cell 'BV' y coord is correct\");\n-      assert.strictEqual(cellBV.attr(\"fill\"), \"#777777\", \"cell 'BV' color is correct\");\n-    };\n-\n-    it(\"renders correctly\", () => {\n-      let xScale = new Plottable.Scales.Category();\n-      let yScale = new Plottable.Scales.Category();\n-      let colorScale = new Plottable.Scales.InterpolatedColor();\n-      colorScale.range([\"black\", \"white\"]);\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      let gridPlot = new Plottable.Plots.Rectangle();\n-      gridPlot.addDataset(new Plottable.Dataset(DATA))\n-              .attr(\"fill\", (d) => d.magnitude, colorScale);\n-      gridPlot.x((d: any) => d.x, xScale)\n-              .y((d: any) => d.y, yScale);\n-      gridPlot.renderTo(svg);\n-      VERIFY_CELLS((<any> gridPlot)._renderArea.selectAll(\"rect\")[0]);\n-      svg.remove();\n-    });\n+      it(\"renders correctly when data is set after construction\", () => {\n+        let dataset = new Plottable.Dataset();\n+        let plot = new Plottable.Plots.Rectangle();\n+        plot.addDataset(dataset);\n+        plot.attr(\"fill\", (d) => d.magnitude, colorScale);\n+        plot.x((d: any) => d.x, xScale);\n+        plot.y((d: any) => d.y, yScale);\n+        plot.renderTo(svg);\n+        dataset.data(data);\n+        verifyCells(plot.content().selectAll(\"rect\")[0]);\n+        svg.remove();\n+      });\n+\n+      it(\"renders correctly when there isn't data for every spot\", () => {\n+        let CELL_HEIGHT = 50;\n+        let CELL_WIDTH = 100;\n+        let dataset = new Plottable.Dataset();\n+        let plot = new Plottable.Plots.Rectangle();\n+        plot.addDataset(dataset);\n+        plot.attr(\"fill\", (d) => d.magnitude, colorScale);\n+        plot.x((d: any) => d.x, xScale);\n+        plot.y((d: any) => d.y, yScale);\n+        plot.renderTo(svg);\n+        let data = [\n+          {x: \"A\", y: \"W\", magnitude: 0},\n+          {x: \"B\", y: \"X\", magnitude: 8},\n+          {x: \"C\", y: \"Y\", magnitude: 16},\n+          {x: \"D\", y: \"Z\", magnitude: 24}\n+        ];\n+        dataset.data(data);\n+        let cells = plot.content().selectAll(\"rect\")[0];\n+        assert.strictEqual(cells.length, data.length);\n+        for (let i = 0; i < cells.length; i++) {\n+          let cell = d3.select(cells[i]);\n+          assert.strictEqual(cell.attr(\"x\"), String(i * CELL_WIDTH), \"Cell x coord is correct\");\n+          assert.strictEqual(cell.attr(\"y\"), String(i * CELL_HEIGHT), \"Cell y coord is correct\");\n+          assert.strictEqual(cell.attr(\"width\"), String(CELL_WIDTH), \"Cell width is correct\");\n+          assert.strictEqual(cell.attr(\"height\"), String(CELL_HEIGHT), \"Cell height is correct\");\n+        }\n+        svg.remove();\n+      });\n \n-    it(\"renders correctly when data is set after construction\", () => {\n-      let xScale = new Plottable.Scales.Category();\n-      let yScale = new Plottable.Scales.Category();\n-      let colorScale = new Plottable.Scales.InterpolatedColor();\n-      colorScale.range([\"black\", \"white\"]);\n-      let svg = TestMethods.generateSVG(SVG_WIDTH, SVG_HEIGHT);\n-      let dataset = new Plottable.Dataset();\n-      let gridPlot = new Plottable.Plots.Rectangle();\n-      gridPlot.addDataset(dataset)\n-              .attr(\"fill\", (d) => d.magnitude, colorScale);\n-      gridPlot.x((d: any) => d.x, xScale)\n-              .y((d: any) => d.y, yScale)\n-              .renderTo(svg);\n-      dataset.data(DATA);\n-      VERIFY_CELLS((<any> gridPlot)._renderArea.selectAll(\"rect\")[0]);\n-      svg.remove();\n+      it(\"can invert y axis correctly\", () => {\n+        let plot = new Plottable.Plots.Rectangle();\n+        plot.addDataset(new Plottable.Dataset(data));\n+        plot.attr(\"fill\", (d) => d.magnitude, colorScale);\n+        plot.x((d: any) => d.x, xScale);\n+        plot.y((d: any) => d.y, yScale);\n+        plot.renderTo(svg);\n+\n+        yScale.domain([\"U\", \"V\"]);\n+\n+        let cells = plot.content().selectAll(\"rect\")[0];\n+        let cellAU = d3.select(cells[0]);\n+        let cellAV = d3.select(cells[2]);\n+        cellAU.attr(\"fill\", \"#000000\");\n+        cellAU.attr(\"x\", \"0\");\n+        cellAU.attr(\"y\", \"100\");\n+\n+        cellAV.attr(\"fill\", \"#ffffff\");\n+        cellAV.attr(\"x\", \"0\");\n+        cellAV.attr(\"y\", \"0\");\n+\n+        yScale.domain([\"V\", \"U\"]);\n+        cells = plot.content().selectAll(\"rect\")[0];\n+        cellAU = d3.select(cells[0]);\n+        cellAV = d3.select(cells[2]);\n+        cellAU.attr(\"fill\", \"#000000\");\n+        cellAU.attr(\"x\", \"0\");\n+        cellAU.attr(\"y\", \"0\");\n+\n+        cellAV.attr(\"fill\", \"#ffffff\");\n+        cellAV.attr(\"x\", \"0\");\n+        cellAV.attr(\"y\", \"100\");\n+        svg.remove();\n+      });","path":"test/plots/rectanglePlotTests.ts","position":621,"original_position":621,"commit_id":"edec0423bf30ba0d138f2aea73f3cb9fd5fd6c3c","original_commit_id":"edec0423bf30ba0d138f2aea73f3cb9fd5fd6c3c","user":{"login":"aicioara","id":3248682,"avatar_url":"https://avatars.githubusercontent.com/u/3248682?v=3","gravatar_id":"","url":"https://api.github.com/users/aicioara","html_url":"https://github.com/aicioara","followers_url":"https://api.github.com/users/aicioara/followers","following_url":"https://api.github.com/users/aicioara/following{/other_user}","gists_url":"https://api.github.com/users/aicioara/gists{/gist_id}","starred_url":"https://api.github.com/users/aicioara/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aicioara/subscriptions","organizations_url":"https://api.github.com/users/aicioara/orgs","repos_url":"https://api.github.com/users/aicioara/repos","events_url":"https://api.github.com/users/aicioara/events{/privacy}","received_events_url":"https://api.github.com/users/aicioara/received_events","type":"User","site_admin":false},"body":"Lol, this test was so broken. ","created_at":"2015-08-20T22:44:07Z","updated_at":"2015-08-20T22:44:07Z","html_url":"https://github.com/palantir/plottable/pull/2653#discussion_r37589772","pull_request_url":"https://api.github.com/repos/palantir/plottable/pulls/2653","_links":{"self":{"href":"https://api.github.com/repos/palantir/plottable/pulls/comments/37589772"},"html":{"href":"https://github.com/palantir/plottable/pull/2653#discussion_r37589772"},"pull_request":{"href":"https://api.github.com/repos/palantir/plottable/pulls/2653"}}},"pull_request":{"url":"https://api.github.com/repos/palantir/plottable/pulls/2653","id":42866844,"html_url":"https://github.com/palantir/plottable/pull/2653","diff_url":"https://github.com/palantir/plottable/pull/2653.diff","patch_url":"https://github.com/palantir/plottable/pull/2653.patch","issue_url":"https://api.github.com/repos/palantir/plottable/issues/2653","number":2653,"state":"open","locked":false,"title":"Refactor rectangle plot tests","user":{"login":"aicioara","id":3248682,"avatar_url":"https://avatars.githubusercontent.com/u/3248682?v=3","gravatar_id":"","url":"https://api.github.com/users/aicioara","html_url":"https://github.com/aicioara","followers_url":"https://api.github.com/users/aicioara/followers","following_url":"https://api.github.com/users/aicioara/following{/other_user}","gists_url":"https://api.github.com/users/aicioara/gists{/gist_id}","starred_url":"https://api.github.com/users/aicioara/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aicioara/subscriptions","organizations_url":"https://api.github.com/users/aicioara/orgs","repos_url":"https://api.github.com/users/aicioara/repos","events_url":"https://api.github.com/users/aicioara/events{/privacy}","received_events_url":"https://api.github.com/users/aicioara/received_events","type":"User","site_admin":false},"body":"Part of #2636\r\n\r\nI will be doing multiple passes because I will get more context (and better sense of best practices) by refactoring other files. However, please flag anything that seems unusual.\r\n\r\nAs part of this: \r\n- Applied best practices from the wiki page\r\n- Factored out common code into `beforeEach()` clauses\r\n- No nested `beforeEach()`es\r\n- Correct semantics of the test titles\r\n- Remade hierarchy as shown bellow\r\n![screen shot 2015-08-19 at 6 43 26 pm](https://cloud.githubusercontent.com/assets/3248682/9373707/36fdf38a-46a2-11e5-8763-7cbfd378d855.png)\r\n\r\n","created_at":"2015-08-19T21:33:10Z","updated_at":"2015-08-20T22:44:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0c9fdd3f0d4811ef5332ac726ef3afb0d3000741","assignee":{"login":"aicioara","id":3248682,"avatar_url":"https://avatars.githubusercontent.com/u/3248682?v=3","gravatar_id":"","url":"https://api.github.com/users/aicioara","html_url":"https://github.com/aicioara","followers_url":"https://api.github.com/users/aicioara/followers","following_url":"https://api.github.com/users/aicioara/following{/other_user}","gists_url":"https://api.github.com/users/aicioara/gists{/gist_id}","starred_url":"https://api.github.com/users/aicioara/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aicioara/subscriptions","organizations_url":"https://api.github.com/users/aicioara/orgs","repos_url":"https://api.github.com/users/aicioara/repos","events_url":"https://api.github.com/users/aicioara/events{/privacy}","received_events_url":"https://api.github.com/users/aicioara/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/palantir/plottable/pulls/2653/commits","review_comments_url":"https://api.github.com/repos/palantir/plottable/pulls/2653/comments","review_comment_url":"https://api.github.com/repos/palantir/plottable/pulls/comments{/number}","comments_url":"https://api.github.com/repos/palantir/plottable/issues/2653/comments","statuses_url":"https://api.github.com/repos/palantir/plottable/statuses/edec0423bf30ba0d138f2aea73f3cb9fd5fd6c3c","head":{"label":"palantir:refactorRectangle","ref":"refactorRectangle","sha":"edec0423bf30ba0d138f2aea73f3cb9fd5fd6c3c","user":{"login":"palantir","id":303157,"avatar_url":"https://avatars.githubusercontent.com/u/303157?v=3","gravatar_id":"","url":"https://api.github.com/users/palantir","html_url":"https://github.com/palantir","followers_url":"https://api.github.com/users/palantir/followers","following_url":"https://api.github.com/users/palantir/following{/other_user}","gists_url":"https://api.github.com/users/palantir/gists{/gist_id}","starred_url":"https://api.github.com/users/palantir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/palantir/subscriptions","organizations_url":"https://api.github.com/users/palantir/orgs","repos_url":"https://api.github.com/users/palantir/repos","events_url":"https://api.github.com/users/palantir/events{/privacy}","received_events_url":"https://api.github.com/users/palantir/received_events","type":"Organization","site_admin":false},"repo":{"id":16149854,"name":"plottable","full_name":"palantir/plottable","owner":{"login":"palantir","id":303157,"avatar_url":"https://avatars.githubusercontent.com/u/303157?v=3","gravatar_id":"","url":"https://api.github.com/users/palantir","html_url":"https://github.com/palantir","followers_url":"https://api.github.com/users/palantir/followers","following_url":"https://api.github.com/users/palantir/following{/other_user}","gists_url":"https://api.github.com/users/palantir/gists{/gist_id}","starred_url":"https://api.github.com/users/palantir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/palantir/subscriptions","organizations_url":"https://api.github.com/users/palantir/orgs","repos_url":"https://api.github.com/users/palantir/repos","events_url":"https://api.github.com/users/palantir/events{/privacy}","received_events_url":"https://api.github.com/users/palantir/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/palantir/plottable","description":"A library of modular chart components, built on D3","fork":false,"url":"https://api.github.com/repos/palantir/plottable","forks_url":"https://api.github.com/repos/palantir/plottable/forks","keys_url":"https://api.github.com/repos/palantir/plottable/keys{/key_id}","collaborators_url":"https://api.github.com/repos/palantir/plottable/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/palantir/plottable/teams","hooks_url":"https://api.github.com/repos/palantir/plottable/hooks","issue_events_url":"https://api.github.com/repos/palantir/plottable/issues/events{/number}","events_url":"https://api.github.com/repos/palantir/plottable/events","assignees_url":"https://api.github.com/repos/palantir/plottable/assignees{/user}","branches_url":"https://api.github.com/repos/palantir/plottable/branches{/branch}","tags_url":"https://api.github.com/repos/palantir/plottable/tags","blobs_url":"https://api.github.com/repos/palantir/plottable/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/palantir/plottable/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/palantir/plottable/git/refs{/sha}","trees_url":"https://api.github.com/repos/palantir/plottable/git/trees{/sha}","statuses_url":"https://api.github.com/repos/palantir/plottable/statuses/{sha}","languages_url":"https://api.github.com/repos/palantir/plottable/languages","stargazers_url":"https://api.github.com/repos/palantir/plottable/stargazers","contributors_url":"https://api.github.com/repos/palantir/plottable/contributors","subscribers_url":"https://api.github.com/repos/palantir/plottable/subscribers","subscription_url":"https://api.github.com/repos/palantir/plottable/subscription","commits_url":"https://api.github.com/repos/palantir/plottable/commits{/sha}","git_commits_url":"https://api.github.com/repos/palantir/plottable/git/commits{/sha}","comments_url":"https://api.github.com/repos/palantir/plottable/comments{/number}","issue_comment_url":"https://api.github.com/repos/palantir/plottable/issues/comments{/number}","contents_url":"https://api.github.com/repos/palantir/plottable/contents/{+path}","compare_url":"https://api.github.com/repos/palantir/plottable/compare/{base}...{head}","merges_url":"https://api.github.com/repos/palantir/plottable/merges","archive_url":"https://api.github.com/repos/palantir/plottable/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/palantir/plottable/downloads","issues_url":"https://api.github.com/repos/palantir/plottable/issues{/number}","pulls_url":"https://api.github.com/repos/palantir/plottable/pulls{/number}","milestones_url":"https://api.github.com/repos/palantir/plottable/milestones{/number}","notifications_url":"https://api.github.com/repos/palantir/plottable/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/palantir/plottable/labels{/name}","releases_url":"https://api.github.com/repos/palantir/plottable/releases{/id}","created_at":"2014-01-22T19:29:19Z","updated_at":"2015-08-20T07:02:51Z","pushed_at":"2015-08-20T22:13:28Z","git_url":"git://github.com/palantir/plottable.git","ssh_url":"git@github.com:palantir/plottable.git","clone_url":"https://github.com/palantir/plottable.git","svn_url":"https://github.com/palantir/plottable","homepage":"plottablejs.org","size":133403,"stargazers_count":669,"watchers_count":669,"language":"TypeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":68,"mirror_url":null,"open_issues_count":176,"forks":68,"open_issues":176,"watchers":669,"default_branch":"develop"}},"base":{"label":"palantir:develop","ref":"develop","sha":"7cec0ea6d5eed4703a0eab3600801a588428defb","user":{"login":"palantir","id":303157,"avatar_url":"https://avatars.githubusercontent.com/u/303157?v=3","gravatar_id":"","url":"https://api.github.com/users/palantir","html_url":"https://github.com/palantir","followers_url":"https://api.github.com/users/palantir/followers","following_url":"https://api.github.com/users/palantir/following{/other_user}","gists_url":"https://api.github.com/users/palantir/gists{/gist_id}","starred_url":"https://api.github.com/users/palantir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/palantir/subscriptions","organizations_url":"https://api.github.com/users/palantir/orgs","repos_url":"https://api.github.com/users/palantir/repos","events_url":"https://api.github.com/users/palantir/events{/privacy}","received_events_url":"https://api.github.com/users/palantir/received_events","type":"Organization","site_admin":false},"repo":{"id":16149854,"name":"plottable","full_name":"palantir/plottable","owner":{"login":"palantir","id":303157,"avatar_url":"https://avatars.githubusercontent.com/u/303157?v=3","gravatar_id":"","url":"https://api.github.com/users/palantir","html_url":"https://github.com/palantir","followers_url":"https://api.github.com/users/palantir/followers","following_url":"https://api.github.com/users/palantir/following{/other_user}","gists_url":"https://api.github.com/users/palantir/gists{/gist_id}","starred_url":"https://api.github.com/users/palantir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/palantir/subscriptions","organizations_url":"https://api.github.com/users/palantir/orgs","repos_url":"https://api.github.com/users/palantir/repos","events_url":"https://api.github.com/users/palantir/events{/privacy}","received_events_url":"https://api.github.com/users/palantir/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/palantir/plottable","description":"A library of modular chart components, built on D3","fork":false,"url":"https://api.github.com/repos/palantir/plottable","forks_url":"https://api.github.com/repos/palantir/plottable/forks","keys_url":"https://api.github.com/repos/palantir/plottable/keys{/key_id}","collaborators_url":"https://api.github.com/repos/palantir/plottable/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/palantir/plottable/teams","hooks_url":"https://api.github.com/repos/palantir/plottable/hooks","issue_events_url":"https://api.github.com/repos/palantir/plottable/issues/events{/number}","events_url":"https://api.github.com/repos/palantir/plottable/events","assignees_url":"https://api.github.com/repos/palantir/plottable/assignees{/user}","branches_url":"https://api.github.com/repos/palantir/plottable/branches{/branch}","tags_url":"https://api.github.com/repos/palantir/plottable/tags","blobs_url":"https://api.github.com/repos/palantir/plottable/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/palantir/plottable/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/palantir/plottable/git/refs{/sha}","trees_url":"https://api.github.com/repos/palantir/plottable/git/trees{/sha}","statuses_url":"https://api.github.com/repos/palantir/plottable/statuses/{sha}","languages_url":"https://api.github.com/repos/palantir/plottable/languages","stargazers_url":"https://api.github.com/repos/palantir/plottable/stargazers","contributors_url":"https://api.github.com/repos/palantir/plottable/contributors","subscribers_url":"https://api.github.com/repos/palantir/plottable/subscribers","subscription_url":"https://api.github.com/repos/palantir/plottable/subscription","commits_url":"https://api.github.com/repos/palantir/plottable/commits{/sha}","git_commits_url":"https://api.github.com/repos/palantir/plottable/git/commits{/sha}","comments_url":"https://api.github.com/repos/palantir/plottable/comments{/number}","issue_comment_url":"https://api.github.com/repos/palantir/plottable/issues/comments{/number}","contents_url":"https://api.github.com/repos/palantir/plottable/contents/{+path}","compare_url":"https://api.github.com/repos/palantir/plottable/compare/{base}...{head}","merges_url":"https://api.github.com/repos/palantir/plottable/merges","archive_url":"https://api.github.com/repos/palantir/plottable/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/palantir/plottable/downloads","issues_url":"https://api.github.com/repos/palantir/plottable/issues{/number}","pulls_url":"https://api.github.com/repos/palantir/plottable/pulls{/number}","milestones_url":"https://api.github.com/repos/palantir/plottable/milestones{/number}","notifications_url":"https://api.github.com/repos/palantir/plottable/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/palantir/plottable/labels{/name}","releases_url":"https://api.github.com/repos/palantir/plottable/releases{/id}","created_at":"2014-01-22T19:29:19Z","updated_at":"2015-08-20T07:02:51Z","pushed_at":"2015-08-20T22:13:28Z","git_url":"git://github.com/palantir/plottable.git","ssh_url":"git@github.com:palantir/plottable.git","clone_url":"https://github.com/palantir/plottable.git","svn_url":"https://github.com/palantir/plottable","homepage":"plottablejs.org","size":133403,"stargazers_count":669,"watchers_count":669,"language":"TypeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":68,"mirror_url":null,"open_issues_count":176,"forks":68,"open_issues":176,"watchers":669,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/palantir/plottable/pulls/2653"},"html":{"href":"https://github.com/palantir/plottable/pull/2653"},"issue":{"href":"https://api.github.com/repos/palantir/plottable/issues/2653"},"comments":{"href":"https://api.github.com/repos/palantir/plottable/issues/2653/comments"},"review_comments":{"href":"https://api.github.com/repos/palantir/plottable/pulls/2653/comments"},"review_comment":{"href":"https://api.github.com/repos/palantir/plottable/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/palantir/plottable/pulls/2653/commits"},"statuses":{"href":"https://api.github.com/repos/palantir/plottable/statuses/edec0423bf30ba0d138f2aea73f3cb9fd5fd6c3c"}}}}