|
| 1 | +import * as Plot from "@observablehq/plot"; |
| 2 | +import tape from "tape-await"; |
| 3 | +import {JSDOM} from "jsdom"; |
| 4 | +const {window} = new JSDOM(""); |
| 5 | +global.document = window.document; |
| 6 | + |
| 7 | +tape("plot(…).scales() exposes the plot’s scales", test => { |
| 8 | + const plot = Plot.dot([1, 2], {x: d => d, y: d => d}).plot(); |
| 9 | + test.equal(typeof plot.scales, "function"); |
| 10 | + const scales = plot.scales(); |
| 11 | + test.equal(Object.entries(scales).length, 2); |
| 12 | + test.assert("x" in scales); |
| 13 | + test.assert("y" in scales); |
| 14 | +}); |
| 15 | + |
| 16 | +tape("plot(…).scales('x') exposes the plot’s x scale", test => { |
| 17 | + const x = Plot.dot([1, 2], {x: d => d}).plot().scales('x'); |
| 18 | + test.deepEqual(x.domain, [1, 2]); |
| 19 | + test.deepEqual(x.range, [20, 620]); |
| 20 | + test.equal(typeof x.interpolate, "function"); |
| 21 | + test.equal(x.type, "linear"); |
| 22 | + test.equal(x.clamp, undefined); |
| 23 | + test.equal(typeof x.scale, "function"); |
| 24 | +}); |
| 25 | + |
| 26 | +tape("plot(…).scales('y') exposes the plot’s y scale", test => { |
| 27 | + const y0 = Plot.dot([1, 2], {x: d => d}).plot().scales('y'); |
| 28 | + test.equal(y0, undefined); |
| 29 | + const y = Plot.dot([1, 2], {y: d => d}).plot().scales('y'); |
| 30 | + test.deepEqual(y.domain, [1, 2]); |
| 31 | + test.deepEqual(y.range, [380, 20]); |
| 32 | + test.equal(typeof y.interpolate, "function"); |
| 33 | + test.equal(y.type, "linear"); |
| 34 | + test.equal(y.clamp, undefined); |
| 35 | + test.equal(typeof y.scale, "function"); |
| 36 | +}); |
| 37 | + |
| 38 | +tape("plot(…).scales('fx') exposes the plot’s fx scale", test => { |
| 39 | + const fx0 = Plot.dot([1, 2], {x: d => d}).plot().scales('fx'); |
| 40 | + test.equal(fx0, undefined); |
| 41 | + const data = [1, 2]; |
| 42 | + const fx = Plot.dot(data, {y: d => d}).plot({facet: {data, x: data}}).scales('fx'); |
| 43 | + test.deepEqual(fx.domain, [1, 2]); |
| 44 | + test.deepEqual(fx.range, [40, 620]); |
| 45 | + test.equal(typeof fx.interpolate, "undefined"); |
| 46 | + test.equal(fx.type, "band"); |
| 47 | + test.equal(fx.clamp, undefined); |
| 48 | + test.equal(typeof fx.scale, "function"); |
| 49 | +}); |
| 50 | + |
| 51 | +tape("plot(…).scales('fy') exposes the plot’s fy scale", test => { |
| 52 | + const fy0 = Plot.dot([1, 2], {x: d => d}).plot().scales('fy'); |
| 53 | + test.equal(fy0, undefined); |
| 54 | + const data = [1, 2]; |
| 55 | + const fy = Plot.dot(data, {y: d => d}).plot({facet: {data, y: data}}).scales('fy'); |
| 56 | + test.deepEqual(fy.domain, [1, 2]); |
| 57 | + test.deepEqual(fy.range, [20, 380]); |
| 58 | + test.equal(typeof fy.interpolate, "undefined"); |
| 59 | + test.equal(fy.type, "band"); |
| 60 | + test.equal(fy.clamp, undefined); |
| 61 | + test.equal(typeof fy.scale, "function"); |
| 62 | +}); |
| 63 | + |
| 64 | +tape("plot(…).scales('color') exposes a continuous color scale", test => { |
| 65 | + const color0 = Plot.dot([1, 2], {x: d => d}).plot().scales('color'); |
| 66 | + test.equal(color0, undefined); |
| 67 | + const data = [1, 2, 3, 4, 5]; |
| 68 | + const color = Plot.dot(data, {y: d => d, fill: d => d}).plot().scales('color'); |
| 69 | + test.deepEqual(color.domain, [1, 5]); |
| 70 | + test.deepEqual(color.range, [0, 1]); |
| 71 | + test.equal(typeof color.interpolate, "function"); |
| 72 | + test.equal(color.type, "linear"); |
| 73 | + test.equal(color.clamp, undefined); |
| 74 | + test.equal(typeof color.scale, "function"); |
| 75 | +}); |
| 76 | + |
| 77 | +tape("plot(…).scales('color') exposes an ordinal color scale", test => { |
| 78 | + const data = ["a", "b", "c", "d"]; |
| 79 | + const color = Plot.dot(data, {y: d => d, fill: d => d}).plot().scales('color'); |
| 80 | + test.deepEqual(color.domain, data); |
| 81 | + test.deepEqual(color.range, ['#4e79a7', '#f28e2c', '#e15759', '#76b7b2', '#59a14f', '#edc949', '#af7aa1', '#ff9da7', '#9c755f', '#bab0ab']); |
| 82 | + test.equal(typeof color.interpolate, "undefined"); |
| 83 | + test.equal(color.type, "ordinal"); |
| 84 | + test.equal(color.clamp, undefined); |
| 85 | + test.equal(typeof color.scale, "function"); |
| 86 | +}); |
| 87 | + |
| 88 | +tape("plot(…).scales('r') exposes a radius scale", test => { |
| 89 | + const r0 = Plot.dot([1, 2], {x: d => d}).plot().scales('r'); |
| 90 | + test.equal(r0, undefined); |
| 91 | + const data = [1, 2, 3, 4, 9]; |
| 92 | + const r = Plot.dot(data, {r: d => d}).plot().scales('r'); |
| 93 | + test.deepEqual(r.domain, [0, 9]); |
| 94 | + test.deepEqual(r.range, [0, Math.sqrt(40.5)]); |
| 95 | + test.equal(typeof r.interpolate, "function"); |
| 96 | + test.equal(r.type, "sqrt"); |
| 97 | + test.equal(r.clamp, undefined); |
| 98 | + test.equal(typeof r.scale, "function"); |
| 99 | +}); |
| 100 | + |
| 101 | +tape("plot(…).scales('opacity') exposes a linear scale", test => { |
| 102 | + const opacity0 = Plot.dot([1, 2], {x: d => d}).plot().scales('opacity'); |
| 103 | + test.equal(opacity0, undefined); |
| 104 | + const data = [1, 2, 3, 4, 9]; |
| 105 | + const opacity = Plot.dot(data, {fillOpacity: d => d}).plot().scales('opacity'); |
| 106 | + test.deepEqual(opacity.domain, [0, 9]); |
| 107 | + test.deepEqual(opacity.range, [0, 1]); |
| 108 | + test.equal(typeof opacity.interpolate, "function"); |
| 109 | + test.equal(opacity.type, "linear"); |
| 110 | + test.equal(opacity.clamp, undefined); |
| 111 | + test.equal(typeof opacity.scale, "function"); |
| 112 | +}); |
| 113 | + |
| 114 | +tape("plot(…).scales expose inset domain", test => { |
| 115 | + test.deepEqual(scaleOpt({inset: null}).range, [20, 620]); |
| 116 | + test.deepEqual(scaleOpt({inset: 7}).range, [27, 613]); |
| 117 | +}); |
| 118 | + |
| 119 | +tape("plot(…).scales expose clamp", test => { |
| 120 | + test.equal(scaleOpt({clamp: false}).clamp, undefined); |
| 121 | + test.equal(scaleOpt({clamp: true}).clamp, true); |
| 122 | +}); |
| 123 | + |
| 124 | +tape("plot(…).scales expose rounded scales", test => { |
| 125 | + test.equal(scaleOpt({round: false}).scale(Math.SQRT2), 144.26406871192853); |
| 126 | + test.equal(scaleOpt({round: true}).scale(Math.SQRT2), 144); |
| 127 | + test.equal(scaleOpt({round: true}).interpolate(0, 100)(Math.SQRT1_2), 71); |
| 128 | +}); |
| 129 | + |
| 130 | +tape("plot(…).scales expose label", test => { |
| 131 | + test.equal(scaleOpt({}).label, "x →"); |
| 132 | + test.equal(scaleOpt({label: "value"}).label, "value"); |
| 133 | +}); |
| 134 | + |
| 135 | +tape("plot(…).scales expose color label", test => { |
| 136 | + const x = Plot.dot([{x: 1}, {x: 2}, {x: 3}], {fill: "x"}).plot().scales("color"); |
| 137 | + test.equal(x.label, "x"); |
| 138 | + const y = Plot.dot([{x: 1}, {x: 2}, {x: 3}], {fill: "x"}).plot({color: {label: "y"}}).scales("color"); |
| 139 | + test.equal(y.label, "y"); |
| 140 | +}); |
| 141 | + |
| 142 | +tape("plot(…).scales expose radius label", test => { |
| 143 | + const x = Plot.dot([{x: 1}, {x: 2}, {x: 3}], {r: "x"}).plot().scales("r"); |
| 144 | + test.equal(x.label, "x"); |
| 145 | + const r = Plot.dot([{x: 1}, {x: 2}, {x: 3}], {r: "x"}).plot({color: {label: "radius"}}).scales("color"); |
| 146 | + test.equal(r.label, "radius"); |
| 147 | +}); |
| 148 | + |
| 149 | +function scaleOpt(x) { |
| 150 | + return Plot.dot([{x: 1}, {x: 2}, {x: 3}], {x: "x"}).plot({x}).scales("x"); |
| 151 | +} |
0 commit comments