starting new job...
→ running command: cd "/etc/byggsteg/job-clone//wikimusic/trunk" && git reset --hard && git pull
HEAD is now at 430b72f ci: Name the byggsteg step with BYGGSTEG_STEP
From https://codeberg.org/jjba23/wikimusic
430b72f..69fb3e7 trunk -> origin/trunk
Updating 430b72f..69fb3e7
Fast-forward
manifest.scm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
→ running command: cd /etc/byggsteg/job-clone/wikimusic/trunk && uname -a
Linux wolk-jjba 7.2.11-gnu #1 SMP PREEMPT_DYNAMIC 1 x86_64 GNU/Linux
→ running command: cd /etc/byggsteg/job-clone/wikimusic/trunk && git log --name-status HEAD^..HEAD
commit 69fb3e7be4e6483bba8d3fc4cbf5de6ef18d962c
Author: Josep Bigorra <jjbigorra@gmail.com>
Date: Mon Oct 26 10:59:29 2026 +0100
chore: Update guile-veritas
The pin moves to v0.9.0, the release that makes coverage work: the measured
part of a run switches to Guile's debugging VM engine, and a run writes LCOV,
JSON, Cobertura, JaCoCo and a one-page HTML report for the whole project, merged
over the run and over the workers of --jobs. Two fiber-safety fixes for the
test helpers ride along.
🤖 Generated with [ECA](https://eca.dev) (deepseek/deepseek-flash)
Co-Authored-By: eca-agent <git@eca.dev>
M manifest.scm
→ running command: cd /etc/byggsteg/job-clone/wikimusic/trunk && maak test
The following derivation will be built:
/gnu/store/agnby8yvapda2mpmf547dwk0vlw95ydy-profile.drv
building CA certificate bundle...
listing Emacs sub-directories...
building fonts directory...
building directory of Info manuals...
building profile with 19 packages...
scanning directories for unit tests...
scanning present working directory for unit tests...
shuffled the files with seed 85110602 (replay with VERITAS_SEED=85110602)
found unit tests: (error-pages-spec.scm config-spec.scm domain-spec.scm about-spec.scm controller-spec.scm views-spec.scm auth-spec.scm assets-spec.scm sql-spec.scm guitarpro-spec.scm guitarpro-view-spec.scm)
running unit tests from file: error-pages-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] The classes an error page asks for
[🧪 test] every class the page names is one the sheets define
[⚙️ assert] no class is a no-op on the page
✅ got: ()
[⚙️ assert] and the page does name a fair few
✅ got: #t
+----------------------------------------------+
[📑 suite] Rendering an error page
[🧪 test] the wording is translated through the procedure it is given
[⚙️ assert] the headline arrives wrapped
✅ got: #t
[⚙️ assert] and so does the detail
✅ got: #t
[🧪 test] the page is serialized the way the rest of the site is
[⚙️ assert] inline script survives the serializer
✅ got: #t
[⚙️ assert] and is not escaped into nonsense
✅ got: #t
[🧪 test] the reader is offered a way out
[⚙️ assert] a link to /
✅ got: #t
[⚙️ assert] a link to /songs
✅ got: #t
[⚙️ assert] a link to /artists
✅ got: #t
[⚙️ assert] a link to /genres
✅ got: #t
[🧪 test] a reader who is signed in is not invited to sign in again
[⚙️ assert] the navigation differs with the session
✅ got: #t
[🧪 test] the page is a whole document of the site's own shell
[⚙️ assert] it starts with a doctype
✅ got: #t
[⚙️ assert] it is titled a WikiMusic page
✅ got: #t
[⚙️ assert] it links the site's stylesheet
✅ got: #t
[⚙️ assert] it carries the navigation
✅ got: #t
[⚙️ assert] and the footer
✅ got: #t
[🧪 test] the page says which status it is
[⚙️ assert] a 400 page shows its code
✅ got: #t
[⚙️ assert] a 400 page leads with its own wording
✅ got: #t
[⚙️ assert] a 400 page is drawn with a glyph
✅ got: #t
[⚙️ assert] a 401 page shows its code
✅ got: #t
[⚙️ assert] a 401 page leads with its own wording
✅ got: #t
[⚙️ assert] a 401 page is drawn with a glyph
✅ got: #t
[⚙️ assert] a 403 page shows its code
✅ got: #t
[⚙️ assert] a 403 page leads with its own wording
✅ got: #t
[⚙️ assert] a 403 page is drawn with a glyph
✅ got: #t
[⚙️ assert] a 404 page shows its code
✅ got: #t
[⚙️ assert] a 404 page leads with its own wording
✅ got: #t
[⚙️ assert] a 404 page is drawn with a glyph
✅ got: #t
[⚙️ assert] a 408 page shows its code
✅ got: #t
[⚙️ assert] a 408 page leads with its own wording
✅ got: #t
[⚙️ assert] a 408 page is drawn with a glyph
✅ got: #t
[⚙️ assert] a 500 page shows its code
✅ got: #t
[⚙️ assert] a 500 page leads with its own wording
✅ got: #t
[⚙️ assert] a 500 page is drawn with a glyph
✅ got: #t
+----------------------------------------------+
[📑 suite] What an error page says
[🧪 test] a page is drawn in the tone its class of refusal is read in
[⚙️ assert] a 502 is read as a 500
✅ got: warning
[⚙️ assert] a 503 is read as a 500
✅ got: warning
[⚙️ assert] a 418 is read as a 400
✅ got: plugs
[⚙️ assert] a 451 is read as a 400
✅ got: plugs
[⚙️ assert] a request that timed out has a page
✅ got: #t
[🧪 test] a status with no wording of its own still describes itself
[⚙️ assert] an unnamed status is named in its headline
✅ got: #t
[⚙️ assert] and it still has an explanation
✅ got: #t
[⚙️ assert] which is not the wording of a status that has one
✅ got: #t
[🧪 test] an error page describes what the reader can do
[⚙️ assert] a 500 offers to be tried again
✅ got: #t
[⚙️ assert] a 404 points at what is still there
✅ got: #t
[🧪 test] a page leads with a headline of its own
[⚙️ assert] a 404 has a headline
✅ got: #t
[⚙️ assert] and something to explain itself
✅ got: #t
[⚙️ assert] the two codes do not share wording
✅ got: #t
[⚙️ assert] nor do their explanations
✅ got: #t
ℹ️ info - ran 3 tasks in: 1 seconds, -230318 microseconds
running unit tests from file: config-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] The manual is read where the code is
[🧪 test] the manual's address is the deployment's, or the README beside its code
[⚙️ assert] the manual follows the code
✅ got: https://codeberg.org/jjba23/wikimusic/src/branch/trunk/README.org
+----------------------------------------------+
[📑 suite] The control an instance turns off
[🧪 test] an instance that says nothing about it asks
[⚙️ assert] the ask is shown unless it says otherwise
✅ got: #t
[🧪 test] an instance that raises nothing says so with #f
[⚙️ assert] the switch itself
✅ got: #f
[🧪 test] and may say so in words
[⚙️ assert] false
✅ got: #f
[⚙️ assert] No, however it is capitalised
✅ got: #f
[⚙️ assert] off, with room around it
✅ got: #f
[⚙️ assert] 0
✅ got: #f
[🧪 test] and words that are not a no leave it on
[⚙️ assert] yes
✅ got: #t
[⚙️ assert] or the switch itself
✅ got: #t
+----------------------------------------------+
[📑 suite] Where the interface's own files are read from
[🧪 test] a file named with a leading slash is one file
[⚙️ assert] the leading slash is not doubled
✅ got: /css/wikimusic.olive.min.css
[🧪 test] a deployment that serves them elsewhere says where
[⚙️ assert] every file hangs off the host it named
✅ got: https://assets.example.org/wikimusic/vendor/fonts/lucida.css
[🧪 test] an instance serving its own reads them off itself
[⚙️ assert] a path on this instance
✅ got: /vendor/fonts/lucida.css
[⚙️ assert] and the page's own stylesheet with it
✅ got: /css/wikimusic.olive.min.css
[🧪 test] a host written with a trailing slash does not double it
[⚙️ assert] one slash between the two
✅ got: https://assets.example.org/wikimusic/favicon.ico
+----------------------------------------------+
[📑 suite] The picture a page is announced with
[🧪 test] a path is turned into an address of the instance serving it
[⚙️ assert] the path is joined onto the origin
✅ got: https://example.org/img/cover.jpg
[🧪 test] an address the deployment gave is left alone
[⚙️ assert] an address is already one
✅ got: https://pictures.example.org/cover.jpg
[🧪 test] and with no host to build one on, no address is invented
[⚙️ assert] no origin, no address
✅ got: #f
+----------------------------------------------+
[📑 suite] The addresses the instance offers
[🧪 test] the mail an instance sends comes from an address
[⚙️ assert] an address, not a blank
✅ got: #t
[⚙️ assert] and a name beside it
✅ got: #t
[🧪 test] the copyright line names somebody
[⚙️ assert] the holder is named
✅ got: #t
[🧪 test] each one is an absolute address
[⚙️ assert] where the source is read
✅ got: #t
[⚙️ assert] where the manual is read
✅ got: #t
[⚙️ assert] where the licence is written out
✅ got: #t
[⚙️ assert] where a reader supports the project
✅ got: #t
+----------------------------------------------+
[📑 suite] Where the instance reads what it says about itself
[🧪 test] a variable the deployment set is the one read
[⚙️ assert] the deployment's own value wins
✅ got: https://pingwing.jointhefreeworld.org
[🧪 test] a variable the deployment did not set falls back
[⚙️ assert] the project's own value is used
✅ got: the project's own value
ℹ️ info - ran 6 tasks in: 0 seconds, 24000 microseconds
running unit tests from file: domain-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] What a sort control means
[🧪 test] the clause names a column and a direction, and nothing else
[⚙️ assert] the column is a symbol
✅ got: #t
[⚙️ assert] the direction is one of the two words
✅ got: #t
[⚙️ assert] and a clause is all there is to it
✅ got: 2
[🧪 test] a sort that is spelled like SQL is not passed through
[⚙️ assert] "views desc; DROP TABLE songs" sorts by default
✅ got: ((last-edited-at desc))
[⚙️ assert] "display-name asc --" sorts by default
✅ got: ((last-edited-at desc))
[⚙️ assert] "(drop-table)" sorts by default
✅ got: ((last-edited-at desc))
[⚙️ assert] "views\") desc" sorts by default
✅ got: ((last-edited-at desc))
[🧪 test] something the page does not offer sorts the default way
[⚙️ assert] an unknown sort falls back
✅ got: ((last-edited-at desc))
[⚙️ assert] so does an empty one
✅ got: ((last-edited-at desc))
[🧪 test] every sort the pages offer maps onto its own clause
[⚙️ assert] newest first
✅ got: ((created-at desc))
[⚙️ assert] oldest first
✅ got: ((created-at asc))
[⚙️ assert] edited most recently
✅ got: ((last-edited-at desc))
[⚙️ assert] edited longest ago
✅ got: ((last-edited-at asc))
[⚙️ assert] by name, descending
✅ got: ((display-name desc))
[⚙️ assert] by name, ascending
✅ got: ((display-name asc))
[⚙️ assert] most viewed first
✅ got: ((views desc))
[⚙️ assert] least viewed first
✅ got: ((views asc))
+----------------------------------------------+
[📑 suite] Which related rows belong to an entry
[🧪 test] a genre is matched on the genre's identifier
[⚙️ assert] the row naming this genre
✅ got: (((artist-identifier . artist-1) (genre-identifier . genre-1) (song-identifier . song-1) (display-name . the one that matches)))
[🧪 test] the identifier compared against is the entry's own
[⚙️ assert] a row naming a song is not the artist's row
✅ got: ()
[⚙️ assert] nor is another entry's row this one's
✅ got: ()
[🧪 test] an artist is matched on the artist's identifier
[⚙️ assert] the row naming this artist
✅ got: (((artist-identifier . artist-1) (genre-identifier . genre-1) (song-identifier . song-1) (display-name . the one that matches)))
[🧪 test] a song is matched on the song's identifier
[⚙️ assert] the row naming this song
✅ got: (((artist-identifier . artist-1) (genre-identifier . genre-1) (song-identifier . song-1) (display-name . the one that matches)))
ℹ️ info - ran 2 tasks in: 0 seconds, 19136 microseconds
running unit tests from file: about-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] The order the page says things in
[🧪 test] the list stands under the sentence that introduces it
[⚙️ assert] the introduction comes first
✅ got: #t
[🧪 test] the promises keep the order they were written in
[⚙️ assert] each one follows the one before it
✅ got: #t
[🧪 test] the account of the place comes before the ask
[⚙️ assert] nothing is asked for before anything is said
✅ got: #t
+----------------------------------------------+
[📑 suite] The front page as a way in
[🧪 test] the search control carries the words to the collection
[⚙️ assert] the form names the collection
✅ got: #t
[⚙️ assert] and the field its words are read from
✅ got: #t
[🧪 test] a page with no artists to show is still the whole page
[⚙️ assert] no heading over nothing
✅ got: #f
[🧪 test] both shelves of the collection are shown, songs first
[⚙️ assert] the songs are there
✅ got: #t
[⚙️ assert] and so are the artists
✅ got: #t
[⚙️ assert] in the order they are read
✅ got: #t
[⚙️ assert] with a way to the rest of them
✅ got: #t
[🧪 test] the first screen says what is in the place
[⚙️ assert] the summary is read under the tagline
✅ got: #t
[⚙️ assert] and it is read after it
✅ got: #t
+----------------------------------------------+
[📑 suite] The pages of an instance that asks for nothing
[🧪 test] what the pages are for is still said
[⚙️ assert] the promises are still made
✅ got: #t
[⚙️ assert] and the front page still invites
✅ got: #t
[🧪 test] the about page asks for nothing
[⚙️ assert] there is no control
✅ got: #f
[⚙️ assert] and none of the words that are on one
✅ got: #f
[⚙️ assert] and nothing about what the money pays for
✅ got: #f
[🧪 test] and the front page asks for nothing either
[⚙️ assert] there is no control
✅ got: #f
[⚙️ assert] and none of the words that are on one
✅ got: #f
+----------------------------------------------+
[📑 suite] What the page says the project is
[🧪 test] it names what the project is
[⚙️ assert] the community is named
✅ got: #t
[⚙️ assert] and what it works towards
✅ got: #t
[🧪 test] it introduces the list of what a reader can do
[⚙️ assert] the list is introduced
✅ got: #t
[🧪 test] it ends on an invitation
[⚙️ assert] the last line is the invitation
✅ got: #t
[🧪 test] it says what the project is built on
[⚙️ assert] the language is named
✅ got: #t
[⚙️ assert] and so is the architecture
✅ got: #t
+----------------------------------------------+
[📑 suite] What the page tells a crawler
[🧪 test] the page says what kind of page it is
[⚙️ assert] the page states its own type
✅ got: #t
[⚙️ assert] and names the community as its subject
✅ got: #t
[🧪 test] the description is the page's own one
[⚙️ assert] a search result shows the community
✅ got: #t
[🧪 test] the title names the community
[⚙️ assert] the page is titled
✅ got: #t
+----------------------------------------------+
[📑 suite] The words the two pages share
[🧪 test] both pages name the place the same way
[⚙️ assert] the about page says it
✅ got: #t
[⚙️ assert] and so does the front page
✅ got: #t
[🧪 test] the account of the project belongs to the about page
[⚙️ assert] the front page is still the collection
✅ got: #f
[🧪 test] both pages close on the same invitation;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;; or pass the --no-auto-compile argument to disable.
;;; compiling /etc/byggsteg/job-clone/wikimusic/trunk/env.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/env.scm.go
;;; compiling ./test/veritas/unit/error-pages-spec.scm
;;; compiling ./app/views/error.scm
;;; compiling ./lib/wikimusic/html.scm
WARNING: (hygguile hygguile): imported module (hygguile components select) overrides core binding `select'
;;; compiling ./lib/wikimusic/config.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/config.scm.go
;;; compiling ./lib/wikimusic/seo.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/seo.scm.go
WARNING: (wikimusic html): imported module (hygguile hygguile) overrides core binding `select'
WARNING: (wikimusic html): `get-short-commit-sha' imported from both (kracht prelude) and (hygguile hygguile)
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/html.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/app/views/error.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/error-pages-spec.scm.go
WARNING: (wikimusic html): `get-short-commit-sha' imported from both (kracht prelude) and (hygguile hygguile)
;;; compiling ./test/veritas/unit/config-spec.scm
;;; compiling ./test/support/deployment.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/support/deployment.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/config-spec.scm.go
;;; compiling ./test/veritas/unit/domain-spec.scm
;;; compiling ./lib/wikimusic/domain.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/domain.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/domain-spec.scm.go
;;; compiling ./test/veritas/unit/about-spec.scm
;;; compiling ./app/views/about.scm
;;; compiling ./lib/wikimusic/prose.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/prose.scm.go
;;; compiling ./app/views/index.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/app/views/index.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/app/views/about.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/about-spec.scm.go
WARNING: (wikimusic html): imported module (hygguile hygguile) overrides core binding `select'
;;; compiling ./test/veritas/unit/controller-spec.scm
;;; compiling ./lib/wikimusic/controller.scm
;;; compiling ./lib/wikimusic/sqlite/util.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/sqlite/util.scm.go
;;; compiling ./lib/wikimusic/sqlite/comment.scm
;;; compiling ./lib/wikimusic/domain/comment.scm
;;; compiling ./lib/wikimusic/domain/repo.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/domain/repo.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/domain/comment.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/sqlite/comment.scm.go
;;; compiling ./lib/wikimusic/auth.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/auth.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/controller.scm.go
;;; compiled
[⚙️ assert] the about page invites
✅ got: #t
[⚙️ assert] and so does the front page
✅ got: #t
[🧪 test] the one ask is the same control on both pages
[⚙️ assert] the about page asks
✅ got: #t
[⚙️ assert] and so does the front page
✅ got: #t
[⚙️ assert] offered in the project's own words
✅ got: #t
+----------------------------------------------+
[📑 suite] The link to the page
[🧪 test] every page offers it
[⚙️ assert] the footer links to it
✅ got: #t
[⚙️ assert] and says where it leads
✅ got: #t
+----------------------------------------------+
[📑 suite] The word the link is offered in
[🧪 test] nl_NL has a word for it
[⚙️ assert] the label is translated
✅ got: #t
[🧪 test] ja_JP has a word for it
[⚙️ assert] the label is translated
✅ got: #t
[🧪 test] es_ES has a word for it
[⚙️ assert] the label is translated
✅ got: #t
[🧪 test] en_US has a word for it
[⚙️ assert] the label is translated
✅ got: #t
+----------------------------------------------+
[📑 suite] What the page promises a reader can do
[🧪 test] “Learn through curated resources that con…” is promised
[⚙️ assert] it is an item of the list
✅ got: #t
[⚙️ assert] and it is said once
✅ got: 1
[🧪 test] “Organize information with structured met…” is promised
[⚙️ assert] it is an item of the list
✅ got: #t
[⚙️ assert] and it is said once
✅ got: 1
[🧪 test] “Contribute by adding new compositions, a…” is promised
[⚙️ assert] it is an item of the list
✅ got: #t
[⚙️ assert] and it is said once
✅ got: 1
[🧪 test] “Discover music from diverse genres and t…” is promised
[⚙️ assert] it is an item of the list
✅ got: #t
[⚙️ assert] and it is said once
✅ got: 1
ℹ️ info - ran 9 tasks in: 1 seconds, -149845 microseconds
running unit tests from file: controller-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] The ownership half of who may change a row
[🧪 test] a contributor does not change a row somebody else made
[⚙️ assert] someone else's row is refused
✅ got: #f
[🧪 test] a contributor changes the row they made
[⚙️ assert] their own row is theirs to change
✅ got: #t
[🧪 test] a row that names no creator is only the super grant's to change
[⚙️ assert] a row with no creator is refused
✅ got: #f
[⚙️ assert] while the super grant may still change it
✅ got: #t
[🧪 test] the super grant changes any row, whoever made it
[⚙️ assert] a row another user created
✅ got: #t
[⚙️ assert] and a row of its own
✅ got: #t
+----------------------------------------------+
[📑 suite] The guard a mistyped address reaches
[🧪 test] a row that was found is handed on as it is
[⚙️ assert] the very row comes back, not a copy
✅ got: #t
[⚙️ assert] and nothing about it is rewritten
✅ got: ((identifier . 1c9a5b7e-2f3a-4c5d-9e0f-1a2b3c4d5e6f) (display-name . blue))
[⚙️ assert] what it is called does not decide what it returns
✅ got: #t
[🧪 test] a lookup that found nothing is answered with a 404
[⚙️ assert] it raises rather than returning nothing
✅ got: #t
[⚙️ assert] with the code artanis renders a page for
✅ got: 404
[⚙️ assert] in the shape artanis reads: code, name, message, arguments
✅ got: #t
[⚙️ assert] the message is a format string
✅ got: #t
[⚙️ assert] and its arguments come as a list
✅ got: #t
[🧪 test] a lookup that found an empty list is a lookup that found nothing
[⚙️ assert] an empty list is answered like #f
✅ got: 404
[🧪 test] the answer says what was looked for, and where
[⚙️ assert] the message names the kind of thing and the identifier
✅ got: no genre with the identifier a-genre-that-is-not-there
ℹ️ info - ran 2 tasks in: 0 seconds, 29174 microseconds
running unit tests from file: views-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] Where the shell reads its own files
[🧪 test] no file of the interface is somebody else's to serve
[⚙️ assert] no font host
✅ got: #f
[⚙️ assert] and none of the hosts a face was fetched from
✅ got: #f
[⚙️ assert] no icon CDN
✅ got: #f
[⚙️ assert] and no typeface read from somebody's static assets
✅ got: #f
[🧪 test] a deployment that serves them elsewhere moves every one of them
[⚙️ assert] the stylesheet
✅ got: #t
[⚙️ assert] the type the page is set in
✅ got: #t
[⚙️ assert] the glyphs its controls wear
✅ got: #t
[⚙️ assert] and the icon, with no address left behind
✅ got: #t
[🧪 test] an instance that serves its own reads them off itself
[⚙️ assert] the stylesheet the page is laid out with
✅ got: #t
[⚙️ assert] and the icon the tab is marked with
✅ got: #t
+----------------------------------------------+
[📑 suite] The footer
[🧪 test] it points at the code, the manual and the licence
[⚙️ assert] where the source is
✅ got: #t
[⚙️ assert] where the manual is
✅ got: #t
[⚙️ assert] and where the licence is written out
✅ got: #t
[🧪 test] it offers the way back to the top
[⚙️ assert] the control says what it does
✅ got: #t
[⚙️ assert] and it is the one that scrolls
✅ got: #t
[🧪 test] no class is asked for twice
[⚙️ assert] a clean class attribute
✅ got: #f
[🧪 test] it states the version this instance runs
[⚙️ assert] the version is named
✅ got: #t
+----------------------------------------------+
[📑 suite] A page a browser can read
[🧪 test] no non-void element is closed as a self-closed tag
[⚙️ assert] each one is closed, not reopened
✅ got: #f
[🧪 test] the body the caller passed is the body that is served
[⚙️ assert] the content survives
✅ got: #t
[⚙️ assert] and it stands inside the document
✅ got: #t
+----------------------------------------------+
[📑 suite] A page a reader is reading
[🧪 test] the navigation is pinned while browsing
[⚙️ assert] the bar keeps its place
✅ got: #t
[⚙️ assert] just below the top edge
✅ got: #t
[🧪 test] the navigation is left to scroll away while reading
[⚙️ assert] the bar is still rendered
✅ got: #t
[⚙️ assert] nothing pins it
✅ got: #f
[⚙️ assert] no offset holds it there
✅ got: #f
[⚙️ assert] and it does not float above the text
✅ got: #f
[🧪 test] the whole template carries the reading mode down to the bar
[⚙️ assert] a reading page still has a bar
✅ got: #t
[⚙️ assert] but nothing pins it
✅ got: #f
[⚙️ assert] and every other page keeps it
✅ got: #t
+----------------------------------------------+
[📑 suite] Choosing a language
[🧪 test] every offered language is a row of the menu
[⚙️ assert] en_US is offered
✅ got: #t
[⚙️ assert] nl_NL is offered
✅ got: #t
[⚙️ assert] es_ES is offered
✅ got: #t
[⚙️ assert] ja_JP is offered
✅ got: #t
[🧪 test] the control posts the choice to the preference route
[⚙️ assert] the form names the route
✅ got: #t
[⚙️ assert] the menu is the posted field
✅ got: #t
[🧪 test] the control names itself for a reader and for assistive tech
[⚙️ assert] the label is bound to the menu
✅ got: #t
[⚙️ assert] and says what it is
✅ got: #t
[🧪 test] the page states the language it is being read in
[⚙️ assert] the language being read is the row shown
✅ got: #t
[⚙️ assert] and a language not being read is not
✅ got: #f
+----------------------------------------------+
[📑 suite] The languages a page offers
[🧪 test] a compiled catalog stands behind each offered language
[⚙️ assert] en_US has a catalog
✅ got: #t
[⚙️ assert] nl_NL has a catalog
✅ got: #t
[⚙️ assert] es_ES has a catalog
✅ got: #t
[⚙️ assert] ja_JP has a catalog
✅ got: #t
[🧪 test] each language is named in that language
[⚙️ assert] en_US is named
✅ got: #t
[⚙️ assert] nl_NL is named
✅ got: #t
[⚙️ assert] es_ES is named
✅ got: #t
[⚙️ assert] ja_JP is named
✅ got: #t
[🧪 test] every offered language is one this instance ships
[⚙️ assert] the four catalogs are offered
✅ got: (en_US nl_NL es_ES ja_JP)
ℹ️ info - ran 6 tasks in: 1 seconds, -755025 microseconds
running unit tests from file: auth-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] Reading a session
[🧪 test] an expired session is no session
[⚙️ assert] a validity that is already behind it
✅ got: #f
[🧪 test] every way of failing is the same noerror decrypting token: misc-error: (#f ~A (open-envelope: not a bewaking envelope (expected BWK3).) #f)error decrypting token: misc-error: (#f ~A (open-envelope: not a bewaking envelope (expected BWK3).) #f)
[⚙️ assert] no token at all
✅ got: #f
[⚙️ assert] a false token
✅ got: #f
[⚙️ assert] an empty cookie
✅ got: #f
[⚙️ assert] a cookie that is not even an envelope
✅ got: #f
[⚙️ assert] a cookie of some other shape
✅ got: #f
[🧪 test] a token that has been altered does not openerror decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)
[⚙️ assert] a truncated token
✅ got: #f
[⚙️ assert] a token with something appended
✅ got: #f
[🧪 test] a token sealed with the project's keys names its owner
[⚙️ assert] the owner's identifier comes back
✅ got: 8b3f6a1e-1c2d-4e5f-8a9b-0c1d2e3f4a5b
[⚙️ assert] and the permissions it was sealed with
✅ got: (wikimusic:song-create)
[⚙️ assert] the payload carries its own expiry
✅ got: #t
[🧪 test] a token sealed under another key is not ourserror decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)
[⚙️ assert] a token sealed with a key we do not hold
✅ got: #f
[⚙️ assert] nor one signed with another
✅ got: #f
[🧪 test] a route's permission has to be one the session holds
[⚙️ assert] the permission it holds is granted
✅ got: #t
[⚙️ assert] and so is a set it holds in full
✅ got: #t
[⚙️ assert] one it does not hold is refused
✅ got: #f
[⚙️ assert] with no permission asked for, a session is enough
✅ got: #t
+----------------------------------------------+
[📑 suite] The permissions column
[🧪 test] a list of permissions is read as written
[⚙️ assert] one permission
✅ got: (wikimusic:song-create)
[⚙️ assert] several, in order
✅ got: (wikimusic:song-create wikimusic:artist-delete)
[🧪 test] the column is read, never run
[⚙️ assert] a form naming a procedure comes back as data
✅ got: (system rm -rf /)
[⚙️ assert] and so does a lambda
✅ got: (lambda (x) x)
[🧪 test] anything that is not a list of permissions is an empty list
[⚙️ assert] an empty column
✅ got: ()
[⚙️ assert] no column at all
✅ got: ()
[⚙️ assert] an unreadable column
✅ got: ()
[⚙️ assert] a bare symbol
✅ got: ()
[⚙️ assert] a string
✅ got: ()
[🧪 test] a row written before the change still yields its permissions
[⚙️ assert] a quasiquoted list is unwrapped
✅ got: (wikimusic:song-create)
[⚙️ assert] the long spelling of it too
✅ got: (wikimusic:song-create)
+----------------------------------------------+
[📑 suite] Checking a password
[🧪 test] a row with no usable hash is refused rather than crashed on
[⚙️ assert] no hash is not a legacy hash
✅ got: #f
[⚙️ assert] nor is something that is not a string
✅ got: #f
[🧪 test] a hash was only derived from the one password
[⚙️ assert] a password missing its last character
✅ got: #f
[⚙️ assert] a password with the wrong case
✅ got: #f
[⚙️ assert] the empty password
✅ got: #f
[🧪 test] a hash that cannot be read is not a match
[⚙️ assert] no hash at all
✅ got: #f
[⚙️ assert] an argon2id salt that is not hexadecimal
✅ got: #f
[⚙️ assert] an argon2id cost that is not a number
✅ got: #f
[⚙️ assert] an argon2id hash with a field missing
✅ got: #f
[⚙️ assert] a pbkdf2 hash with a field missing
✅ got: #f
[🧪 test] the password a hash was derived from verifies
[⚙️ assert] the preferred scheme round trips
✅ got: #t
[⚙️ assert] and so does the fallback scheme
✅ got: #t
[⚙️ assert] the salt column no longer decides
✅ got: #t
[🧪 test] a password hashed before the change still verifies
[⚙️ assert] the right password still signs in
✅ got: #t
[⚙️ assert] the wrong one still does not
✅ got: #f
[⚙️ assert] and the row is recognisable as an old one
✅ got: #t
[⚙️ assert] while a derived hash is not
✅ got: #f
+----------------------------------------------+
[📑 suite] Passwords on file
[🧪 test] a hash names the scheme it was derived with
[⚙️ assert] an argon2id hash says so
✅ got: argon2id
[⚙️ assert] and carries iterations, memory, lanes, salt and key
✅ got: 6
[⚙️ assert] a pbkdf2 hash says so
✅ got: pbkdf2-sha256
[⚙️ assert] and carries iterations, salt and key
✅ got: 4
[🧪 test] the same password hashed twice is never the same hash
[⚙️ assert] the salt is drawn fresh every time
✅ got: #t
[🧪 test] the recorded cost is at least the cost that was chosen
[⚙️ assert] argon2id does at least two passes
✅ got: #t
[⚙️ assert] and asks for at least 19 MiB a pass
✅ got: #t
[⚙️ assert] pbkdf2 does at least 210000 iterations
✅ got: #t
ℹ️ info - ran 4 tasks in: 0 seconds, 91799 microseconds
running unit tests from file: assets-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] An icon set is copied with what is served of it
[🧪 test] a stylesheet with nothing to prune is left alone
[⚙️ assert] the text comes back as it went in
✅ got: @font-face {
font-family: "Phosphor";
src:
url("./Phosphor.woff2") format("woff2");
font-weight: normal;
font-style: normal;
font-display: block;
}
.ph {
font-family: "Phosphor" !important;
line-height: 1;
}
[🧪 test] what is left is still a stylesheet
[⚙️ assert] the braces still balance
✅ got: 2
[⚙️ assert] and they close as often
✅ got: 2
[⚙️ assert] the face keeps its family
✅ got: #t
[⚙️ assert] and the class the glyphs are worn with
✅ got: #t
[⚙️ assert] no clause is left dangling
✅ got: #t
[🧪 test] the face names the file that is beside it, and only it
[⚙️ assert] the woff2 clause ends the list
✅ got: #t
[⚙️ assert] the older woff is not named
✅ got: #t
[⚙️ assert] nor the ttf
✅ got: #t
[⚙️ assert] nor the svg
✅ got: #t
+----------------------------------------------+
[📑 suite] A fetched stylesheet names the files beside it
[🧪 test] each face is named for the block it stands in
[⚙️ assert] the addresses and the names line up
✅ got: ((https://fonts.gstatic.com/s/intelonemono/v25/aaa111.woff2 . intelonemono-symbols2-italic.woff2) (https://fonts.gstatic.com/s/intelonemono/v25/bbb222.woff2 . intelonemono-latin.woff2) (https://fonts.gstatic.com/s/plusjakartasans/v9/ccc333.woff2 . plusjakartasans-latin-italic.woff2))
[🧪 test] what the face says about itself is kept
[⚙️ assert] the format stays on the line
✅ got: #t
[⚙️ assert] so does what the face asks of the reader
✅ got: #t
[⚙️ assert] and the range it carries
✅ got: #t
[⚙️ assert] the line saying which subset follows
✅ got: #t
[⚙️ assert] and the stylesheet is as long as it was
✅ got: 27
[🧪 test] the address of the host it came from is gone
[⚙️ assert] no gstatic face is asked for
✅ got: #t
[⚙️ assert] nor any other absolute address
✅ got: #t
[⚙️ assert] the file beside it is named instead
✅ got: #t
[🧪 test] every face the answer named is a face to fetch
[⚙️ assert] three faces, three files
✅ got: ((https://fonts.gstatic.com/s/intelonemono/v25/aaa111.woff2 . intelonemono-symbols2-italic.woff2) (https://fonts.gstatic.com/s/intelonemono/v25/bbb222.woff2 . intelonemono-latin.woff2) (https://fonts.gstatic.com/s/plusjakartasans/v9/ccc333.woff2 . plusjakartasans-latin-italic.woff2))
+----------------------------------------------+
[📑 suite] A face is named after what it carries
[🧪 test] the family, the subset and the slope are all in the name
[⚙️ assert] a straight face names no slope
✅ got: intelonemono-latin.woff2
[⚙️ assert] a sloped one says so
✅ got: plusjakartasans-latin-italic.woff2
[⚙️ assert] and a subset that is not latin is kept apart
✅ got: intelonemono-symbols2-italic.woff2
ℹ️ info - ran 3 tasks in: 0 seconds, 23205 microseconds
running unit tests from file: sql-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] Matching a term
[🧪 test] the search statement a builder cannot write is still kracht's
[⚙️ assert] the apostrophe in the term is doubled
✅ got: #t
[⚙️ assert] no placeholder survives the substitution
✅ got: #f
[⚙️ assert] and the paging is written as numbers
✅ got: #t
[🧪 test] a LIKE condition renders as LIKE, with its term bound
[⚙️ assert] a wildcard term
✅ got: SELECT * FROM "songs" WHERE "display_name" LIKE '%x%'
+----------------------------------------------+
[📑 suite] Shaping a row
[🧪 test] only the named columns survive, in the named order
[⚙️ assert] the columns decide, not the attributes
✅ got: ((views . 2) (display-name . x))
[🧪 test] a row holding none of the columns is an error
[⚙️ assert] an insert with no columns is refused
✅ got: #t
[🧪 test] a column the attributes do not carry is simply left out
[⚙️ assert] so the table's own default can stand
✅ got: ((display-name . x))
[🧪 test] an attribute for an unlisted column cannot reach the statement
[⚙️ assert] a key wikimusic never names is dropped
✅ got: ((display-name . x))
+----------------------------------------------+
[📑 suite] Matching a set of identifiers
[🧪 test] and a NOT IN over an empty set matches everything
[⚙️ assert] NOT IN () becomes a true predicate
✅ got: SELECT * FROM "songs" WHERE 1 = 1
[🧪 test] an IN clause binds one value per identifier, in order
[⚙️ assert] two identifiers
✅ got: SELECT * FROM "songs" WHERE "identifier" IN ('a', 'b')
[🧪 test] an empty set matches nothing rather than everything
[⚙️ assert] IN () becomes a false predicate
✅ got: SELECT * FROM "songs" WHERE 1 = 0
+----------------------------------------------+
[📑 suite] Sorting
[🧪 test] a clause renders its column and its direction
[⚙️ assert] two clauses, in order
✅ got: "views" DESC, "display_name" ASC
[⚙️ assert] a column with no direction renders bare
✅ got: "display_name"
[⚙️ assert] and a hyphen becomes an underscore there too
✅ got: "last_edited_at" DESC
[🧪 test] a direction that is not a direction is an error
[⚙️ assert] so an unknown word cannot reach the statement
✅ got: #t
[🧪 test] both spellings of a sort are accepted
[⚙️ assert] one clause, not yet wrapped
✅ got: ((display-name asc))
[⚙️ assert] a clause list is left as it is
✅ got: ((views desc) (display-name asc))
[⚙️ assert] and nothing sorts by nothing
✅ got: ()
+----------------------------------------------+
[📑 suite] Accounting for placeholders
[🧪 test] the number of values has to match the number of placeholders
[⚙️ assert] a value too few is an error rather than a guess
✅ got: #t
[⚙️ assert] a value too many is an error too
✅ got: #t
[⚙️ assert] a placeholder with no value is refused, not left behind
✅ got: #t
[🧪 test] a rendered statement holds no placeholder any more
[⚙️ assert] no question mark survives the substitution
✅ got: #f
[⚙️ assert] and the rest of the statement is intact
✅ got: #t
[🧪 test] something that is neither a query nor a string is refused
[⚙️ assert] a number is not a statement
✅ got: #t
[⚙️ assert] nor is a symbol
✅ got: #t
+----------------------------------------------+
[📑 suite] Rendering a statement for the driver
[🧪 test] a statement string is passed through untouched
[⚙️ assert] a plain string
✅ got: SELECT 1
[⚙️ assert] a statement with a quoted value of its own
✅ got: SELECT 'x'
[🧪 test] a value is rendered as a literal, and its quotes are doubled
[⚙️ assert] a string is quoted
✅ got: SELECT * FROM "songs" WHERE "display_name" = 'x'
[⚙️ assert] an apostrophe inside a value is doubled
✅ got: SELECT * FROM "songs" WHERE "display_name" = 'O''Brien'
[⚙️ assert] a value that means to end the string cannot
✅ got: SELECT * FROM "songs" WHERE "display_name" = '''; DROP TABLE users; --'
[⚙️ assert] so every quote it carries is paired
✅ got: 4
[🧪 test] a number and a boolean are not quoted
[⚙️ assert] a number is written as itself
✅ got: SELECT * FROM "songs" WHERE "views" = 3
[⚙️ assert] a true value is written as 1
✅ got: SELECT * FROM "songs" WHERE "views" = 1
[🧪 test] column names are quoted as identifiers
[⚙️ assert] a hyphenated symbol is spelled underscore
✅ got: UPDATE "users" SET "password" = 'argon2id$x' WHERE "identifier" = 'id-1'
ℹ️ info - ran 6 tasks in: 0 seconds, 11250 microseconds
running unit tests from file: guitarpro-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] The key a header names
[🧪 test] a number no signature has is not named at all
[⚙️ assert] one flat too many
✅ got: #f
[⚙️ assert] and one sharp too many
✅ got: #f
[🧪 test] each signature of the fifteen is named
[⚙️ assert] no accidentals is C
✅ got: C
[⚙️ assert] two flats is B flat
✅ got: Bb
[⚙️ assert] one sharp is G
✅ got: G
[⚙️ assert] seven sharps is C sharp
✅ got: C#
[⚙️ assert] seven flats is C flat
✅ got: Cb
+----------------------------------------------+
[📑 suite] What the header of a Guitar Pro 5 file declares
[🧪 test] a file of the right generation that is cut short is refused
[⚙️ assert] a header missing its last fields
✅ got: #f
[⚙️ assert] a file missing its whole header
✅ got: #f
[🧪 test] every field of a written file is read back
[⚙️ assert] the release
✅ got: (5 10)
[⚙️ assert] the title
✅ got: a title
[⚙️ assert] the artist, two fields along
✅ got: an artist
[⚙️ assert] the notice lines, in order
✅ got: (first notice second notice)
[⚙️ assert] the lyrics
✅ got: (the words of the song)
[⚙️ assert] the tempo
✅ got: 132
[⚙️ assert] the key signature
✅ got: -2
[⚙️ assert] the key it names
✅ got: Bb
[⚙️ assert] the measures
✅ got: 42
[⚙️ assert] the tracks
✅ got: 3
[🧪 test] a file whose counts cannot be true is refused
[⚙️ assert] a negative measure count
✅ got: #f
[🧪 test] a header written by a release after 5.0 is read the same way
[⚙️ assert] the tempo of a 5.1 file
✅ got: 155
[⚙️ assert] the track count of a 5.1 file
✅ got: 5
[⚙️ assert] the tempo of a 5.0 file
✅ got: 155
[⚙️ assert] the track count of a 5.0 file
✅ got: 5
[🧪 test] the reader consumes exactly the header and nothing more
[⚙️ assert] the plain file
✅ got: 1063
[⚙️ assert] a file with no title
✅ got: 1056
[⚙️ assert] a file with a long title
✅ got: 1093
[⚙️ assert] a file with two notice lines
✅ got: 1092
[⚙️ assert] a file of the earlier release
✅ got: 1058
[⚙️ assert] a file with numbers at their widest
✅ got: 1063
[🧪 test] a file that is not a readable Guitar Pro 5 file is answered with #f
[⚙️ assert] nothing at all
✅ got: #f
[⚙️ assert] a text file
✅ got: #f
[⚙️ assert] a pdf
✅ got: #f
[⚙️ assert] a Guitar Pro 4 file
✅ got: #f
[🧪 test] a field whose two lengths disagree is refused
[⚙️ assert] a string that claims a length it does not have
✅ got: #f
+----------------------------------------------+
[📑 suite] What a data URL holds
[🧪 test] a base64 data URL is one, and its bytes come back
[⚙️ assert] a file posted by a browser
✅ got: #t
[⚙️ assert] the bytes after the comma
✅ got: hi
[🧪 test] a version's own file is read through its data URL
[⚙️ assert] the title
✅ got: through a data url
[⚙️ assert] the tempo
✅ got: 90
[🧪 test] an empty value is not a data URL
[⚙️ assert] the empty string
✅ got: #f
[⚙️ assert] nor is a path
✅ got: #f
[🧪 test] a data URL that holds something other than base64 holds no bytes
[⚙️ assert] a text data URL
✅ got: #f
[⚙️ assert] a base64 text that does not decode
✅ got: #f
+----------------------------------------------+
[📑 suite] What a base64 text spells
[🧪 test] a text broken across lines is read as one
[⚙️ assert] whitespace between the characters is ignored
✅ got: hello
[🧪 test] a text whose bytes are known decodes to them
[⚙️ assert] two characters
✅ got: h
[⚙️ assert] three characters
✅ got: hi
[⚙️ assert] five characters
✅ got: hello
[⚙️ assert] six characters is two whole groups
✅ got: hello!
[🧪 test] the encoding a browser does round-trips through the decoder
[⚙️ assert] one character, the shortest text that needs padding
✅ got: a
[⚙️ assert] one whole group of three
✅ got: abc
[⚙️ assert] a word
✅ got: wikimusic
[⚙️ assert] a text whose bytes are not its characters
✅ got: a title with an accent: café
[🧪 test] a text that is not base64 is refused rather than guessed at
[⚙️ assert] a character outside the alphabet
✅ success catching error: misc-error: (#f base64-decode-string: not a base64 character ~S (*) #f)
[⚙️ assert] a text that ends in a lone character
✅ success catching error: misc-error: (#f base64-decode-string: the text ends in a lone base64 character () #f)
ℹ️ info - ran 4 tasks in: 0 seconds, 38913 microseconds
running unit tests from file: guitarpro-view-spec.scm, entrypoint: spec
ℹ️ info - shuffled with seed 85110602 (replay with VERITAS_SEED=85110602)
+----------------------------------------------+
[📑 suite] The section a version's tab is offered in
[🧪 test] a tab whose header cannot be read says so and is still a download
[⚙️ assert] the sentence
✅ got: #t
[🧪 test] a version carrying no tab is offered none
[⚙️ assert] a field a reader never touched
✅ got: ()
[⚙️ assert] and a version whose tab is not a tab at all
✅ got: ()
[🧪 test] the words the player shows are the page's own
[⚙️ assert] while it loads
✅ got: #t
[⚙️ assert] once it is drawn
✅ got: #t
[⚙️ assert] and when it cannot be drawn
✅ got: #t
[⚙️ assert] the state while loading is a place the script reaches
✅ got: #t
[⚙️ assert] and the state once drawn
✅ got: #t
[⚙️ assert] and the state that failed
✅ got: #t
[🧪 test] and the offer to draw it here, which is a button and not a script
[⚙️ assert] the button
✅ got: #t
[🧪 test] each version's section is named after the version it is
[⚙️ assert] the score of the second version
✅ got: #t
[⚙️ assert] and not the first version's
✅ got: #t
[🧪 test] the controls and the score are on the page before they are used
[⚙️ assert] the controls start hidden
✅ got: #t
[⚙️ assert] the place a score is drawn in
✅ got: #t
[🧪 test] a version carrying a tab offers it for download
[⚙️ assert] the link to the file
✅ got: #t
[⚙️ assert] and the name it is saved under
✅ got: #t
[🧪 test] playing and stopping are offered once there is something to play
[⚙️ assert] playing
✅ got: #t
[⚙️ assert] and stopping
✅ got: #t
+----------------------------------------------+
[📑 suite] The name a tab is saved under
[🧪 test] the name says which song and which version it is
[⚙️ assert] the two together
✅ got: A Song - v1.gp5
[🧪 test] a name is still made of nothing
[⚙️ assert] a version with no name of its own
✅ got: wikimusic-tab.gp5
[⚙️ assert] and a song the page has not read yet
✅ got: wikimusic-tab.gp5
[🧪 test] the characters a file name cannot hold are replaced
[⚙️ assert] a song whose name holds a slash and a colon
✅ got: A-B- C-D-.gp5
+----------------------------------------------+
[📑 suite] What a tab's own header is shown as
[🧪 test] every field a tab's author filled in is listed
[⚙️ assert] the title
✅ got: a title
[⚙️ assert] the artist
✅ got: an artist
[⚙️ assert] the album
✅ got: an album
[⚙️ assert] who tabbed it
✅ got: a tabber
[🧪 test] a tempo is written as a reader reads it
[⚙️ assert] a tempo in beats per minute
✅ got: 132 bpm
[🧪 test] a field its author left empty is not listed at all
[⚙️ assert] an empty artist
✅ got: #f
[⚙️ assert] an album that was never read
✅ got: #f
[⚙️ assert] a key with no name
✅ got: #f
[🧪 test] the numbers a header always carries are always listed
[⚙️ assert] the measures
✅ got: 42
[⚙️ assert] the tracks
✅ got: 3
[🧪 test] a key is listed by the name of the key and not the count
[⚙️ assert] two flats is B flat
✅ got: Bb
ℹ️ info - ran 3 tasks in: 0 seconds, 27818 microseconds
finished running tests
/root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/controller-spec.scm.go
;;; compiling ./test/veritas/unit/views-spec.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/views-spec.scm.go
;;; compiling ./test/veritas/unit/auth-spec.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/auth-spec.scm.go
;;; compiling ./test/veritas/unit/assets-spec.scm
;;; compiling ./resources/assets/fetch.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/resources/assets/fetch.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/assets-spec.scm.go
;;; compiling ./test/veritas/unit/sql-spec.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/sql-spec.scm.go
;;; compiling ./test/veritas/unit/guitarpro-spec.scm
;;; compiling ./lib/wikimusic/guitarpro.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/guitarpro.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/guitarpro-spec.scm.go
;;; compiling ./test/veritas/unit/guitarpro-view-spec.scm
;;; compiling ./app/views/song-content-view.scm
;;; compiling ./lib/wikimusic/domain/guitar-chord-guide.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/lib/wikimusic/domain/guitar-chord-guide.scm.go
WARNING: (app views song-content-view): imported module (hygguile hygguile) overrides core binding `select'
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/app/views/song-content-view.scm.go
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/wikimusic/trunk/test/veritas/unit/guitarpro-view-spec.scm.go
--------------------------------------------------------------
Maak 0.14.0: the infinitely extensible command runner
Loading tasks from Maak file: /etc/byggsteg/job-clone/wikimusic/trunk/maak.scm
Executing Maak tasks: test
--------------------------------------------------------------
=> Running Maak task: test
Run the project's test suite, one spec at a time, from test/veritas.
Executing: guix time-machine --channels=channels.scm -- shell -m manifest.scm -- guile --fresh-auto-compile -L ./lib -L ./test -L . -c '(load "env.scm")(begin (setlocale LC_ALL "C.UTF-8") (use-modules (veritas runner)) (run-tests))'
;;; note: source file /etc/byggsteg/job-clone/wikimusic/trunk/maak.scm
;;; newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.6/etc/byggsteg/job-clone/wikimusic/trunk/maak.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;; or pass the --no-auto-compile argument to disable.
;;; compiling /etc/byggsteg/job-clone/wikimusic/trunk/maak.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.6/etc/byggsteg/job-clone/wikimusic/trunk/maak.scm.go
→ running command: cd /etc/byggsteg/job-clone/wikimusic/trunk && sudo herd enable wikimusic-daemon || true && sudo herd restart wikimusic-daemon || true
Enabled service wikimusic-daemon.
Service wikimusic-daemon has been started.
→ running command: cd /etc/byggsteg/job-clone/wikimusic/trunk && sudo maak deploy
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
Warning (emacs): Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see ‘org-html-htmlize-output-type’)
finished publishing Wikimusic manual
--------------------------------------------------------------
Maak 0.14.0: the infinitely extensible command runner
Loading tasks from Maak file: /etc/byggsteg/job-clone/wikimusic/trunk/maak.scm
Executing Maak tasks: deploy
--------------------------------------------------------------
=> Running Maak task: deploy
Deploy the project's documentation.
The manual is rendered from the README and served under `manuals/wikimusic',
which is where a reader of the site is sent.
Execute command:
guix time-machine --channels=channels.scm -- shell -m manifest.scm -- emacs -Q --batch --eval '(progn (require (quote ox-html)) (setq org-html-prefer-user-labels t) (find-file "./README.org") (org-html-export-to-html) (message "finished publishing Wikimusic manual"))'
Executing: guix time-machine --channels=channels.scm -- shell -m manifest.scm -- emacs -Q --batch --eval '(progn (require (quote ox-html)) (setq org-html-prefer-user-labels t) (find-file "./README.org") (org-html-export-to-html) (message "finished publishing Wikimusic manual"))'
removed '/srv/http/jointhefreeworld.org/manuals/wikimusic/index.html'
renamed 'README.html' -> '/srv/http/jointhefreeworld.org/manuals/wikimusic/index.html'