Functional Weave
Code in Rust

charts.scale@1.1.0

vectors.json

13,419 bytes · view raw

[
  {"fn": "linearScale", "name": "a quarter of the way along a 500 pixel axis", "args": [[0, 100], [0, 500], 25, false], "expect": 125},
  {"fn": "linearScale", "name": "the start of the domain is the start of the range", "args": [[0, 100], [0, 500], 0, false], "expect": 0},
  {"fn": "linearScale", "name": "the end of the domain is the end of the range", "args": [[0, 100], [0, 500], 100, false], "expect": 500},
  {"fn": "linearScale", "name": "a reversed range, as a y axis drawn downwards", "args": [[0, 50], [300, 0], 10, false], "expect": 240},
  {"fn": "linearScale", "name": "a reversed domain", "args": [[100, 0], [0, 1], 75, false], "expect": 0.25},
  {"fn": "linearScale", "name": "negative values", "args": [[-20, 40], [0, 600], -5, false], "expect": 150},
  {"fn": "linearScale", "name": "past the end runs on without clamp", "args": [[0, 10], [0, 100], 15, false], "expect": 150},
  {"fn": "linearScale", "name": "past the end stops at the range with clamp", "args": [[0, 10], [0, 100], 15, true], "expect": 100},
  {"fn": "linearScale", "name": "before the start stops at the range with clamp", "args": [[0, 10], [100, 200], -3, true], "expect": 100},
  {"fn": "linearScale", "name": "clamp changes nothing inside the domain", "args": [[0, 10], [0, 100], 2.5, true], "expect": 25},
  {"fn": "linearScale", "name": "a third is rounded to 6 decimal places", "args": [[0, 3], [0, 1], 1, false], "expect": 0.333333},
  {"fn": "linearScale", "name": "fractional domain", "args": [[0.1, 0.3], [0, 10], 0.2, false], "expect": 5},
  {"fn": "linearScale", "name": "a domain with no width is an error", "args": [[5, 5], [0, 100], 5, false], "expectError": "domain has no width"},
  {"fn": "linearScale", "name": "a domain needs two ends", "args": [[0, 1, 2], [0, 100], 1, false], "expectError": "domain must have exactly 2 values, [from, to]"},
  {"fn": "invertLinear", "name": "a pixel back to its value", "args": [[0, 100], [0, 500], 125], "expect": 25},
  {"fn": "invertLinear", "name": "the start of the range is the start of the domain", "args": [[0, 100], [0, 500], 0], "expect": 0},
  {"fn": "invertLinear", "name": "a reversed range", "args": [[0, 50], [300, 0], 240], "expect": 10},
  {"fn": "invertLinear", "name": "past the end of the axis is past the end of the data", "args": [[0, 10], [0, 100], 150], "expect": 15},
  {"fn": "invertLinear", "name": "a third is rounded to 6 decimal places", "args": [[0, 1], [0, 3], 1], "expect": 0.333333},
  {"fn": "invertLinear", "name": "negative domain", "args": [[-20, 40], [0, 600], 150], "expect": -5},
  {"fn": "invertLinear", "name": "a range with no width is an error", "args": [[0, 10], [7, 7], 7], "expectError": "range has no width"},
  {"fn": "invertLinear", "name": "a range needs two ends", "args": [[0, 10], [7], 7], "expectError": "range must have exactly 2 values, [from, to]"},
  {"fn": "niceDomain", "name": "widens to whole tens", "args": [[3, 97], 10], "expect": {"domain": [0, 100], "step": 10}},
  {"fn": "niceDomain", "name": "small numbers widen to tenths", "args": [[0.13, 0.87], 10], "expect": {"domain": [0.1, 0.9], "step": 0.1}},
  {"fn": "niceDomain", "name": "a messy extent becomes 0 to 10", "args": [[0.13, 9.7], 5], "expect": {"domain": [0, 10], "step": 2}},
  {"fn": "niceDomain", "name": "an already nice domain is unchanged", "args": [[0, 100], 10], "expect": {"domain": [0, 100], "step": 10}},
  {"fn": "niceDomain", "name": "negative to positive", "args": [[-12.5, 37.2], 5], "expect": {"domain": [-20, 40], "step": 10}},
  {"fn": "niceDomain", "name": "a reversed domain stays reversed", "args": [[97, 3], 10], "expect": {"domain": [100, 0], "step": 10}},
  {"fn": "niceDomain", "name": "large values step in fives of a power of ten", "args": [[1234, 98765], 20], "expect": {"domain": [0, 100000], "step": 5000}},
  {"fn": "niceDomain", "name": "one tick", "args": [[2, 9], 1], "expect": {"domain": [0, 10], "step": 10}},
  {"fn": "niceDomain", "name": "a fractional step that divides badly", "args": [[0.3, 0.9], 6], "expect": {"domain": [0.3, 0.9], "step": 0.1}},
  {"fn": "niceDomain", "name": "equal ends are returned as they are", "args": [[4, 4], 10], "expect": {"domain": [4, 4], "step": 0}},
  {"fn": "niceDomain", "name": "count must be at least 1", "args": [[0, 10], 0], "expectError": "count must be a whole number of at least 1"},
  {"fn": "niceDomain", "name": "a domain needs two ends", "args": [[1], 5], "expectError": "domain must have exactly 2 values, [from, to]"},
  {"fn": "logScale", "name": "a decade is a third of three decades", "args": [[1, 1000], [0, 300], 10, false], "expect": 100},
  {"fn": "logScale", "name": "two decades", "args": [[1, 1000], [0, 300], 100, false], "expect": 200},
  {"fn": "logScale", "name": "the start of the domain", "args": [[1, 100], [0, 1], 1, false], "expect": 0},
  {"fn": "logScale", "name": "the end of the domain", "args": [[1, 100], [0, 1], 100, false], "expect": 1},
  {"fn": "logScale", "name": "a reversed range, as a y axis", "args": [[10, 1000], [500, 0], 100, false], "expect": 250},
  {"fn": "logScale", "name": "2 sits at log10(2) of a decade, not a ninth of it as a linear scale would put it", "args": [[1, 10], [0, 100], 2, false], "expect": 30.103},
  {"fn": "logScale", "name": "past the end runs on without clamp", "args": [[1, 10], [0, 100], 100, false], "expect": 200},
  {"fn": "logScale", "name": "past the end stops at the range with clamp", "args": [[1, 10], [0, 100], 100, true], "expect": 100},
  {"fn": "logScale", "name": "before the start runs on without clamp", "args": [[1, 10], [0, 100], 0.1, false], "expect": -100},
  {"fn": "logScale", "name": "before the start stops with clamp", "args": [[1, 10], [0, 100], 0.1, true], "expect": 0},
  {"fn": "logScale", "name": "a reversed domain", "args": [[1000, 1], [0, 300], 10, false], "expect": 200},
  {"fn": "logScale", "name": "a domain below one", "args": [[0.01, 1], [0, 200], 0.1, false], "expect": 100},
  {"fn": "logScale", "name": "a domain end of zero is an error", "args": [[0, 10], [0, 100], 1, false], "expectError": "log scale domain must be positive"},
  {"fn": "logScale", "name": "a negative domain end is an error", "args": [[-1, 10], [0, 100], 1, false], "expectError": "log scale domain must be positive"},
  {"fn": "logScale", "name": "a value of zero is an error", "args": [[1, 10], [0, 100], 0, false], "expectError": "value must be positive for a log scale"},
  {"fn": "logScale", "name": "a domain with no width is an error", "args": [[5, 5], [0, 100], 5, false], "expectError": "domain has no width"},
  {"fn": "logScale", "name": "a domain needs two ends", "args": [[1, 10, 100], [0, 100], 5, false], "expectError": "domain must have exactly 2 values, [from, to]"},
  {"fn": "timeScale", "name": "the middle of January", "args": [["2026-01-01", "2026-01-31"], [0, 300], "2026-01-16", false], "expect": 150},
  {"fn": "timeScale", "name": "the first day is the start of the range", "args": [["2026-01-01", "2026-01-31"], [0, 300], "2026-01-01", false], "expect": 0},
  {"fn": "timeScale", "name": "the last day is the end of the range", "args": [["2026-01-01", "2026-01-31"], [0, 300], "2026-01-31", false], "expect": 300},
  {"fn": "timeScale", "name": "a leap February has 29 days", "args": [["2024-02-01", "2024-03-01"], [0, 29], "2024-02-29", false], "expect": 28},
  {"fn": "timeScale", "name": "a clock change is still one day (no time zone involved)", "args": [["2026-03-28", "2026-03-30"], [0, 100], "2026-03-29", false], "expect": 50},
  {"fn": "timeScale", "name": "a reversed range over a year", "args": [["2026-01-01", "2027-01-01"], [365, 0], "2026-07-02", false], "expect": 183},
  {"fn": "timeScale", "name": "a third of a three-day domain is rounded to 6 places", "args": [["2026-01-01", "2026-01-04"], [0, 1], "2026-01-02", false], "expect": 0.333333},
  {"fn": "timeScale", "name": "after the end runs on without clamp", "args": [["2026-01-01", "2026-01-11"], [0, 100], "2026-01-21", false], "expect": 200},
  {"fn": "timeScale", "name": "after the end stops with clamp", "args": [["2026-01-01", "2026-01-11"], [0, 100], "2026-01-21", true], "expect": 100},
  {"fn": "timeScale", "name": "before the start runs on without clamp", "args": [["2026-01-01", "2026-01-11"], [0, 100], "2025-12-22", false], "expect": -100},
  {"fn": "timeScale", "name": "before the start stops with clamp", "args": [["2026-01-01", "2026-01-11"], [0, 100], "2025-12-22", true], "expect": 0},
  {"fn": "timeScale", "name": "a reversed domain", "args": [["2026-01-11", "2026-01-01"], [0, 100], "2026-01-03", false], "expect": 80},
  {"fn": "timeScale", "name": "a domain of one day has no width", "args": [["2026-01-01", "2026-01-01"], [0, 100], "2026-01-01", false], "expectError": "domain has no width"},
  {"fn": "timeScale", "name": "an impossible date is an error", "args": [["2026-01-01", "2026-03-01"], [0, 100], "2026-02-30", false], "expectError": "is not a real calendar date"},
  {"fn": "timeScale", "name": "a domain needs two ends", "args": [["2026-01-01"], [0, 100], "2026-01-01", false], "expectError": "domain must have exactly 2 values, [from, to]"},
  {"fn": "bandScale", "name": "three bands with no padding", "args": [["a", "b", "c"], [0, 300], "b", 0, 0, 0.5], "expect": {"start": 100, "center": 150, "width": 100}},
  {"fn": "bandScale", "name": "padding: the first band", "args": [["a", "b", "c", "d"], [0, 100], "a", 0.2, 0.1, 0.5], "expect": {"start": 2.5, "center": 12.5, "width": 20}},
  {"fn": "bandScale", "name": "padding: the last band", "args": [["a", "b", "c", "d"], [0, 100], "d", 0.2, 0.1, 0.5], "expect": {"start": 77.5, "center": 87.5, "width": 20}},
  {"fn": "bandScale", "name": "align 0 puts the outer space at the end", "args": [["a", "b", "c", "d"], [0, 100], "a", 0.2, 0.1, 0], "expect": {"start": 0, "center": 10, "width": 20}},
  {"fn": "bandScale", "name": "align 1 puts the outer space at the start", "args": [["a", "b", "c", "d"], [0, 100], "d", 0.2, 0.1, 1], "expect": {"start": 80, "center": 90, "width": 20}},
  {"fn": "bandScale", "name": "a reversed range reverses the order, not the band", "args": [["a", "b", "c", "d"], [100, 0], "a", 0.2, 0.1, 0.5], "expect": {"start": 77.5, "center": 87.5, "width": 20}},
  {"fn": "bandScale", "name": "one category", "args": [["x"], [0, 50], "x", 0.5, 0, 0.5], "expect": {"start": 12.5, "center": 25, "width": 25}},
  {"fn": "bandScale", "name": "inner padding 1 leaves bands of no width", "args": [["a", "b"], [0, 10], "b", 1, 0, 0.5], "expect": {"start": 10, "center": 10, "width": 0}},
  {"fn": "bandScale", "name": "thirds are rounded to 6 places", "args": [["a", "b", "c"], [0, 100], "b", 0, 0, 0.5], "expect": {"start": 33.333333, "center": 50, "width": 33.333333}},
  {"fn": "bandScale", "name": "a range through zero", "args": [["a", "b"], [-50, 50], "a", 0, 0.5, 0.5], "expect": {"start": -33.333333, "center": -16.666667, "width": 33.333333}},
  {"fn": "bandScale", "name": "a value outside the domain is an error", "args": [["a", "b"], [0, 10], "z", 0, 0, 0.5], "expectError": "value is not in the domain: \"z\""},
  {"fn": "bandScale", "name": "a repeated category is an error", "args": [["a", "b", "a"], [0, 10], "a", 0, 0, 0.5], "expectError": "domain has a repeated value: \"a\""},
  {"fn": "bandScale", "name": "an empty domain is an error", "args": [[], [0, 10], "a", 0, 0, 0.5], "expectError": "domain must not be empty"},
  {"fn": "bandScale", "name": "inner padding above 1 is an error", "args": [["a"], [0, 10], "a", 1.5, 0, 0.5], "expectError": "paddingInner must be between 0 and 1"},
  {"fn": "bandScale", "name": "negative outer padding is an error", "args": [["a"], [0, 10], "a", 0, -1, 0.5], "expectError": "paddingOuter must be 0 or more"},
  {"fn": "bandScale", "name": "align above 1 is an error", "args": [["a"], [0, 10], "a", 0, 0, 2], "expectError": "align must be between 0 and 1"},
  {"fn": "pointScale", "name": "the middle of three points", "args": [["a", "b", "c"], [0, 100], "b", 0, 0.5], "expect": 50},
  {"fn": "pointScale", "name": "the first point sits on the start with no padding", "args": [["a", "b", "c"], [0, 100], "a", 0, 0.5], "expect": 0},
  {"fn": "pointScale", "name": "the last point sits on the end with no padding", "args": [["a", "b", "c"], [0, 100], "c", 0, 0.5], "expect": 100},
  {"fn": "pointScale", "name": "half a step of padding at each end", "args": [["a", "b", "c"], [0, 100], "a", 0.5, 0.5], "expect": 16.666667},
  {"fn": "pointScale", "name": "half a step of padding, the last point", "args": [["a", "b", "c"], [0, 100], "c", 0.5, 0.5], "expect": 83.333333},
  {"fn": "pointScale", "name": "a single point is centred", "args": [["x"], [0, 80], "x", 0, 0.5], "expect": 40},
  {"fn": "pointScale", "name": "a reversed range", "args": [["a", "b", "c"], [100, 0], "a", 0, 0.5], "expect": 100},
  {"fn": "pointScale", "name": "align 0 pushes the padding to the end", "args": [["a", "b"], [0, 100], "b", 1, 0], "expect": 33.333333},
  {"fn": "pointScale", "name": "a value outside the domain is an error", "args": [["a", "b"], [0, 100], "q", 0, 0.5], "expectError": "value is not in the domain: \"q\""},
  {"fn": "pointScale", "name": "negative padding is an error", "args": [["a", "b"], [0, 100], "a", -1, 0.5], "expectError": "padding must be 0 or more"},
  {"fn": "pointScale", "name": "align below 0 is an error", "args": [["a", "b"], [0, 100], "a", 0, -0.1], "expectError": "align must be between 0 and 1"}
]