elm-explorations / test

Write unit and fuzz tests for Elm code.
https://package.elm-lang.org/packages/elm-explorations/test/latest
BSD 3-Clause "New" or "Revised" License
236 stars 40 forks source link

WebGL canvas not included in Test.Html tests #210

Open MartinSStewart opened 1 year ago

MartinSStewart commented 1 year ago

If I write a test that expects for a canvas tag to be present, it will fail if the canvas tag was created with WebGL.toHtml (it will pass if the canvas was created with Html.canvas)

SSCCE: https://ellie-app.com/kfR9HFsqPQDa1

lydell commented 1 year ago

Random notes:

WebGL.toHtml indirectly calls Elm.Kernel.WebGL.toHtml: https://github.com/elm-explorations/webgl/blob/cb1a95d002ff89361170c6a60695bafc734ebd65/src/WebGL.elm#L287-L300

Elm.Kernel.WebGL.toHtml is a “custom” vdom node instead of a regular “node” vdom node: https://github.com/elm-explorations/webgl/blob/cb1a95d002ff89361170c6a60695bafc734ebd65/src/Elm/Kernel/WebGL.js#L711-L722

It uses _WebGL_render for rendering: https://github.com/elm-explorations/webgl/blob/cb1a95d002ff89361170c6a60695bafc734ebd65/src/Elm/Kernel/WebGL.js#L772

Which creates an actual canvas DOM node and access its webgl context: https://github.com/elm-explorations/webgl/blob/cb1a95d002ff89361170c6a60695bafc734ebd65/src/Elm/Kernel/WebGL.js#L789-L795

Which is not pure and requires a DOM implementation, which no runner has, and does not want.

Random guess: It’s not possible to fix this in elm-explorations/test.

MartinSStewart commented 1 year ago

Maybe this is something that should be addressed in elm-explorations/webgl then? In other words, perhaps the implementation could be modified to be more test friendly?

Edit: Fixed typo, had written elm-explorations/test instead of webgl 🤦‍♂️

w0rm commented 1 year ago

Here elm-explorations/test converts Elm Virtual DOM nodes to JSON, I'm pretty sure it can be made to understand the __VirtualDom_custom nodes that WebGL creates.

It uses _WebGL_render for rendering Which is not pure and requires a DOM implementation

We do not need to evaluate this in order to write assertions. The __VirtualDom_custom contains a declarative definition of what should be rendered (WebGL options, and a list of WebGL entities)

lydell commented 1 year ago

My understanding of this might be off, but this is what a “custom” vdom node looks like:

https://github.com/elm/virtual-dom/blob/44cbe2bf3d598cab569045cefcc10de31907598d/src/Elm/Kernel/VirtualDom.js#L129-L138

I thought calling that calling .__render on it is the only way of knowing what elements it would render.

Do you mean that one could look into .__facts and try to deduce that this node seems to be a webgl one and therefore most likely renders a <canvas> element?

(The only other thing I know of that uses “custom” is elm-explorations/markdown: https://github.com/elm-explorations/markdown/blob/5fdbf4433c0d7942ec2bf7db22c6a19c3e1770f4/src/Elm/Kernel/Markdown.js#L15)

w0rm commented 1 year ago

I mean, in the simplest case it could deduce that a given custom node is a webgl one and just output canvas in the json.

I'm not sure how useful this would be for testing webgl. If the goal is to write assertions for webgl options and entities, then this could be somehow expanded in json too.

lydell commented 1 year ago

it could deduce that a given custom node is a webgl

How?

w0rm commented 1 year ago

By introspecting the __model property of a custom node.

lydell commented 1 year ago

In conclusion: Possible, but requires heuristics, higher effort than reward?

MartinSStewart commented 1 year ago

For some larger context: elm-pages and lamdera/program-test have vendored the htmlToJson kernel code for server side rendering and visual regression testing respectively. So solving this issue would solve it in 3 different places.

dillonkearns commented 1 year ago

Yes, for context, elm-pages shares the html-to-string logic from the elm-test codebase and I try to keep it in sync with the upstream code. Even if there isn't any useful content in the server-side rendered canvas, it would be nice to support this in the case of elm-pages for compatibility. The initial page hydrates from the server-rendered HTML and the goal is to have the exact same HTML in the server-rendered HTML and the initial view in Elm once the JS is run and the Elm view takes over the DOM.