Replace Karma and Mocha with Vitest - #1773
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
matthew-white
left a comment
There was a problem hiding this comment.
Adding questions and comments
There was a problem hiding this comment.
My local commit also deleted karma.conf.js. One thing I'd want to do is review whether there have been any changes to karma.conf.js since the last time I worked on this. Maybe there's configuration in karma.conf.js that we'd want to preserve via parallel configuration in this file.
| import { fileURLToPath } from 'node:url'; | ||
| import { defineConfig, mergeConfig } from 'vitest/config'; | ||
|
|
||
| import viteConfig from './vite.config'; |
There was a problem hiding this comment.
My work on this predated the monorepo setup, which is why this file expects vite.config.js to exist in this directory. Not sure whether the new vitest.config.js here will also be used by the Web Forms app. If so, it should probably go somewhere else (probably the apps/ directory or the root directory of the repository).
| trap 'rm -- ../../public/index.html "$output"' EXIT | ||
|
|
||
| NODE_ENV="test" karma start karma.conf.js | tee "$output" | ||
| vitest run "$@" | tee "$output" |
There was a problem hiding this comment.
I think "$@" is there so that devs can specify a filter. See the related changes to CONTRIBUTING.md about filtering tests.
| /WARN LOG:/ { ++warnings; print "WARNING: " $0 } | ||
| /stderr/ { ++warnings; print "WARNING: " $0 } | ||
| /ERROR LOG:/ { ++warnings; print "WARNING: " $0 } | ||
| /Module Warning/ { ++warnings; print "WARNING: " $0 } | ||
| /WARN \[web-server\]:/ { ++warnings; print "WARNING: " $0 } |
There was a problem hiding this comment.
I understand the removal of WARN [web-server]:, since I'm pretty sure that's from Karma. But I'm not sure why I replaced WARN LOG: with stderr. I'm also not sure what's going on with ERROR LOG:. Should that line be removed now, similar to WARN LOG:?
There was a problem hiding this comment.
In my local commit, I moved this file to test/setup/index.js. I didn't do so here because I wanted to make the diff clearer.
There was a problem hiding this comment.
When I was working on this, there was something really weird going on with hooks that I'm not sure I fully understood. IIRC individual test files had access to beforeAll, afterAll, beforeEach, and afterEach, but test/index.js didn't. There was some split in the environment available to test/index.js and the environment available to individual tests. I added these hook mechanisms here so that test/index.js could continue to define global hooks. That setup worked and was running for me locally, but it definitely felt like a workaround.
| window.should = should(); | ||
| window.expect = expect; |
There was a problem hiding this comment.
I'm not sure why this PR removes expect from window, but keeps should. 🤔 But it's what I have in my local commit. Do we maybe import expect wherever we use it in tests (such that it doesn't need to be global)?
| configurable: true | ||
| }); | ||
|
|
||
| Error.stackTraceLimit = 40; |
There was a problem hiding this comment.
I'm not sure why this was added. It feels like something that should go in its own PR. Maybe we can just remove it if I don't remember why it was added. Or maybe there's no harm in adding it.
| `npm run test:debug` opens a browser window. This file styles the page to | ||
| improve its look for when `npm run test:debug` is run. |
There was a problem hiding this comment.
Maybe I could further reduce the size of this PR by moving these comments to #1772, along with the style changes that these comments mention that are further below in the file.
| // given that we also specify them under `browser` above. | ||
| fileParallelism: false, | ||
| isolate: false, | ||
| sequence: { hooks: 'list' }, |
There was a problem hiding this comment.
I have a vague memory that this hooks configuration was an important step in getting things to run.
There was a problem hiding this comment.
My local branch also made this change to package.json, which I don't really understand:
diff --git a/package.json b/package.json
index 715a4dec2..be759c7e7 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,8 @@
"build:dev": "nf start build,nginx",
"lint": "eslint --max-warnings 0 --cache --ext .js,.vue,.cjs src/ bin/ test/ *.js *.cjs",
"lint:fix": "eslint --max-warnings 0 --fix --cache --ext .js,.vue,.cjs src/ bin/ test/ *.js *.cjs",
- "test": "./test/run.sh"
+ "test": "vitest",
+ "test:run": "./test/run.sh"
},
"volta": {
"node": "20.10.0"Most everything still refers to npm run test, not npm run test:run, though my local branch does change CI to use test:run. But test/run.sh does some good things, both in CI and local development, e.g., it checks for Vue warnings and Sass warnings. I'm not sure why we would want to run vitest without running test/run.sh. Maybe it has something to do with filtering tests?
There was a problem hiding this comment.
Oh maybe it's the difference between vitest and vitest run. Like does vitest by itself run continuously?
A while ago, I worked on replacing Karma (and Mocha) with Vitest (getodk/central#1267). I never finished that work, but I wanted to share what I have so far.
State of the PR
I had these changes running locally at some point. However, that was well over a year ago. Importantly, it predated our new monorepo setup, which means that related configuration has changed since I last worked on it.
This PR is not expected to work at the moment. I'll add more details below as to why. Note that I didn't fully review the changes here. This PR is a work-in-progress.
I don't remember whether 100% of tests were passing back when I was working on this. It's very possible that they were. I seem to remember that most of them were at least. Locally, I don't see any changes to individual tests.
Overall approach
The overall approach I took was to use Vitest browser mode. That's because it seemed most similar to Karma.
At the time, Vitest browser mode was marked as experimental. I'm pretty sure there have been breaking changes to it since I last worked on it.
Required PRs
My original local commit was on a long branch (now quite outdated) that made a series of changes:
I've rebased my local commit and also extracted other work that was on the same long branch. I've put that other work in separate PRs so that this core PR can be as slim as possible. The following PRs are required in order for the changes in this PR to work:
Follow-up work
I want this PR to be self-contained, i.e., to contain the minimal changes needed to move to Vitest. However, I had other changes on my local branch that can be considered in separate PRs. At least one of those PRs requires this PR to be merged first.
Package changes
I had local changes to package.json. However, that file has changed a lot in the repo since I last worked on this, so I decided not to include those changes in the PR. The packages I used back then are probably outdated by now anyway. But here's the list of packages I added locally:
I also removed packages related to Karma, Mocha, Vue CLI, and webpack. With this PR, none of those frameworks will be needed for Central Frontend anymore.
More details below
I'm going to leave comments below on particular files and lines in order to explain my approach and surface current open questions.