I just finished adding tests to my Repository-Context-Packager project,
I went with Jest as my testing framework. Jest is probably the most popular JavaScript testing framework out there and it comes with everything built-in, mocking, coverage reports. I didn't need to install a bunch of separate packages like you would with some other frameworks. Plus, Jest has really good documentation and a huge community, so when I got stuck, I could find answers pretty easily. The other reason was that Jest just works out of the box for most projects.
My project uses ES modules, and Jest doesn't natively support that without some configuration. First, I installed Jest as a dev dependency with npm install --save-dev jest, but then when I tried to run it with just npm run jest, it completely failed with a "Cannot use import statement outside a module" error. Turns out, even though Jest 30.x has better ES module support, you still need to run it with Node's experimental VM modules flag. So I had to update my package.json test script to node --experimental-vm-modules node_modules/jest/bin/jest.js instead of just jest. I also created a jest.config.js file to tell Jest to use Node as the test environment and specify where my tests are located. The config was pretty simple, just set testEnvironment: 'node', defined my test match patterns for files, and configured coverage settings. One more thing that tripped me up, I had to import jest from @jest/globals in my test files to use things like jest.spyOn() for mocking, and I also had to update my ESLint config to recognize Jest globals like describe, test, and expect, otherwise my editor was full of red squiggly lines complaining that these weren't defined.
I decided to start with three different modules to get good coverage of different testing scenarios. First was toml-config.js, which loads configuration from TOML files. This was perfect for a first test because it's a simple, pure function with clear inputs and outputs. I wrote 12 test cases covering everything from valid configs to malformed TOML syntax to missing files. I needed to create actual test fixture files instead of mocking the file system. My second target was tree-builder.js, which has two functions - one that builds a tree structure from file paths and another that renders it as text. This ended up being super fun to test because I could write 30 test cases covering all sorts of edge cases like empty arrays, nested directories, different path separators, dotfiles, and making sure the sorting worked correctly. I even added integration tests that combined both functions. The third module I tested was git-info.js, which gets Git repository information. This one was tricky because it involves running actual Git commands. I initially tried creating temporary Git repositories in my tests, but that got really complicated really fast with issues about deleted directories and branch names. So I simplified it to just test against the actual project repository, which worked much better. I wrote 13 tests covering things like checking the return value structure, handling non-Git directories, and various edge cases.
I discovered that my Git function needed to handle cases where someone runs it from a non-Git directory, and it properly returns null in those cases. The most interesting edge case was dealing with different Git default branch names - some systems use master and newer ones use main, so I had to make my tests flexible enough to handle both. I also found that testing with Unicode characters in author names and special characters in commit messages worked fine. One thing that surprised me was that my TOML parser properly rejected duplicate keys in config files, which I wasn't even sure about until I wrote a test for it.
I've written unit tests before in other projects, but this was my first time setting up Jest from scratch with ES modules, and honestly, it was more challenging than I expected. The ES modules support in Jest is still marked as "experimental" and it shows - the setup wasn't as smooth as I remembered from working with CommonJS projects. But once I got past the initial configuration hurdles, everything clicked. What really struck me this time was how much more thoughtful I've become about testing. Before, I used to just write tests to make sure functions returned the right values, but now I'm thinking more deeply about edge cases and failure modes. The biggest lesson was about test design. I learned that sometimes testing against real files and real Git repositories is actually better than mocking everything.
Top comments (0)