Cannabis Freedom Index

Changelog d32a988tree, with Claude Opus 5.5

Run every test before each build: npm test

`npm test` runs all node test files (answers, profile claims, history, research coverage, charts, survey, books). `prebuild` and `prebuild:quick` run it, so the build agents already run stops on a failing test. CI runs `npm test` once in place of four steps. The chart-semantics tests were in no script; one (#183) still read the use figure from CountryArticle, which now lives in CountryIntro.

7 files of code, design or docs +19 −16 lines

Code, design and documents 7 files

.github/workflows/deploy.yml +5 −9
@@ -32,13 +32,9 @@ jobs:
         uses: actions/configure-pages@v6
       - run: npm ci
-      # Every profile's quick answers ("Can I carry it?") against its own text, and no sentence
-      # known to be false (scripts/answers.test.mjs, scripts/profile-claims.test.mjs): a failure
-      # stops the deploy instead of going live.
-      - run: npm run answers:test
-      # the facts earlier issues corrected, which a later rewrite must not lose
-      - run: npm run history:test
-      - run: npm run research:test
-      # the survey: relay text never as HTML, deletions confirmed, one respondent per key
-      - run: npm run survey:test
+      # Every test (npm test): each profile's quick answers ("Can I carry it?") against its own text
+      # and no sentence known to be false, the facts earlier issues corrected, research coverage,
+      # chart wording, the survey's safety. A failure stops the deploy instead of going live.
+      # (`npm run build` runs them again first, as everywhere: a few seconds.)
+      - run: npm test
       # The social preview images (one per page) take minutes to draw and rarely change. Each is
       # kept under a hash of its own content, so restoring the folder redraws only what is new.

AGENTS.md +3 −0
@@ -16,2 +16,5 @@ cannabis law (`changes.yaml`, `articles/`) and a cultural atlas (`culture/`), bu
 - Don't start dev or preview servers; check with `npm run build` (one build at a time) and the
   HTML in `dist/`. For a small frontend change, `npm run build:quick` skips the preview images.
+- Both builds run `npm test` first (answers, profile claims, history, charts, research, survey; a
+  few seconds) and stop if a test fails. Run `npm test` alone for a quick check. A new test file
+  goes into the `test` script in `package.json`.

docs/EXPAND-COUNTRIES.md +1 −1
@@ -31,5 +31,5 @@ For each country in the batch:
 3. Work through `docs/EXPAND-COUNTRY.md` in its order: current law and penalty tables, history,
    articles, context sections, culture, links.
-4. Build (`npm run build`; wait if another build is running), run
+4. Build (`npm run build`, which runs `npm test` first; wait if another build is running), run
    `node scripts/profile-audit.cjs <id>` (no errors allowed), then read the built page in
    `dist/country/<id>/`.

docs/EXPAND-COUNTRY.md +1 −1
@@ -122,5 +122,5 @@ covers well need not be repeated. `node scripts/country-gaps.cjs us/ca` is a sta
 
 ```bash
-npm run build          # must pass; it checks schemas, citations and internal links
+npm run build          # must pass; runs npm test first (answers, claims, history), then checks schemas, citations and links
 npm run profiles:audit # must report no errors for your country (node scripts/profile-audit.cjs <id>)
 npm run seo:audit      # what the deploy runs after the build

docs/SOLVE-ISSUES.md +2 −3
@@ -60,7 +60,6 @@ overreach (a proposed new score, a "binding" law that is only a draft).
 ```bash
 node scripts/profile-audit.cjs <id>   # no errors
-npm run answers:test                   # answers and profile claims
-npm run history:test                   # when changes.yaml changed
-npm run build                          # schemas, citations, links
+npm test                               # answers, profile claims, history, charts (the build runs it too)
+npm run build                          # npm test, then schemas, citations, links
 npm run seo:audit
 ```

package.json +3 −0
@@ -6,5 +6,8 @@
   "scripts": {
     "dev": "astro dev",
+    "test": "node --test scripts/answers.test.mjs scripts/profile-claims.test.mjs scripts/use-freedom-ratio.test.mjs scripts/history-scope.test.cjs scripts/context-coverage.test.mjs scripts/chart-semantics.test.cjs scripts/survey.test.mjs scripts/books-status.test.cjs",
+    "prebuild": "npm test",
     "build": "astro build",
+    "prebuild:quick": "npm test",
     "build:quick": "SKIP_OG=1 astro build",
     "preview": "astro preview",

scripts/chart-semantics.test.cjs +4 −2
@@ -126,6 +126,8 @@ test('compact prevalence cells and profiles keep age and sampling detail in tool
   assert.match(home, /useShareLabel\(c.use\)/);
   assert.match(home, /useDetail\(c\).*USE_COMPARISON_NOTE/);
-  const profile = fs.readFileSync('src/components/CountryArticle.astro', 'utf8');
-  assert.match(profile, /<dt>Past-year share<\/dt>/);
+  // the profile's figure lives in its opening, "Cannabis in …" (CountryIntro.astro)
+  const profile = fs.readFileSync('src/components/CountryIntro.astro', 'utf8');
+  assert.match(profile, /<dt>Past year<\/dt>/);
+  assert.match(profile, /people aged \{ages\}/);
   assert.match(profile, /<SourceTip><span>Past-year cannabis use among people aged \{useAges\(use\)\}/);
   assert.doesNotMatch(profile, /<p>\{USE_COMPARISON_NOTE\}<\/p>/);

    ↑↓ to move, ↵ to open.