I’m working on a cli program similar to the examples in elm-cli-options-parser (link), and was wondering if anyone had worked out ways to test something like that using Jest or similar?
Some of the functionality can be tested via elm-test, but I’d really like the ability to test it “end-to-end” in the sense of “I run this command, and this file gets rewritten in this specific way”.
The main issue is I can’t figure out how to get the files to compile for testing with a library like Jest or similar. Jest can’t handle compiling Elm on it’s own, and I get weird errors when trying to compile files separately from Jest and then import them into the test files (“parcelRequire is not defined” when using Parcel, and “Cannot read property ‘Elm’ of undefined” when using elm make).
Does anyone have examples of a setup like this that works? Or recommendations of things to try?
I have a few projects that I maintain with test suites for Elm-based CLIs. There are a lot of different ways to approach this, and many of them don’t involve elm-test at all for the end-to-end testing (only for unit testing).
For many of these approaches, I’ve found approval testing (i.e. snapshot testing) to be a very helpful technique. The basic idea of snapshot testing is that you manually approve the output. The output could be terminal output, or generated code output, etc. Any time there’s a change, you have to manually approve the new change as the correct answer.
That said, here are a few different overall approaches to running Elm code with some sort of testing harness. I’ve ordered them starting with the simplest approaches. If simple does the trick, it’s best to start there.
Compile and run Elm from a shell script
I use the snapshot testing concept with some simple shell scripts and git. If there is a git diff in the snapshot output folder locations, then my GitHub Actions scripts will cause the build to fail. To approve, I just commit the new output.
Don’t test end-to-end, but get close with pure Elm
elm-program-test is a great tool, but I wouldn’t call it end-to-end testing. It’s more like integration testing for your Elm code. So you don’t exercise the end-to-end executable. I use this heavily in elm-pages to test part of the binary that runs HTTP requests.
Compile and run the Elm app from JS
This code is very much an early proof-of-concept, but I’ve been working on a concept for running snapshot tests from Elm. This is just an experiment for running a Jest snapshot test against some output from Elm.
It’s compiling the Elm app with a Jest transformer, which uses elm-node-compiler to compile the code when it’s required:
And this is where the transformer is wired in to the jest config:
Compile Elm in your build, run it from JS
Similar to the above technique, but you can compile it from a shell script and then require that Elm from your JS.
That’s a lot of detail, and some very specific scripts. But a lot of real-world code, too, that’s served me well in maintaining some of these projects. So I hope that’s helpful as a reference point! The bottom line is that just because you wrote the core logic in Elm, doesn’t mean you need to write all the tests in Elm. Especially with Snapshot testing, you’re just running output and comparing a snapshot, so it’s just an implementation detail that the output is generated from running some Elm code.