Skip to content

Commit 4652fe9

Browse files
authored
test: replace jasmine browser runner with vitest + jsdom (#869)
* test: replace jasmine browser runner with vitest + jsdom PR-1 of the modernization plan: makes the test suite headless and CI-ready without touching src/jquery.autocomplete.js. - Add vitest, jsdom, jquery@3.7.1, jquery-mockjax@2.6.0 dev deps (jQuery + mockjax versions match what spec/runner.html loaded from CDN). - test/setup.js attaches a single jQuery instance to globalThis/window, registers mockjax against it, then loads the UMD plugin so it binds to the same instance. Silences mockjax's per-request console logging. - vitest.config.js pins pool: "threads" — the default "forks" pool on Windows times out the worker handshake when the setup file does heavy synchronous work (jQuery + mockjax + UMD plugin load). - Port all 26 Jasmine specs to test/autocomplete.test.js (31 it() cases): beforeEach(done) -> await new Promise(...), spyOn -> vi.spyOn. - Add npm test / test:watch scripts; broaden lint and format globs to test/. - Rename eslint.config.js -> eslint.config.mjs to silence Node's ESM-reparse warning without adding "type": "module" to package.json (which would break CommonJS consumers of the dist UMD bundle). - Remove spec/ (vendored Jasmine 1.3.1 + 2.0.1, runner.html, original spec). grunt + grunt-contrib-uglify still in devDependencies; PR-2 replaces them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: add claude.md with project, test, and commit conventions Documents project shape (single-file UMD plugin), commands, test setup (vitest + jsdom + mockjax), release/version flow, non-obvious architecture (UMD wrapper, dual plugin name, defaults merge, response normalization, caching guards), source style (intentionally ES5 inside the IIFE), and the Conventional Commits requirement.
1 parent 7f76a39 commit 4652fe9

19 files changed

Lines changed: 2676 additions & 7504 deletions

CLAUDE.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project shape
6+
7+
This is a single-file jQuery plugin (Ajax Autocomplete). The entire implementation lives in `src/jquery.autocomplete.js` (~1k lines). Everything else — `dist/`, `typings/`, `spec/`, `scripts/`, `index.htm` — is produced from, tests, types, or demos that one source file. Edits almost always belong in `src/jquery.autocomplete.js`; never edit `dist/*` directly (the build overwrites it).
8+
9+
## Commands
10+
11+
- `npm test` — Vitest run (headless, jsdom). Single-shot, exits nonzero on failure.
12+
- `npm run test:watch` — Vitest watch mode for local TDD.
13+
- `npm run lint` — ESLint (flat config in `eslint.config.mjs`) over `src/` and `test/`.
14+
- `npm run format` — Prettier rewrite of `src/` and `test/` (100-col, 4-space, ES5 trailing commas — config in `package.json`).
15+
- `npm run build``grunt build`: copies `src/jquery.autocomplete.js` to `dist/jquery.autocomplete.js` while substituting the `%version%` placeholder with `package.json` `version`, uglifies to `dist/jquery.autocomplete.min.js`, and syncs `devbridge-autocomplete.jquery.json` version. Run this before release/commit when source changes. *(Slated for replacement with a smaller Node script in the next modernization PR.)*
16+
17+
## Tests
18+
19+
Vitest + jsdom, headless. Specs live in `test/autocomplete.test.js`. `test/setup.js` attaches a single jQuery instance to the jsdom `window` and `globalThis`, registers `jquery-mockjax` against it, silences mockjax's per-request console logging, then loads `src/jquery.autocomplete.js`. The plugin's UMD wrapper picks up `globalThis.jQuery` and registers `$.Autocomplete` plus `$.fn.autocomplete`/`$.fn.devbridgeAutocomplete` against that same instance.
20+
21+
The Vitest pool is pinned to `threads` in `vitest.config.js` — the default `forks` pool times out the worker handshake on Windows when the setup file does heavy synchronous work (jQuery + mockjax + UMD plugin load). Don't switch pools without re-verifying.
22+
23+
To run a single test, use `npx vitest run -t "test name substring"` or temporarily change `describe`/`it` to `describe.only`/`it.only`.
24+
25+
The demo page `index.htm` is the manual test surface (Ajax lookup, local lookup with grouping, custom container, dynamic width). It loads jQuery + mockjax from CDN; just open in a browser.
26+
27+
## Release/version flow
28+
29+
1. Bump `version` in `package.json`.
30+
2. `npm run build` — this propagates the new version into `dist/jquery.autocomplete.js` (via `%version%` placeholder) and `devbridge-autocomplete.jquery.json`. The placeholder only exists in `src/`; do not hand-edit version strings in `dist/`.
31+
32+
## Architecture notes that aren't obvious from a single file
33+
34+
- **UMD wrapper** at the top of `src/jquery.autocomplete.js` registers under AMD, CommonJS, or browser global — keep all three branches working when touching the wrapper.
35+
- **Dual plugin name**: registers `$.fn.devbridgeAutocomplete` unconditionally, and aliases `$.fn.autocomplete` only if it is not already taken (jQuery UI defines one). Tests and the README rely on this fallback behavior — don't remove the guard.
36+
- **Defaults live on `Autocomplete.defaults`** and are merged per-instance via `$.extend(true, {}, defaults, options)`. New options must be added to the defaults object so deep-merge picks them up, and mirrored in `typings/jquery.autocomplete.d.ts` and the option tables in `readme.md`.
37+
- **Response normalization**: server responses pass through `transformResult` (default JSON.parse for `dataType: 'text'`). Local `lookup` may be an array or a `function(query, done)` callback; both paths converge on the same `{ value, data }` suggestion shape used everywhere downstream (`formatResult`, `onSelect`, grouping).
38+
- **Caching + bad-query guard**: `cachedResponse` keys by query string, and `preventBadQueries` records prefixes that returned no results so future queries with the same prefix short-circuit. `clearCache` / `clear` reset these — when adding new request paths, decide whether they should populate or honor these caches.
39+
40+
## Conventions
41+
42+
- Source style is the existing one: ES5 inside the IIFE (no `let`/`const`/arrow funcs in `src/jquery.autocomplete.js`), `"use strict"`, `var that = this` pattern. ESLint config targets `ecmaVersion: 2022` but the file is intentionally written to run in old browsers — match the existing style rather than modernizing.
43+
- Prettier owns formatting; run `npm run format` before committing source changes.
44+
45+
## Commit messages
46+
47+
Use [Conventional Commits](https://www.conventionalcommits.org/): `<type>(<optional scope>): <description>`.
48+
49+
- Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`.
50+
- Description is imperative, lowercase, no trailing period (e.g. `fix: handle null suggestion data`).
51+
- Breaking changes: append `!` after the type/scope (`feat!: ...`) and/or add a `BREAKING CHANGE:` footer.
52+
- Scope, when useful, names the area touched: `build`, `test`, `deps`, `autocomplete`.
53+
54+
Examples: `test: port specs to vitest + jsdom`, `build: replace grunt with node script`, `chore(deps): bump prettier to 3.6.2`, `feat!: drop ie11 support`.

eslint.config.js renamed to eslint.config.mjs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import js from '@eslint/js';
33
export default [
44
js.configs.recommended,
55
{
6+
files: ['src/**/*.js'],
67
languageOptions: {
78
ecmaVersion: 2022,
89
sourceType: 'script',
@@ -18,9 +19,20 @@ export default [
1819
clearTimeout: 'readonly',
1920
},
2021
},
21-
files: ['src/**/*.js'],
22-
rules: {
23-
// Add any custom rules here if needed
22+
},
23+
{
24+
files: ['test/**/*.js', 'vitest.config.js'],
25+
languageOptions: {
26+
ecmaVersion: 2022,
27+
sourceType: 'module',
28+
globals: {
29+
globalThis: 'readonly',
30+
window: 'readonly',
31+
document: 'readonly',
32+
console: 'readonly',
33+
setTimeout: 'readonly',
34+
clearTimeout: 'readonly',
35+
},
2436
},
2537
},
2638
];

0 commit comments

Comments
 (0)