Unit Testing with Jest fails when testing @observablehq/runtime cells with library dependencies

Hi all,

I was conversing on this topic with @mootari in the Observable ambassadors slack channel but thought I would move to the proper channel of community. This topic should be of interest to those trying to use observable runtime for software development.

I have been using observable runtime in several code repositories and started trying to implement unit testing in those recently with Jest. I have been installing my notebooks as npm modules in my code repositories and needed to implement unit testing as the developed applications moved closer to launch.

I was able to install and configure Jest to successfully test some cells in notebooks, but noticed that when I try to test a cell that contains code referencing a dependency library of @observablehq/stdlib like d3 or plot, the tests always time out.

As an example, in this notebook, when I try and test the value returned by the cell d3_test using the below test, the test times out, it doesn’t matter if I increase the time to 30 seconds, 60 seconds, etc:

import assert from "assert"; import { Runtime, Inspector } from "@observablehq/runtime"; 
import notebook from "5ef68b6d8020c0c7"; 

it('observable-dependency-library-cell', async () => { 
const runtime = new Runtime(); const main = runtime.module(notebook); 
const test = await main.value("d3_test");  //cell code d3_test = d3.utcFormat("%Y")(new Date);
assert.deepStrictEqual(test, "2024"); 
});

To help debug, I have created this simple github repository: GitHub - mishatsvelik/observable-jest-playground, if you download and install it locally, then run npm test in your CLI you will get details of the passing and failing tests (the test above is contained in the file observable-notebook.test.ts).

Thanks,
Misha

Not had time to properly look but I did noticed that if you import the runtime like this you can step debug

import {
  Runtime,
  Inspector,
} from "../node_modules/@observablehq/runtime/src/index.js";

Builtins are loaded as UMD modules via d3-require, which works by adding a script element to the DOM and executing it implicitly.

jsdom won’t load resources by default unless you tell it to (see docs). Add the following to your jest.config.js:

  testEnvironmentOptions: {
    resources: "usable",
  },  

Note that your test “observable-plot-dependency-cell” checks the baseURI which defaults to http://localhost in jsdom. If you want to mock it for individual tests you may have to instantiate jsdom directly.

1 Like

Awesome @mootari - works now, I have updated the repo - for anyway who may want to use it to get going with unit testing. GitHub - mishatsvelik/observable-jest-playground