Skip to content

Commit

Permalink
test: Add headless render tests using JSDOM.
Browse files Browse the repository at this point in the history
  • Loading branch information
jheer committed Dec 14, 2024
1 parent 797a7c3 commit ae92551
Show file tree
Hide file tree
Showing 10 changed files with 546 additions and 0 deletions.
316 changes: 316 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"esbuild": "^0.24.0",
"eslint": "^9.17.0",
"eslint-plugin-jsdoc": "^50.6.1",
"jsdom": "^25.0.1",
"lerna": "^8.1.9",
"nodemon": "^3.1.9",
"rimraf": "^6.0.1",
Expand Down
11 changes: 11 additions & 0 deletions packages/vgplot/test/output/airline-travelers.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div class="plot" style="display: flex;"><svg class="plot-d6a7b5" fill="currentColor" font-family="system-ui, sans-serif" font-size="10" text-anchor="middle" width="640" height="400" viewBox="0 0 640 400"><style>:where(.plot-d6a7b5) {
--plot-background: white;
display: block;
height: auto;
height: intrinsic;
max-width: 100%;
}
:where(.plot-d6a7b5 text),
:where(.plot-d6a7b5 tspan) {
white-space: pre;
}</style><g aria-label="y-grid" aria-hidden="true" stroke="currentColor" stroke-opacity="0.1"><line x1="40" x2="620" y1="370" y2="370"></line><line x1="40" x2="620" y1="345.7190205052872" y2="345.7190205052872"></line><line x1="40" x2="620" y1="321.4380410105744" y2="321.4380410105744"></line><line x1="40" x2="620" y1="297.1570615158615" y2="297.1570615158615"></line><line x1="40" x2="620" y1="272.8760820211487" y2="272.8760820211487"></line><line x1="40" x2="620" y1="248.59510252643588" y2="248.59510252643588"></line><line x1="40" x2="620" y1="224.31412303172308" y2="224.31412303172308"></line><line x1="40" x2="620" y1="200.03314353701026" y2="200.03314353701026"></line><line x1="40" x2="620" y1="175.75216404229747" y2="175.75216404229747"></line><line x1="40" x2="620" y1="151.47118454758464" y2="151.47118454758464"></line><line x1="40" x2="620" y1="127.19020505287182" y2="127.19020505287182"></line><line x1="40" x2="620" y1="102.90922555815902" y2="102.90922555815902"></line><line x1="40" x2="620" y1="78.6282460634462" y2="78.6282460634462"></line><line x1="40" x2="620" y1="54.347266568733396" y2="54.347266568733396"></line><line x1="40" x2="620" y1="30.06628707402055" y2="30.06628707402055"></line></g><g aria-label="y-axis tick" aria-hidden="true" fill="none" stroke="currentColor"><path transform="translate(40,370)" d="M0,0L-6,0"></path><path transform="translate(40,345.7190205052872)" d="M0,0L-6,0"></path><path transform="translate(40,321.4380410105744)" d="M0,0L-6,0"></path><path transform="translate(40,297.1570615158615)" d="M0,0L-6,0"></path><path transform="translate(40,272.8760820211487)" d="M0,0L-6,0"></path><path transform="translate(40,248.59510252643588)" d="M0,0L-6,0"></path><path transform="translate(40,224.31412303172308)" d="M0,0L-6,0"></path><path transform="translate(40,200.03314353701026)" d="M0,0L-6,0"></path><path transform="translate(40,175.75216404229747)" d="M0,0L-6,0"></path><path transform="translate(40,151.47118454758464)" d="M0,0L-6,0"></path><path transform="translate(40,127.19020505287182)" d="M0,0L-6,0"></path><path transform="translate(40,102.90922555815902)" d="M0,0L-6,0"></path><path transform="translate(40,78.6282460634462)" d="M0,0L-6,0"></path><path transform="translate(40,54.347266568733396)" d="M0,0L-6,0"></path><path transform="translate(40,30.06628707402055)" d="M0,0L-6,0"></path></g><g aria-label="y-axis tick label" text-anchor="end" font-variant="tabular-nums" transform="translate(-9,0)"><text y="0.32em" transform="translate(40,370)">0.0M</text><text y="0.32em" transform="translate(40,345.7190205052872)">0.2M</text><text y="0.32em" transform="translate(40,321.4380410105744)">0.4M</text><text y="0.32em" transform="translate(40,297.1570615158615)">0.6M</text><text y="0.32em" transform="translate(40,272.8760820211487)">0.8M</text><text y="0.32em" transform="translate(40,248.59510252643588)">1.0M</text><text y="0.32em" transform="translate(40,224.31412303172308)">1.2M</text><text y="0.32em" transform="translate(40,200.03314353701026)">1.4M</text><text y="0.32em" transform="translate(40,175.75216404229747)">1.6M</text><text y="0.32em" transform="translate(40,151.47118454758464)">1.8M</text><text y="0.32em" transform="translate(40,127.19020505287182)">2.0M</text><text y="0.32em" transform="translate(40,102.90922555815902)">2.2M</text><text y="0.32em" transform="translate(40,78.6282460634462)">2.4M</text><text y="0.32em" transform="translate(40,54.347266568733396)">2.6M</text><text y="0.32em" transform="translate(40,30.06628707402055)">2.8M</text></g><g aria-label="y-axis label" text-anchor="start" transform="translate(-37,-17)"><text y="0.71em" transform="translate(40,20)">↑ Travelers per day</text></g><g aria-label="x-axis tick" aria-hidden="true" fill="none" stroke="currentColor"><path transform="translate(40,370)" d="M0,0L0,6"></path><path transform="translate(100.13377926421404,370)" d="M0,0L0,6"></path><path transform="translate(158.3277591973244,370)" d="M0,0L0,6"></path><path transform="translate(218.46153846153845,370)" d="M0,0L0,6"></path><path transform="translate(276.6555183946488,370)" d="M0,0L0,6"></path><path transform="translate(336.7892976588629,370)" d="M0,0L0,6"></path><path transform="translate(396.9230769230769,370)" d="M0,0L0,6"></path><path transform="translate(455.1170568561873,370)" d="M0,0L0,6"></path><path transform="translate(515.2508361204013,370)" d="M0,0L0,6"></path><path transform="translate(573.4448160535118,370)" d="M0,0L0,6"></path></g><g aria-label="x-axis tick label" font-variant="tabular-nums" transform="translate(0,9)"><text transform="translate(40,370)"><tspan x="0" y="0.71em">Mar</tspan><tspan x="0" dy="1em">2020</tspan></text><text y="0.71em" transform="translate(100.13377926421404,370)">Apr</text><text y="0.71em" transform="translate(158.3277591973244,370)">May</text><text y="0.71em" transform="translate(218.46153846153845,370)">Jun</text><text y="0.71em" transform="translate(276.6555183946488,370)">Jul</text><text y="0.71em" transform="translate(336.7892976588629,370)">Aug</text><text y="0.71em" transform="translate(396.9230769230769,370)">Sep</text><text y="0.71em" transform="translate(455.1170568561873,370)">Oct</text><text y="0.71em" transform="translate(515.2508361204013,370)">Nov</text><text y="0.71em" transform="translate(573.4448160535118,370)">Dec</text></g><g aria-label="x-axis label" text-anchor="end" transform="translate(17,27)"><text transform="translate(620,370)">date →</text></g><g aria-label="rule" stroke="currentColor" data-index="0"><line x1="40" x2="620" y1="370" y2="370"></line></g><g aria-label="line" fill="none" stroke="currentColor" stroke-width="1.5" stroke-opacity="0.35" stroke-linejoin="round" stroke-linecap="round" data-index="1"><path d="M40,90.594L41.94,95.877L43.88,129.672L45.819,109.754L47.759,78.301L49.699,61.184L51.639,108.219L53.579,68.257L55.518,81.217L57.458,112.27L59.398,104.451L61.338,66.011L63.278,50.193L65.217,93.845L67.157,60.934L69.097,70.651L71.037,105.589L72.977,88.233L74.916,64.881L76.856,59.288L78.796,99.609L80.736,61.311L82.676,74.456L84.615,108.747L86.555,93.948L88.495,68.046L90.435,61.828L92.375,106.197L94.314,65.238L96.254,83.478L98.194,124.003L100.134,108.782L102.074,77.232L104.013,69.294L105.953,125.768L107.893,70.988L109.833,80.56L111.773,116.136L113.712,99.355L115.652,68.018L117.592,55.501L119.532,120.01L121.472,72.946L123.411,68.36L125.351,101.854L127.291,88.659L129.231,52.386L131.171,71.692L133.11,128.622L135.05,83.873L136.99,55.055L138.93,99.574L140.87,96.328L142.809,63.215L144.749,63.829L146.689,128.348L148.629,65.661L150.569,77.078L152.508,114.799L154.448,96.057L156.388,66.553L158.328,60.9L160.268,131.041L162.207,64.958L164.147,70.012L166.087,114.249L168.027,94.331L169.967,59.769L171.906,54.028L173.846,128.897L175.786,76.308L177.726,64.993L179.666,103.955L181.605,85.466L183.545,52.972L185.485,46.511L187.425,116.128L189.365,51.886L191.304,52.442L193.244,89.224L195.184,69.872L197.124,45.408L199.064,30.956L201.003,112.036L202.943,118.605L204.883,65.002L206.823,72.115L208.763,94.528L210.702,68.215L212.642,57.915L214.582,112.964L216.522,59.74L218.462,66.609L220.401,97.152L222.341,82.252L224.281,51.44L226.221,48.3L228.161,99.759L230.1,45.866L232.04,48.886L233.98,74.599L235.92,65.388L237.86,45.159L239.799,38.824L241.739,88.469L243.679,49.238L245.619,42.258L247.559,70.546L249.498,60.127L251.438,38.712L253.378,33.356L255.318,81.231L257.258,39.822L259.197,40.212L261.137,65.697L263.077,54.995L265.017,40.844L266.957,38.502L268.896,82.41L270.836,50.459L272.776,71.886L274.716,84.97L276.656,60.674L278.595,116.414L280.535,104.821L282.475,85.203L284.415,30.629L286.355,36.292L288.294,65.655L290.234,64.557L292.174,53.351L294.114,40.166L296.054,89.29L297.993,45.883L299.933,52.512L301.873,72.901L303.813,63.748L305.753,40.164L307.692,32.863L309.632,79.058L311.572,38.886L313.512,50.06L315.452,66.553L317.391,58.971L319.331,41.551L321.271,38.228L323.211,82.887L325.151,42.119L327.09,52.727L329.03,73.897L330.97,61.344L332.91,37.001L334.849,38.451L336.789,82.517L338.729,43.586L340.669,51.991L342.609,80.193L344.548,74.975L346.488,41.237L348.428,39.172L350.368,91.942L352.308,48.532L354.247,58.234L356.187,89.94L358.127,79.611L360.067,54.05L362.007,51.001L363.946,106.313L365.886,56.236L367.826,57.144L369.766,97.149L371.706,89.939L373.645,62.459L375.585,59.295L377.525,122.427L379.465,67.318L381.405,83.726L383.344,125.358L385.284,104.283L387.224,59.069L389.164,47.238L391.104,132.665L393.043,140.806L394.983,93.42L396.923,122.607L398.863,140.661L400.803,113.853L402.742,103.052L404.682,156.873L406.622,82.27L408.562,91.62L410.502,134.064L412.441,126.478L414.381,72.643L416.321,68.427L418.261,141.78L420.201,68.293L422.14,77.92L424.08,125.606L426.02,109.361L427.96,71.901L429.9,57.756L431.839,134.669L433.779,64.324L435.719,74.818L437.659,123.124L439.599,104.337L441.538,65.161L443.478,60.708L445.418,131.29L447.358,72.243L449.298,82.414L451.237,127.314L453.177,117.213L455.117,72.839L457.057,63.23L458.997,136.759L460.936,61.374L462.876,78.61L464.816,122.865L466.756,101.06L468.696,53.705L470.635,43.66L472.575,118.119L474.515,59.77L476.455,52.311L478.395,89.114L480.334,88.612L482.274,56.653L484.214,49.774L486.154,121.138L488.094,53.587L490.033,64.706L491.973,111.816L493.913,97.422L495.853,61.44L497.793,55.035L499.732,135.449L501.672,69.124L503.612,85.061L505.552,138.055L507.492,119.115L509.431,121.374L511.371,88.352L513.311,147.006L515.251,71.402L517.191,78.227L519.13,126.571L521.07,109.237L523.01,65.594L524.95,61.103L526.89,138.262L528.829,83.928L530.769,70.689L532.709,108.979L534.649,118.424L536.589,82.887L538.528,74.111L540.468,150.593L542.408,79.031L544.348,90.908L546.288,139.222L548.227,118.494L550.167,75.217L552.107,60.362L554.047,103.602L555.987,88.153L557.926,96.331L559.866,74.358L561.806,51.403L563.746,176.826L565.686,131.059L567.625,48.487L569.565,20L571.505,55.383L573.445,93.148L575.385,120.588L577.324,95.276L579.264,93.415L581.204,156.837L583.144,91.73L585.084,99.717L587.023,139.689L588.963,124.703L590.903,83.204L592.843,80.082L594.783,140.075L596.722,90.739L598.662,96.792L600.602,126.084L602.542,98.736L604.482,69.959L606.421,53.365L608.361,67.946L610.301,64.133L612.241,67.641L614.181,129.444L616.12,134.81L618.06,60.151L620,56.462"></path></g><g aria-label="line" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" stroke-linecap="round" data-index="2"><path d="M40,93.133L41.94,116.307L43.88,159.193L45.819,142.074L47.759,111.406L49.699,103.089L51.639,146.031L53.579,112.638L55.518,138.194L57.458,173.662L59.398,163.286L61.338,152.873L63.278,161.867L65.217,189.647L67.157,185.563L69.097,217.294L71.037,254.216L72.977,275.349L74.916,294.622L76.856,297.987L78.796,303.454L80.736,314.82L82.676,329.763L84.615,336.126L86.555,340.956L88.495,345.251L90.435,345.762L92.375,347.658L94.314,348.147L96.254,351.294L98.194,352.233L100.134,353.486L102.074,354.943L104.013,354.246L105.953,355.638L107.893,355.185L109.833,356.851L111.773,358.208L113.712,358.475L115.652,357.363L117.592,356.77L119.532,358.631L121.472,359.012L123.411,357.594L125.351,359.373L127.291,358.978L129.231,358.456L131.171,357.084L133.11,358.195L135.05,357.206L136.99,357.939L138.93,358.726L140.87,357.985L142.809,356.448L144.749,355.011L146.689,356.104L148.629,354.354L150.569,355.449L152.508,356.535L154.448,355.476L156.388,351.219L158.328,349.171L160.268,353.7L162.207,349.33L164.147,350.127L166.087,354.144L168.027,352.954L169.967,346.828L171.906,343.844L173.846,349.412L175.786,345.62L177.726,343.82L179.666,350.186L181.605,348.552L183.545,341.479L185.485,339.592L187.425,346.528L189.365,339.187L191.304,340.356L193.244,346.875L195.184,342.032L197.124,331.339L199.064,327.669L201.003,339.261L202.943,337.53L204.883,328.629L206.823,337.847L208.763,338.293L210.702,330.935L212.642,330.284L214.582,337.358L216.522,327.151L218.462,327.112L220.401,337.495L222.341,333.04L224.281,322.424L226.221,319.049L228.161,327.142L230.1,316.429L232.04,317.746L233.98,328.919L235.92,323.02L237.86,309.029L239.799,306.954L241.739,316.932L243.679,303.95L245.619,305.106L247.559,319.262L249.498,316.36L251.438,300.008L253.378,298.625L255.318,308.432L257.258,298.316L259.197,296.242L261.137,312.767L263.077,309.926L265.017,294.289L266.957,293.153L268.896,303.675L270.836,293.052L272.776,294.093L274.716,309.291L276.656,293.938L278.595,277.154L280.535,282.711L282.475,313.344L284.415,281.117L286.355,278.272L288.294,292.087L290.234,293.212L292.174,283.845L294.114,283.666L296.054,290.324L297.993,278.395L299.933,285.261L301.873,304.409L303.813,298.458L305.753,284.268L307.692,282.543L309.632,291.493L311.572,279.259L313.512,285.584L315.452,305.604L317.391,300.684L319.331,284.432L321.271,282.009L323.211,291.205L325.151,278.8L327.09,285.011L329.03,304.835L330.97,300.411L332.91,282.794L334.849,276.844L336.789,283.92L338.729,272.893L340.669,280.496L342.609,304.004L344.548,297.674L346.488,279.723L348.428,277.423L350.368,287.055L352.308,269.017L354.247,277.506L356.187,302.084L358.127,298.28L360.067,277.511L362.007,274.85L363.946,286.243L365.886,265.234L367.826,276.115L369.766,301.291L371.706,298.77L373.645,276.229L375.585,277.19L377.525,294.022L379.465,267.801L381.405,281.764L383.344,306.483L385.284,304.436L387.224,282.46L389.164,280.297L391.104,298.161L393.043,271.942L394.983,283.66L396.923,307.347L398.863,299.812L400.803,263.443L402.742,252.398L404.682,289.309L406.622,286.276L408.562,256.449L410.502,284.522L412.441,295.103L414.381,278.333L416.321,281.21L418.261,295.493L420.201,271.68L422.14,281.428L424.08,306.58L426.02,299.847L427.96,274.728L429.9,271.393L431.839,292.474L433.779,267.053L435.719,276.526L437.659,303.259L439.599,296.098L441.538,269.681L443.478,269.68L445.418,289.952L447.358,264.009L449.298,273.155L451.237,300.958L453.177,293.024L455.117,266.089L457.057,265.933L458.997,287.729L460.936,260.625L462.876,270.832L464.816,298.278L466.756,288.839L468.696,256.254L470.635,252.414L472.575,276.534L474.515,250.509L476.455,253.641L478.395,287.336L480.334,282.839L482.274,254.662L484.214,251.867L486.154,274.243L488.094,244.77L490.033,258.182L491.973,289.571L493.913,285.727L495.853,256.561L497.793,253.641L499.732,278.304L501.672,250.569L503.612,260.889L505.552,291.267L507.492,289.028L509.431,263.936L511.371,261.62L513.311,294.914L515.251,256.354L517.191,267.275L519.13,300.092L521.07,292.722L523.01,264.729L524.95,261.332L526.89,286.237L528.829,251.871L530.769,268.433L532.709,297.585L534.649,288.096L536.589,264.781L538.528,262.972L540.468,285.337L542.408,251.23L544.348,262.78L546.288,295.761L548.227,284.636L550.167,259.845L552.107,246.187L554.047,250.493L555.987,242.776L557.926,258.629L559.866,259.268L561.806,239.979L563.746,301.904L565.686,270.4L567.625,252.889L569.565,227.217L571.505,250.791L573.445,275.27L575.385,293.229L577.324,280.397L579.264,278.467L581.204,293.584L583.144,268.367L585.084,284.586L587.023,309.114L588.963,301.482L590.903,278.423L592.843,274.395L594.783,289.584L596.722,264.983L598.662,278.649L600.602,302.982L602.542,292.062L604.482,267.178L606.421,240.492L608.361,239.664L610.301,240.75L612.241,254.085L614.181,249.546L616.12,225.392L618.06,267.228L620,295.158"></path></g><g aria-label="text" fill-opacity="0.5" transform="translate(0,-6)" data-index="3"><text transform="translate(620,56.46213988272287)">2019</text></g><g aria-label="text" transform="translate(0,6)" data-index="4"><text y="0.71em" transform="translate(620,295.1576442593694)">2020</text></g></svg></div>
21 changes: 21 additions & 0 deletions packages/vgplot/test/output/density1d.html

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions packages/vgplot/test/render.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { beforeEach, afterEach, expect, describe, it } from 'vitest';
import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { Coordinator } from '@uwdata/mosaic-core';
import { JSDOM } from 'jsdom';
import { nodeConnector } from './util/node-connector.js';
import { createAPIContext } from '../src/index.js';
import { mosaicReady } from './util/mosaic-ready.js';

const cwd = import.meta.dirname;

beforeEach(() => {
const dom = new JSDOM(
`<!DOCTYPE html><body></body>`,
{ pretendToBeVisual: true }
);

// emulate browser environment globals
globalThis.window = dom.window;
globalThis.document = dom.window.document;
globalThis.requestAnimationFrame = window.requestAnimationFrame;
});

afterEach(() => {
// remove browser environment globals
delete globalThis.window;
delete globalThis.document;
delete globalThis.requestAnimationFrame;
});

describe('render', () => {
it('should render the density1d spec', () => {
return renderTest('density1d');
});
it('should render the airline-travelers spec', () => {
return renderTest('airline-travelers');
});
});

async function renderTest(name) {
const specPath = resolve(cwd, `specs/${name}.js`);
const htmlPath = resolve(cwd, `output/${name}.html`);
const expected = await readFile(htmlPath, { encoding: 'utf8'});
const run = (await import(specPath)).default;
const el = await run(vg());
await mosaicReady(el);
expect(el.outerHTML).toEqual(expected);
}

function vg() {
return createAPIContext({
coordinator: new Coordinator(nodeConnector(), { logger: null })
});
}
38 changes: 38 additions & 0 deletions packages/vgplot/test/specs/airline-travelers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { dataPath } from '../util/data-path.js';

export default async function(vg) {
await vg.context.coordinator.exec([
vg.loadParquet("travelers", dataPath("travelers.parquet")),
`CREATE TABLE IF NOT EXISTS endpoint AS SELECT * FROM travelers ORDER BY date DESC LIMIT 1`
]);

return vg.plot(
vg.ruleY([0]),
vg.lineY(
vg.from("travelers"),
{x: "date", y: "previous", strokeOpacity: 0.35}
),
vg.lineY(
vg.from("travelers"),
{x: "date", y: "current"}
),
vg.text(
vg.from("endpoint"),
{
x: "date",
y: "previous",
text: ["2019"],
fillOpacity: 0.5,
lineAnchor: "bottom",
dy: -6
}
),
vg.text(
vg.from("endpoint"),
{x: "date", y: "current", text: ["2020"], lineAnchor: "top", dy: 6}
),
vg.yGrid(true),
vg.yLabel("↑ Travelers per day"),
vg.yTickFormat("s")
);
}
39 changes: 39 additions & 0 deletions packages/vgplot/test/specs/density1d.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { dataPath } from '../util/data-path.js';

export default async function(vg) {
await vg.context.coordinator.exec([
vg.loadParquet("flights", dataPath("flights-200k.parquet"))
]);

const $brush = vg.Selection.crossfilter();
const $bandwidth = vg.Param.value(20);

return vg.vconcat(
vg.slider({label: "Bandwidth (σ)", as: $bandwidth, min: 0.1, max: 100, step: 0.1}),
vg.plot(
vg.densityY(
vg.from("flights", {filterBy: $brush}),
{x: "delay", fill: "#888", fillOpacity: 0.5, bandwidth: $bandwidth}
),
vg.intervalX({as: $brush}),
vg.yAxis(null),
vg.xDomain(vg.Fixed),
vg.width(600),
vg.marginLeft(10),
vg.height(200)
),
vg.plot(
vg.densityY(
vg.from("flights", {filterBy: $brush}),
{x: "distance", fill: "#888", fillOpacity: 0.5, bandwidth: $bandwidth}
),
vg.intervalX({as: $brush}),
vg.yAxis(null),
vg.xScale("log"),
vg.xDomain(vg.Fixed),
vg.width(600),
vg.marginLeft(10),
vg.height(200)
)
);
}
7 changes: 7 additions & 0 deletions packages/vgplot/test/util/data-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { resolve } from 'node:path';

const root = resolve(import.meta.dirname, '../../../../data/');

export function dataPath(file) {
return resolve(root, file);
}
Loading

0 comments on commit ae92551

Please sign in to comment.