Added Node.js unit tests for core JavaScript utilities#636
Added Node.js unit tests for core JavaScript utilities#636khemarato merged 10 commits intobuddhist-uni:mainfrom
Conversation
Added tests for utils.js (unaccented, UpdateQueryString, locationOf, sortedInsert, Ranges) and buggytrack.js (cyrb53) using Node's built-in test runner. Zero new dependencies. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
✅ Deploy Preview for obu ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
khemarato
left a comment
There was a problem hiding this comment.
Some tests! Excellent!
package.json
Outdated
| }, | ||
| "scripts": {} | ||
| "scripts": { | ||
| "test": "node --test test/**/*.test.js" |
There was a problem hiding this comment.
Let's put these tests closer to the files they're testing in assets/js/
Also: make sure to exclude these js test files from the Jekyll build in _config
There was a problem hiding this comment.
Fixed in the latest commit. Moved test files to assets/js/tests/ and added the exclusion pattern in _config.yml to keep them out of the Jekyll build.
test/search-worker.test.js
Outdated
| // Helper: bring vm-realm objects into the current realm for deepEqual | ||
| function toLocal(obj) { return JSON.parse(JSON.stringify(obj)); } | ||
|
|
||
| // search_index.js is a Jekyll/Liquid template, so we cannot load it |
There was a problem hiding this comment.
Let's maybe run these tests after the Jekyll build process for now, so you can grab the real output js? Or alternatively we can split search_index.js into two files (js code and document data) as a first PR before these tests. But I am not a fan of trying to build a custom parser inside a test 😅
There was a problem hiding this comment.
Agreed — the custom parser is brittle and not ideal. I see two viable paths:
- Split
search_index.jsinto pure JS logic + Liquid data template — cleanest long-term, and tests can import the JS directly - Run tests post-build against the generated output — simpler setup but couples tests to the build pipeline
I'd lean toward option 1 since it also improves the code structure. Happy to submit that as a preliminary PR. Which approach do you prefer?
There was a problem hiding this comment.
Sounds good! I'll submit a preliminary PR to split search_index.js into pure JS logic (search_functions.js) + Liquid data template first. Once that's merged, I'll rebase this PR to:
- Remove the
extractFunctionworkaround and import the split file directly - Add
html-validateas a devDependency for HTML fragment validation - Add the "finds the section with the most matches" test case for
getBlurbForResult - Validate HTML output from
categoryName,addMatchHighlights, andgetBlurbForResult
test/search-worker.test.js
Outdated
|
|
||
| describe('categoryName', () => { | ||
| it('returns correct HTML for known categories', () => { | ||
| assert.ok(categoryName('av').includes('Recording')); |
There was a problem hiding this comment.
These are over-specified and trivial tests. Instead of testing that each category has the right name, let's just make sure they are valid html fragments. We can leave the exact names to the function itself.
There was a problem hiding this comment.
Good call. Fixed in the latest commit — now only validates that the return value contains a valid <i> icon element and is non-empty HTML, without asserting specific display names.
test/search-worker.test.js
Outdated
| const result = { matchData: { metadata: {} } }; | ||
| assert.equal(resultMatched(result, 'title'), false); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Let's also add tests for addMatchHighlights and getBlurbForResult while we're here? (Nonblocking: can do in a follow-up PR if you like)
There was a problem hiding this comment.
Added tests for both addMatchHighlights and getBlurbForResult in the latest commit.
…rage - Moved test files from test/ to assets/js/tests/ (closer to source) - Added assets/js/tests/ to _config.yml exclude list - Updated categoryName tests to validate HTML structure instead of specific names - Added tests for addMatchHighlights and getBlurbForResult - Added inline comments explaining why vm.createContext needs explicit globals Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
khemarato
left a comment
There was a problem hiding this comment.
Agreed. Let's go ahead and split search_index.js first so we can run these tests before the build.
| const content = 'a '.repeat(50) + 'MATCH' + ' b'.repeat(200); | ||
| const item = { title: 'Test', description: null, content: content }; | ||
| const blurb = getBlurbForResult(result, item, [50]); | ||
| assert.ok(blurb.includes('MATCH') || blurb.includes('<strong>')); |
|
Thanks for reviewing #638! Since you prefer keeping
Does that sound right, or would you prefer a different approach? |
|
Yep that sounds about right. You can also add tests for your new |
…tests Address review feedback: - Remove extractFunction parser since search_functions.js now exists as a standalone file (after buddhist-uni#637 merged) - Load search_functions.js directly via vm sandbox - Add handleSearchMessage tests covering: stop word handling, +prefix logic, fallback search, filterquery filtering, and result structure validation Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
Updated! Changes in the latest push:
All 57 tests pass (12 suites, 0 failures). Also merged upstream |
Address review feedback from khemarato: add test cases covering all prefix combinations to verify existing +/- prefixes are preserved. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
|
Ping: There are four unaddressed comments above, @xr843 No rush, just alerting you in case they dropped from your inbox. 😊 |
|
@khemarato Done! Addressed all 4 comments:
60 tests passing now. Let me know if anything else needs adjustment. Have a great day! 🙏 |
khemarato
left a comment
There was a problem hiding this comment.
Okay. Two more nits and then this should be good. 😊
| // Should pick the section with the most matches (MATCH, ME, INSTEAD) not the lone IGNORE | ||
| assert.ok(blurb.includes('MATCH'), 'Expected blurb to contain MATCH'); | ||
| assert.ok(blurb.includes('INSTEAD'), 'Expected blurb to contain INSTEAD'); | ||
| assert.ok(!blurb.includes('IGNORE'), 'Expected blurb to NOT contain IGNORE'); |
…order Address review nits: - Add assertValidHtml() for every category in the knownCategories loop - Flip assertion order in "finds the section with the most matches" to catch incorrect greedy implementations by checking the negative first Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
for (var i in positions) yields string keys ("0", "1", ...),
causing j = i + 1 to produce "01" (string concatenation) instead
of 1 (numeric addition). This made the inner while-loop skip
positions[1] for i=0 and exit immediately for all other starting
indices, so the algorithm always selected the first match's window
regardless of where the densest cluster was.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Place the lone IGNORE match before the cluster (MATCH, ME, INSTEAD) so that a greedy algorithm picking the first match would fail. Also add assertValidHtml() in the categoryName loop per review. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
| var best_i = -1; | ||
| var best_n = 0; | ||
| for (var i in positions) { | ||
| for (var i = 0; i < positions.length; i++) { |
There was a problem hiding this comment.
Excellent! This is why I asked for the flipped test. I had a feeling there was a bug! 😁
Summary
assets/js/utils.jscoveringutils.unaccented,UpdateQueryString,locationOf,sortedInsert, and theRangesclass (interval set data structure)assets/js/buggytrack.jscovering thecyrb53hash function (determinism, uniqueness, edge cases)assets/js/search_index.js:categoryName,getPositions, andresultMatchedpackage.jsonto add a"test"script:node --test test/**/*.test.jsZero new dependencies — uses only Node.js built-in
node:testandnode:assertmodules, plusnode:vmto load the browser-global JS files into a sandbox.40 tests across 9 suites, all passing.
This was discussed and agreed to with the maintainer @khinsen-bot (Khemarato Bhikkhu).
Test plan
npm testactions/setup-node@v4)Co-Authored-By: Claude Opus 4.6 (1M context) [email protected]
🤖 Generated with Claude Code