docs: document frontend testing conventions - #1984
Conversation
WalkthroughThe PR updates frontend testing documentation to establish consistent Vitest standards. CONTRIBUTING.md mandates vitest specs for frontend changes and manual smoke testing for jsdom-incompatible scenarios. web/AGENTS.md provides detailed guidance on Vitest configuration, assertion patterns, mocking strategies, and jsdom constraints. ChangesFrontend Testing Guidelines
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@AGENTS.md`:
- Around line 117-128: Update AGENTS.md to point the example hook path to an
existing test pattern (replace the non-existent reference to
web/src/hooks/torrent-table/ with web/src/hooks/useInstanceMetadata.test.tsx)
and adjust the guidance text so assertions and mocking advice match our actual
tests: explicitly state Vitest uses environment: "jsdom", globals: false, no
setup files, require importing test globals (describe, it, expect, vi), forbid
jest-dom matchers (e.g., toBeInTheDocument) and show using plain DOM checks
(textContent, getAttribute, expect(node).toBeNull()), and clarify the
vi.hoisted() recommendation (note use only when a value is referenced inside
vi.mock factories or soften to “prefer vi.hoisted() for stable singletons”);
keep the doc examples and wording aligned with existing repo patterns and tests
such as useInstanceMetadata.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f5200d08-c8f0-46a2-8658-016a40d1643b
📒 Files selected for processing (2)
AGENTS.mdCONTRIBUTING.md
| ### Frontend tests | ||
|
|
||
| Ship colocated `*.test.ts(x)` specs with frontend changes. Prefer extracting logic into hooks (`web/src/hooks/`) and pure helpers (`web/src/lib/`) so it is unit-testable without mounting the whole tree (see `web/src/hooks/torrent-table/` for the pattern). | ||
|
|
||
| Vitest runs with `globals: false` + jsdom and **no setup file**, so: | ||
|
|
||
| - Import test globals explicitly: `import { describe, it, expect, vi } from "vitest"`. Use `render` / `renderHook` / `act` from `@testing-library/react`. | ||
| - **No jest-dom matchers** (`toBeInTheDocument`, `toHaveTextContent`, …). Assert with plain DOM: `el.textContent`, `el.getAttribute(...)`, `expect(node).toBeNull()`. | ||
| - When mounting a component with effects, mock its boundaries (`@/lib/api`, router, context providers, `useVirtualizer`, query hooks) and return a **stable singleton** from each mock — fresh objects per render make effects loop and OOM the worker. Use `vi.hoisted()` for values referenced inside `vi.mock` factories (hoisted above imports). Prefer prop-capturing stubs to assert wiring. | ||
|
|
||
| jsdom does no real layout, scroll, or pointer/drag work — it renders **zero virtual rows** and cannot exercise virtualization, dnd-kit, or scroll restoration. Unit-test the extractable logic (reorder math, row-height mapping, handler wiring) and **manually smoke** anything visual or interactive; a green suite is not full coverage. Run targeted with `cd web && npx vitest run <path>`; CI runs the full suite via `make test-frontend`. | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify Vitest configuration and example path reference
echo "=== Checking Vitest configuration ==="
if [ -f "web/vitest.config.ts" ] || [ -f "web/vitest.config.js" ]; then
echo "Found Vitest config:"
fd -t f 'vitest.config\.(ts|js)' web/ --exec cat {}
else
echo "No vitest.config found in web/"
fi
echo -e "\n=== Checking for setup files ==="
fd -t f 'setup.*\.(ts|js)' web/ --exec echo "Found: {}"
echo -e "\n=== Checking globals configuration ==="
rg -A 5 "globals:" web/vitest.config.ts web/vitest.config.js 2>/dev/null || echo "No globals config found"
echo -e "\n=== Checking for jest-dom usage ==="
rg -n "`@testing-library/jest-dom`" web/src/ 2>/dev/null || echo "No jest-dom imports found"
echo -e "\n=== Verifying example path exists ==="
if [ -d "web/src/hooks/torrent-table/" ]; then
echo "✓ web/src/hooks/torrent-table/ exists"
fd -t f . web/src/hooks/torrent-table/ --exec echo " {}"
else
echo "✗ web/src/hooks/torrent-table/ does not exist"
fi
echo -e "\n=== Checking for vi.hoisted() usage in tests ==="
rg -n "vi\.hoisted\(" web/src/ --glob '*.test.ts*' -C 2 | head -20 || echo "No vi.hoisted() usage found in tests"
echo -e "\n=== Sample test file structure ==="
fd -t f '\.test\.tsx?$' web/src/ | head -3 | while read -r file; do
echo "File: $file"
head -20 "$file"
echo "---"
doneRepository: autobrr/qui
Length of output: 3632
Fix AGENTS.md frontend testing guidance (wrong example path + align test-mocking assertions)
In AGENTS.md (lines 117-128), web/src/hooks/torrent-table/ is referenced but the directory doesn’t exist—update the example to a real hook/unit-test pattern (e.g., web/src/hooks/useInstanceMetadata.test.tsx).
The Vitest config in web/vitest.config.ts matches the doc’s setup (environment: "jsdom", globals: false, and no setupFiles/setupFilesAfterEnv). No @testing-library/jest-dom imports were found in web/src/; if keeping the “no jest-dom matchers” rule, also ensure matcher usage like toBeInTheDocument doesn’t appear. The vi.hoisted() recommendation should be backed by an existing repo pattern (or softened) based on actual test code.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@AGENTS.md` around lines 117 - 128, Update AGENTS.md to point the example hook
path to an existing test pattern (replace the non-existent reference to
web/src/hooks/torrent-table/ with web/src/hooks/useInstanceMetadata.test.tsx)
and adjust the guidance text so assertions and mocking advice match our actual
tests: explicitly state Vitest uses environment: "jsdom", globals: false, no
setup files, require importing test globals (describe, it, expect, vi), forbid
jest-dom matchers (e.g., toBeInTheDocument) and show using plain DOM checks
(textContent, getAttribute, expect(node).toBeNull()), and clarify the
vi.hoisted() recommendation (note use only when a value is referenced inside
vi.mock factories or soften to “prefer vi.hoisted() for stable singletons”);
keep the doc examples and wording aligned with existing repo patterns and tests
such as useInstanceMetadata.
Add a Frontend Tests section to web/AGENTS.md capturing the non-obvious, load-bearing conventions: vitest runs with globals:false + jsdom + no setup file (import test globals from "vitest", no jest-dom matchers, plain DOM assertions), stable-singleton mocks + vi.hoisted to avoid effect-loop OOMs, and the jsdom limits (zero virtual rows -> manual smoke for virtualization/DnD/scroll). Add a matching expectation bullet to CONTRIBUTING.md. Rebased onto develop, which moved frontend rules from the root AGENTS.md into web/AGENTS.md; the conventions land there now rather than in the (since rewritten) root doc. Surfaced while building test coverage during the #1963 table decomposition.
53aef3e to
8d0568b
Compare
|
Rebased onto develop's #1995 rewrote the root Resolved by keeping develop's rewritten root A fresh pull/checkout of this branch is needed. |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
web/AGENTS.md (3)
19-19: ⚡ Quick winAdd
cleanupto the import guidance.Since
globals: falsedisables auto-cleanup (confirmed inSeasonPackCategoryRulesEditor.test.tsx), developers need to import and callcleanupexplicitly inafterEach. Consider addingcleanupto the listed imports from@testing-library/react.📝 Suggested addition
- - Import test globals explicitly: `import { describe, it, expect, vi } from "vitest"`; use `render` / `renderHook` / `act` from `@testing-library/react`. + - Import test globals explicitly: `import { describe, it, expect, vi } from "vitest"`; use `render` / `renderHook` / `act` / `cleanup` from `@testing-library/react`. Call `cleanup()` in `afterEach` since auto-cleanup is disabled.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/AGENTS.md` at line 19, Update the import guidance to include cleanup: instruct developers to import cleanup from "`@testing-library/react`" alongside render / renderHook / act (e.g., import { render, renderHook, act, cleanup } from "`@testing-library/react`") and remind them to call cleanup in an afterEach (e.g., afterEach(() => cleanup())) so tests with globals: false properly teardown DOM between tests; reference the symbols render, renderHook, act, cleanup, and afterEach in the guidance.Source: MCP tools
22-22: ⚡ Quick winClarify "zero virtual rows" phrasing for precision.
The phrase "it renders zero virtual rows" could be misread. The intended meaning appears to be that jsdom natively cannot exercise virtualization due to lack of layout measurements, which would result in no rows being rendered by an unmocked virtualizer. The mock in
TorrentTableOptimized.smoke.test.tsxworks around this by deterministically rendering all rows. Consider rephrasing for clarity.📝 Suggested clarification
-- jsdom does no real layout, scroll, or pointer/drag work — it renders **zero virtual rows** and cannot exercise virtualization, dnd-kit, or scroll restoration. Unit-test the extractable logic (reorder math, row-height mapping, handler wiring) and **manually smoke** anything visual or interactive; a green suite is not full coverage. Run targeted with `cd web && npx vitest run <path>`; CI runs the full suite via `make test-frontend`. +- jsdom does no real layout, scroll, or pointer/drag work — **virtualizers return empty results** without mocking and cannot exercise virtualization, dnd-kit, or scroll restoration. Unit-test the extractable logic (reorder math, row-height mapping, handler wiring) and **manually smoke** anything visual or interactive; a green suite is not full coverage. Run targeted with `cd web && npx vitest run <path>`; CI runs the full suite via `make test-frontend`.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/AGENTS.md` at line 22, Rephrase the sentence that currently reads "it renders **zero virtual rows**" to clearly state that jsdom provides no layout/measurement APIs so unmocked virtualizers will render no rows (e.g., "jsdom provides no layout measurements, so virtualizers typically render nothing unless mocked"); mention the existing test workaround in TorrentTableOptimized.smoke.test.tsx which deterministically renders all rows to exercise logic. Update AGENTS.md accordingly so the intent and the test workaround are unambiguous.Source: MCP tools
51-53: 💤 Low valueOptional: Consider varying sentence openings.
Static analysis flagged three successive sentences starting with "Add" (lines 51-53). The parallel structure aids scannability in this procedural checklist, so the repetition is arguably beneficial. If you prefer variety, consider rephrasing one step.
📝 Optional rephrase example
1. Add all 10 namespace JSON files under `web/src/i18n/locales/<lang>/`. 2. Add code to `supportedLanguages` and display name to `languageNames` in `web/src/i18n/index.ts`. -3. Add/adapt a locale coverage script if the locale is not `zh-CN`. +3. Create or adapt a locale coverage script if the locale is not `zh-CN`. 4. Run `pnpm check:i18n`.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/AGENTS.md` around lines 51 - 53, The three checklist items in AGENTS.md all start with the verb "Add", making the openings repetitive; update one of the three bullets (the lines that list adding namespace JSON files, updating supportedLanguages/languageNames, and adapting the locale coverage script) to use a different opening verb or phrasing (e.g., "Place", "Update", "Adapt", or rephrase as "Include X in Y") so the list keeps parallel structure but avoids identical sentence starts while preserving the original meaning.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@web/AGENTS.md`:
- Line 19: Update the import guidance to include cleanup: instruct developers to
import cleanup from "`@testing-library/react`" alongside render / renderHook / act
(e.g., import { render, renderHook, act, cleanup } from
"`@testing-library/react`") and remind them to call cleanup in an afterEach (e.g.,
afterEach(() => cleanup())) so tests with globals: false properly teardown DOM
between tests; reference the symbols render, renderHook, act, cleanup, and
afterEach in the guidance.
- Line 22: Rephrase the sentence that currently reads "it renders **zero virtual
rows**" to clearly state that jsdom provides no layout/measurement APIs so
unmocked virtualizers will render no rows (e.g., "jsdom provides no layout
measurements, so virtualizers typically render nothing unless mocked"); mention
the existing test workaround in TorrentTableOptimized.smoke.test.tsx which
deterministically renders all rows to exercise logic. Update AGENTS.md
accordingly so the intent and the test workaround are unambiguous.
- Around line 51-53: The three checklist items in AGENTS.md all start with the
verb "Add", making the openings repetitive; update one of the three bullets (the
lines that list adding namespace JSON files, updating
supportedLanguages/languageNames, and adapting the locale coverage script) to
use a different opening verb or phrasing (e.g., "Place", "Update", "Adapt", or
rephrase as "Include X in Y") so the list keeps parallel structure but avoids
identical sentence starts while preserving the original meaning.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 9fda70ee-7fab-429f-998b-958f358ddd22
📒 Files selected for processing (2)
CONTRIBUTING.mdweb/AGENTS.md
✅ Files skipped from review due to trivial changes (1)
- CONTRIBUTING.md
…#160) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.20.0` → `v1.21.0` | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/7) for more information. --- ### Release Notes <details> <summary>autobrr/qui (ghcr.io/autobrr/qui)</summary> ### [`v1.21.0`](https://github.com/autobrr/qui/releases/tag/v1.21.0) [Compare Source](autobrr/qui@v1.20.0...v1.21.0) ##### Changelog ##### New Features - [`51b29a1`](autobrr/qui@51b29a1): feat(api): add GET /api/version reporting the running version ([#​2060](autobrr/qui#2060)) ([@​s0up4200](https://github.com/s0up4200)) - [`98348f1`](autobrr/qui@98348f1): feat(automations): add RLS\_YEAR release-year condition ([#​2003](autobrr/qui#2003)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`58cc7cb`](autobrr/qui@58cc7cb): feat(automations): add tracker status and message conditions ([#​2006](autobrr/qui#2006)) ([@​luckylittle](https://github.com/luckylittle)) - [`2176a92`](autobrr/qui@2176a92): feat(automations): list configured indexer trackers in workflow selector ([#​2005](autobrr/qui#2005)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`2de926e`](autobrr/qui@2de926e): feat(i18n): add Italian (it) translation ([#​2011](autobrr/qui#2011)) ([@​s0up4200](https://github.com/s0up4200)) - [`7b66655`](autobrr/qui@7b66655): feat(i18n): add Korean (ko) translation ([#​2042](autobrr/qui#2042)) ([@​jussaw](https://github.com/jussaw)) - [`2c06a3d`](autobrr/qui@2c06a3d): feat(i18n): add Ukrainian (uk) translation ([#​2032](autobrr/qui#2032)) ([@​rodion981](https://github.com/rodion981)) - [`ef8da0b`](autobrr/qui@ef8da0b): feat(sse): keep cached torrents with a staleness badge when qBittorrent is slow ([#​2057](autobrr/qui#2057)) ([@​s0up4200](https://github.com/s0up4200)) - [`38ebb6e`](autobrr/qui@38ebb6e): feat(web): add file priority controls to torrent file views ([#​2062](autobrr/qui#2062)) ([@​jussaw](https://github.com/jussaw)) ##### Bug Fixes - [`12ac536`](autobrr/qui@12ac536): fix(ci): skip release binary build on main pushes ([#​2008](autobrr/qui#2008)) ([@​s0up4200](https://github.com/s0up4200)) - [`57210a3`](autobrr/qui@57210a3): fix(crossseed): drop resolution token from TV search queries ([#​2017](autobrr/qui#2017)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`791bc7d`](autobrr/qui@791bc7d): fix(crossseed): inject rootless single-file adds into matched folder ([#​2029](autobrr/qui#2029)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`3da437f`](autobrr/qui@3da437f): fix(crossseed): re-query indexers with no usable hit in the alternate connector pass ([#​2002](autobrr/qui#2002)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`8e8b6d9`](autobrr/qui@8e8b6d9): fix(database): prevent int4 sequence exhaustion in Postgres string interning ([#​2015](autobrr/qui#2015)) ([@​s0up4200](https://github.com/s0up4200)) - [`c7e08b9`](autobrr/qui@c7e08b9): fix(db): index string\_pool FK columns so GC stops timing out ([#​2051](autobrr/qui#2051)) ([@​s0up4200](https://github.com/s0up4200)) - [`2553f75`](autobrr/qui@2553f75): fix(docs): use relative file paths for markdown links ([#​2013](autobrr/qui#2013)) ([@​nasenov](https://github.com/nasenov)) - [`8a9c2fc`](autobrr/qui@8a9c2fc): fix(i18n): improve French translation, fix hardcoded UI statuses, and update agent rules ([#​2014](autobrr/qui#2014)) ([@​OlziYT](https://github.com/OlziYT)) - [`190d936`](autobrr/qui@190d936): fix(jackett): decouple cache persistence from SkipHistory ([#​2056](autobrr/qui#2056)) ([@​jussaw](https://github.com/jussaw)) - [`91ad7e4`](autobrr/qui@91ad7e4): fix(pprof): bind to configurable loopback address instead of :6060 ([#​2044](autobrr/qui#2044)) ([@​s0up4200](https://github.com/s0up4200)) - [`10e2d02`](autobrr/qui@10e2d02): fix(qbittorrent): serve stale app info/preferences when refresh fails ([#​2054](autobrr/qui#2054)) ([@​s0up4200](https://github.com/s0up4200)) - [`6d3b04c`](autobrr/qui@6d3b04c): fix(sse): resolve sync-error staleness stamp off the sync-loop callback ([#​2065](autobrr/qui#2065)) ([@​s0up4200](https://github.com/s0up4200)) - [`677e8f4`](autobrr/qui@677e8f4): fix(sse): send torrent page deltas instead of full snapshots ([#​2047](autobrr/qui#2047)) ([@​s0up4200](https://github.com/s0up4200)) - [`a4d252b`](autobrr/qui@a4d252b): fix(sse): size full-sync timeout to prevent permanent disconnect on large instances ([#​2037](autobrr/qui#2037)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`4f375c6`](autobrr/qui@4f375c6): fix(torrents): route unified view exports to the owning instance ([#​2018](autobrr/qui#2018)) ([@​s0up4200](https://github.com/s0up4200)) - [`d49e168`](autobrr/qui@d49e168): fix(web): move instance status bar back to bottom of screen ([#​2024](autobrr/qui#2024)) ([@​OlziYT](https://github.com/OlziYT)) - [`a69ae69`](autobrr/qui@a69ae69): fix(web): prevent framer-motion tab indicator from triggering layout shifts ([#​2025](autobrr/qui#2025)) ([@​OlziYT](https://github.com/OlziYT)) ##### Other Changes - [`860b5bb`](autobrr/qui@860b5bb): chore(deps): bump anthropics/claude-code-action from 1.0.140 to 1.0.148 in the github group ([#​2045](autobrr/qui#2045)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`0b23a7d`](autobrr/qui@0b23a7d): chore(deps): bump the github group with 2 updates ([#​2031](autobrr/qui#2031)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`1fea36b`](autobrr/qui@1fea36b): docs: document frontend testing conventions ([#​1984](autobrr/qui#1984)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`f3443ec`](autobrr/qui@f3443ec): docs: promote multi-language support ([#​2009](autobrr/qui#2009)) ([@​s0up4200](https://github.com/s0up4200)) - [`df88e63`](autobrr/qui@df88e63): test(web): add coverage for hooks and lib/api.ts contract layer ([#​1931](autobrr/qui#1931)) ([#​1998](autobrr/qui#1998)) ([@​nitrobass24](https://github.com/nitrobass24)) **Full Changelog**: <autobrr/qui@v1.20.0...v1.21.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.21.0` - `docker pull ghcr.io/autobrr/qui:latest` ##### What to do next? - Join our [Discord server](https://discord.autobrr.com/qui) Thank you for using qui! </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/Warsaw) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDMuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI0My4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbInJlbm92YXRlL2NvbnRhaW5lciIsInR5cGUvbWlub3IiXX0=--> Reviewed-on: https://git.ajgon.casa/deedee/mark13/pulls/160
… (#200) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.20.0` → `v1.22.0` | --- ### Release Notes <details> <summary>autobrr/qui (ghcr.io/autobrr/qui)</summary> ### [`v1.22.0`](https://github.com/autobrr/qui/releases/tag/v1.22.0) [Compare Source](autobrr/qui@v1.21.0...v1.22.0) ##### Changelog ##### New Features - [`5b9326e`](autobrr/qui@5b9326e): feat(web): add copy path option to content tab context menu ([#​933](autobrr/qui#933)) ([@​lenisko](https://github.com/lenisko)) - [`3a4383d`](autobrr/qui@3a4383d): feat(web): add kanagawa themes ([#​2069](autobrr/qui#2069)) ([@​notmarek](https://github.com/notmarek)) - [`db77a17`](autobrr/qui@db77a17): feat(web): shift+click range select in torrent content tab ([#​2081](autobrr/qui#2081)) ([@​jussaw](https://github.com/jussaw)) ##### Bug Fixes - [`b563d4b`](autobrr/qui@b563d4b): fix(sync): keep SSE aggregates fresh without tracker hydration ([#​2072](autobrr/qui#2072)) ([@​Audionut](https://github.com/Audionut)) ##### Other Changes - [`d428313`](autobrr/qui@d428313): chore(deps): bump the github group with 5 updates ([#​2073](autobrr/qui#2073)) ([@​dependabot](https://github.com/dependabot)\[bot]) **Full Changelog**: <autobrr/qui@v1.21.0...v1.22.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.22.0` - `docker pull ghcr.io/autobrr/qui:latest` ##### What to do next? - Join our [Discord server](https://discord.autobrr.com/qui) Thank you for using qui! ### [`v1.21.0`](https://github.com/autobrr/qui/releases/tag/v1.21.0) [Compare Source](autobrr/qui@v1.20.0...v1.21.0) ##### Changelog ##### New Features - [`51b29a1`](autobrr/qui@51b29a1): feat(api): add GET /api/version reporting the running version ([#​2060](autobrr/qui#2060)) ([@​s0up4200](https://github.com/s0up4200)) - [`98348f1`](autobrr/qui@98348f1): feat(automations): add RLS\_YEAR release-year condition ([#​2003](autobrr/qui#2003)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`58cc7cb`](autobrr/qui@58cc7cb): feat(automations): add tracker status and message conditions ([#​2006](autobrr/qui#2006)) ([@​luckylittle](https://github.com/luckylittle)) - [`2176a92`](autobrr/qui@2176a92): feat(automations): list configured indexer trackers in workflow selector ([#​2005](autobrr/qui#2005)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`2de926e`](autobrr/qui@2de926e): feat(i18n): add Italian (it) translation ([#​2011](autobrr/qui#2011)) ([@​s0up4200](https://github.com/s0up4200)) - [`7b66655`](autobrr/qui@7b66655): feat(i18n): add Korean (ko) translation ([#​2042](autobrr/qui#2042)) ([@​jussaw](https://github.com/jussaw)) - [`2c06a3d`](autobrr/qui@2c06a3d): feat(i18n): add Ukrainian (uk) translation ([#​2032](autobrr/qui#2032)) ([@​rodion981](https://github.com/rodion981)) - [`ef8da0b`](autobrr/qui@ef8da0b): feat(sse): keep cached torrents with a staleness badge when qBittorrent is slow ([#​2057](autobrr/qui#2057)) ([@​s0up4200](https://github.com/s0up4200)) - [`38ebb6e`](autobrr/qui@38ebb6e): feat(web): add file priority controls to torrent file views ([#​2062](autobrr/qui#2062)) ([@​jussaw](https://github.com/jussaw)) ##### Bug Fixes - [`12ac536`](autobrr/qui@12ac536): fix(ci): skip release binary build on main pushes ([#​2008](autobrr/qui#2008)) ([@​s0up4200](https://github.com/s0up4200)) - [`57210a3`](autobrr/qui@57210a3): fix(crossseed): drop resolution token from TV search queries ([#​2017](autobrr/qui#2017)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`791bc7d`](autobrr/qui@791bc7d): fix(crossseed): inject rootless single-file adds into matched folder ([#​2029](autobrr/qui#2029)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`3da437f`](autobrr/qui@3da437f): fix(crossseed): re-query indexers with no usable hit in the alternate connector pass ([#​2002](autobrr/qui#2002)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`8e8b6d9`](autobrr/qui@8e8b6d9): fix(database): prevent int4 sequence exhaustion in Postgres string interning ([#​2015](autobrr/qui#2015)) ([@​s0up4200](https://github.com/s0up4200)) - [`c7e08b9`](autobrr/qui@c7e08b9): fix(db): index string\_pool FK columns so GC stops timing out ([#​2051](autobrr/qui#2051)) ([@​s0up4200](https://github.com/s0up4200)) - [`2553f75`](autobrr/qui@2553f75): fix(docs): use relative file paths for markdown links ([#​2013](autobrr/qui#2013)) ([@​nasenov](https://github.com/nasenov)) - [`8a9c2fc`](autobrr/qui@8a9c2fc): fix(i18n): improve French translation, fix hardcoded UI statuses, and update agent rules ([#​2014](autobrr/qui#2014)) ([@​OlziYT](https://github.com/OlziYT)) - [`190d936`](autobrr/qui@190d936): fix(jackett): decouple cache persistence from SkipHistory ([#​2056](autobrr/qui#2056)) ([@​jussaw](https://github.com/jussaw)) - [`91ad7e4`](autobrr/qui@91ad7e4): fix(pprof): bind to configurable loopback address instead of :6060 ([#​2044](autobrr/qui#2044)) ([@​s0up4200](https://github.com/s0up4200)) - [`10e2d02`](autobrr/qui@10e2d02): fix(qbittorrent): serve stale app info/preferences when refresh fails ([#​2054](autobrr/qui#2054)) ([@​s0up4200](https://github.com/s0up4200)) - [`6d3b04c`](autobrr/qui@6d3b04c): fix(sse): resolve sync-error staleness stamp off the sync-loop callback ([#​2065](autobrr/qui#2065)) ([@​s0up4200](https://github.com/s0up4200)) - [`677e8f4`](autobrr/qui@677e8f4): fix(sse): send torrent page deltas instead of full snapshots ([#​2047](autobrr/qui#2047)) ([@​s0up4200](https://github.com/s0up4200)) - [`a4d252b`](autobrr/qui@a4d252b): fix(sse): size full-sync timeout to prevent permanent disconnect on large instances ([#​2037](autobrr/qui#2037)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`4f375c6`](autobrr/qui@4f375c6): fix(torrents): route unified view exports to the owning instance ([#​2018](autobrr/qui#2018)) ([@​s0up4200](https://github.com/s0up4200)) - [`d49e168`](autobrr/qui@d49e168): fix(web): move instance status bar back to bottom of screen ([#​2024](autobrr/qui#2024)) ([@​OlziYT](https://github.com/OlziYT)) - [`a69ae69`](autobrr/qui@a69ae69): fix(web): prevent framer-motion tab indicator from triggering layout shifts ([#​2025](autobrr/qui#2025)) ([@​OlziYT](https://github.com/OlziYT)) ##### Other Changes - [`860b5bb`](autobrr/qui@860b5bb): chore(deps): bump anthropics/claude-code-action from 1.0.140 to 1.0.148 in the github group ([#​2045](autobrr/qui#2045)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`0b23a7d`](autobrr/qui@0b23a7d): chore(deps): bump the github group with 2 updates ([#​2031](autobrr/qui#2031)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`1fea36b`](autobrr/qui@1fea36b): docs: document frontend testing conventions ([#​1984](autobrr/qui#1984)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`f3443ec`](autobrr/qui@f3443ec): docs: promote multi-language support ([#​2009](autobrr/qui#2009)) ([@​s0up4200](https://github.com/s0up4200)) - [`df88e63`](autobrr/qui@df88e63): test(web): add coverage for hooks and lib/api.ts contract layer ([#​1931](autobrr/qui#1931)) ([#​1998](autobrr/qui#1998)) ([@​nitrobass24](https://github.com/nitrobass24)) **Full Changelog**: <autobrr/qui@v1.20.0...v1.21.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.21.0` - `docker pull ghcr.io/autobrr/qui:latest` ##### What to do next? - Join our [Discord server](https://discord.autobrr.com/qui) Thank you for using qui! </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/London) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI0Mi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL21pbm9yIl19--> Reviewed-on: https://forgejo.hayden.moe/hayden/phoebe/pulls/200
…#160) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.20.0` → `v1.21.0` | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/7) for more information. --- ### Release Notes <details> <summary>autobrr/qui (ghcr.io/autobrr/qui)</summary> ### [`v1.21.0`](https://github.com/autobrr/qui/releases/tag/v1.21.0) [Compare Source](autobrr/qui@v1.20.0...v1.21.0) ##### Changelog ##### New Features - [`51b29a1`](autobrr/qui@51b29a1): feat(api): add GET /api/version reporting the running version ([#​2060](autobrr/qui#2060)) ([@​s0up4200](https://github.com/s0up4200)) - [`98348f1`](autobrr/qui@98348f1): feat(automations): add RLS\_YEAR release-year condition ([#​2003](autobrr/qui#2003)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`58cc7cb`](autobrr/qui@58cc7cb): feat(automations): add tracker status and message conditions ([#​2006](autobrr/qui#2006)) ([@​luckylittle](https://github.com/luckylittle)) - [`2176a92`](autobrr/qui@2176a92): feat(automations): list configured indexer trackers in workflow selector ([#​2005](autobrr/qui#2005)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`2de926e`](autobrr/qui@2de926e): feat(i18n): add Italian (it) translation ([#​2011](autobrr/qui#2011)) ([@​s0up4200](https://github.com/s0up4200)) - [`7b66655`](autobrr/qui@7b66655): feat(i18n): add Korean (ko) translation ([#​2042](autobrr/qui#2042)) ([@​jussaw](https://github.com/jussaw)) - [`2c06a3d`](autobrr/qui@2c06a3d): feat(i18n): add Ukrainian (uk) translation ([#​2032](autobrr/qui#2032)) ([@​rodion981](https://github.com/rodion981)) - [`ef8da0b`](autobrr/qui@ef8da0b): feat(sse): keep cached torrents with a staleness badge when qBittorrent is slow ([#​2057](autobrr/qui#2057)) ([@​s0up4200](https://github.com/s0up4200)) - [`38ebb6e`](autobrr/qui@38ebb6e): feat(web): add file priority controls to torrent file views ([#​2062](autobrr/qui#2062)) ([@​jussaw](https://github.com/jussaw)) ##### Bug Fixes - [`12ac536`](autobrr/qui@12ac536): fix(ci): skip release binary build on main pushes ([#​2008](autobrr/qui#2008)) ([@​s0up4200](https://github.com/s0up4200)) - [`57210a3`](autobrr/qui@57210a3): fix(crossseed): drop resolution token from TV search queries ([#​2017](autobrr/qui#2017)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`791bc7d`](autobrr/qui@791bc7d): fix(crossseed): inject rootless single-file adds into matched folder ([#​2029](autobrr/qui#2029)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`3da437f`](autobrr/qui@3da437f): fix(crossseed): re-query indexers with no usable hit in the alternate connector pass ([#​2002](autobrr/qui#2002)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`8e8b6d9`](autobrr/qui@8e8b6d9): fix(database): prevent int4 sequence exhaustion in Postgres string interning ([#​2015](autobrr/qui#2015)) ([@​s0up4200](https://github.com/s0up4200)) - [`c7e08b9`](autobrr/qui@c7e08b9): fix(db): index string\_pool FK columns so GC stops timing out ([#​2051](autobrr/qui#2051)) ([@​s0up4200](https://github.com/s0up4200)) - [`2553f75`](autobrr/qui@2553f75): fix(docs): use relative file paths for markdown links ([#​2013](autobrr/qui#2013)) ([@​nasenov](https://github.com/nasenov)) - [`8a9c2fc`](autobrr/qui@8a9c2fc): fix(i18n): improve French translation, fix hardcoded UI statuses, and update agent rules ([#​2014](autobrr/qui#2014)) ([@​OlziYT](https://github.com/OlziYT)) - [`190d936`](autobrr/qui@190d936): fix(jackett): decouple cache persistence from SkipHistory ([#​2056](autobrr/qui#2056)) ([@​jussaw](https://github.com/jussaw)) - [`91ad7e4`](autobrr/qui@91ad7e4): fix(pprof): bind to configurable loopback address instead of :6060 ([#​2044](autobrr/qui#2044)) ([@​s0up4200](https://github.com/s0up4200)) - [`10e2d02`](autobrr/qui@10e2d02): fix(qbittorrent): serve stale app info/preferences when refresh fails ([#​2054](autobrr/qui#2054)) ([@​s0up4200](https://github.com/s0up4200)) - [`6d3b04c`](autobrr/qui@6d3b04c): fix(sse): resolve sync-error staleness stamp off the sync-loop callback ([#​2065](autobrr/qui#2065)) ([@​s0up4200](https://github.com/s0up4200)) - [`677e8f4`](autobrr/qui@677e8f4): fix(sse): send torrent page deltas instead of full snapshots ([#​2047](autobrr/qui#2047)) ([@​s0up4200](https://github.com/s0up4200)) - [`a4d252b`](autobrr/qui@a4d252b): fix(sse): size full-sync timeout to prevent permanent disconnect on large instances ([#​2037](autobrr/qui#2037)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`4f375c6`](autobrr/qui@4f375c6): fix(torrents): route unified view exports to the owning instance ([#​2018](autobrr/qui#2018)) ([@​s0up4200](https://github.com/s0up4200)) - [`d49e168`](autobrr/qui@d49e168): fix(web): move instance status bar back to bottom of screen ([#​2024](autobrr/qui#2024)) ([@​OlziYT](https://github.com/OlziYT)) - [`a69ae69`](autobrr/qui@a69ae69): fix(web): prevent framer-motion tab indicator from triggering layout shifts ([#​2025](autobrr/qui#2025)) ([@​OlziYT](https://github.com/OlziYT)) ##### Other Changes - [`860b5bb`](autobrr/qui@860b5bb): chore(deps): bump anthropics/claude-code-action from 1.0.140 to 1.0.148 in the github group ([#​2045](autobrr/qui#2045)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`0b23a7d`](autobrr/qui@0b23a7d): chore(deps): bump the github group with 2 updates ([#​2031](autobrr/qui#2031)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`1fea36b`](autobrr/qui@1fea36b): docs: document frontend testing conventions ([#​1984](autobrr/qui#1984)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`f3443ec`](autobrr/qui@f3443ec): docs: promote multi-language support ([#​2009](autobrr/qui#2009)) ([@​s0up4200](https://github.com/s0up4200)) - [`df88e63`](autobrr/qui@df88e63): test(web): add coverage for hooks and lib/api.ts contract layer ([#​1931](autobrr/qui#1931)) ([#​1998](autobrr/qui#1998)) ([@​nitrobass24](https://github.com/nitrobass24)) **Full Changelog**: <autobrr/qui@v1.20.0...v1.21.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.21.0` - `docker pull ghcr.io/autobrr/qui:latest` ##### What to do next? - Join our [Discord server](https://discord.autobrr.com/qui) Thank you for using qui! </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/Warsaw) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDMuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI0My4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbInJlbm92YXRlL2NvbnRhaW5lciIsInR5cGUvbWlub3IiXX0=--> Reviewed-on: https://git.ajgon.casa/deedee/mark13/pulls/160
…#160) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.20.0` → `v1.21.0` | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/7) for more information. --- ### Release Notes <details> <summary>autobrr/qui (ghcr.io/autobrr/qui)</summary> ### [`v1.21.0`](https://github.com/autobrr/qui/releases/tag/v1.21.0) [Compare Source](autobrr/qui@v1.20.0...v1.21.0) ##### Changelog ##### New Features - [`51b29a1`](autobrr/qui@51b29a1): feat(api): add GET /api/version reporting the running version ([#​2060](autobrr/qui#2060)) ([@​s0up4200](https://github.com/s0up4200)) - [`98348f1`](autobrr/qui@98348f1): feat(automations): add RLS\_YEAR release-year condition ([#​2003](autobrr/qui#2003)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`58cc7cb`](autobrr/qui@58cc7cb): feat(automations): add tracker status and message conditions ([#​2006](autobrr/qui#2006)) ([@​luckylittle](https://github.com/luckylittle)) - [`2176a92`](autobrr/qui@2176a92): feat(automations): list configured indexer trackers in workflow selector ([#​2005](autobrr/qui#2005)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`2de926e`](autobrr/qui@2de926e): feat(i18n): add Italian (it) translation ([#​2011](autobrr/qui#2011)) ([@​s0up4200](https://github.com/s0up4200)) - [`7b66655`](autobrr/qui@7b66655): feat(i18n): add Korean (ko) translation ([#​2042](autobrr/qui#2042)) ([@​jussaw](https://github.com/jussaw)) - [`2c06a3d`](autobrr/qui@2c06a3d): feat(i18n): add Ukrainian (uk) translation ([#​2032](autobrr/qui#2032)) ([@​rodion981](https://github.com/rodion981)) - [`ef8da0b`](autobrr/qui@ef8da0b): feat(sse): keep cached torrents with a staleness badge when qBittorrent is slow ([#​2057](autobrr/qui#2057)) ([@​s0up4200](https://github.com/s0up4200)) - [`38ebb6e`](autobrr/qui@38ebb6e): feat(web): add file priority controls to torrent file views ([#​2062](autobrr/qui#2062)) ([@​jussaw](https://github.com/jussaw)) ##### Bug Fixes - [`12ac536`](autobrr/qui@12ac536): fix(ci): skip release binary build on main pushes ([#​2008](autobrr/qui#2008)) ([@​s0up4200](https://github.com/s0up4200)) - [`57210a3`](autobrr/qui@57210a3): fix(crossseed): drop resolution token from TV search queries ([#​2017](autobrr/qui#2017)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`791bc7d`](autobrr/qui@791bc7d): fix(crossseed): inject rootless single-file adds into matched folder ([#​2029](autobrr/qui#2029)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`3da437f`](autobrr/qui@3da437f): fix(crossseed): re-query indexers with no usable hit in the alternate connector pass ([#​2002](autobrr/qui#2002)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`8e8b6d9`](autobrr/qui@8e8b6d9): fix(database): prevent int4 sequence exhaustion in Postgres string interning ([#​2015](autobrr/qui#2015)) ([@​s0up4200](https://github.com/s0up4200)) - [`c7e08b9`](autobrr/qui@c7e08b9): fix(db): index string\_pool FK columns so GC stops timing out ([#​2051](autobrr/qui#2051)) ([@​s0up4200](https://github.com/s0up4200)) - [`2553f75`](autobrr/qui@2553f75): fix(docs): use relative file paths for markdown links ([#​2013](autobrr/qui#2013)) ([@​nasenov](https://github.com/nasenov)) - [`8a9c2fc`](autobrr/qui@8a9c2fc): fix(i18n): improve French translation, fix hardcoded UI statuses, and update agent rules ([#​2014](autobrr/qui#2014)) ([@​OlziYT](https://github.com/OlziYT)) - [`190d936`](autobrr/qui@190d936): fix(jackett): decouple cache persistence from SkipHistory ([#​2056](autobrr/qui#2056)) ([@​jussaw](https://github.com/jussaw)) - [`91ad7e4`](autobrr/qui@91ad7e4): fix(pprof): bind to configurable loopback address instead of :6060 ([#​2044](autobrr/qui#2044)) ([@​s0up4200](https://github.com/s0up4200)) - [`10e2d02`](autobrr/qui@10e2d02): fix(qbittorrent): serve stale app info/preferences when refresh fails ([#​2054](autobrr/qui#2054)) ([@​s0up4200](https://github.com/s0up4200)) - [`6d3b04c`](autobrr/qui@6d3b04c): fix(sse): resolve sync-error staleness stamp off the sync-loop callback ([#​2065](autobrr/qui#2065)) ([@​s0up4200](https://github.com/s0up4200)) - [`677e8f4`](autobrr/qui@677e8f4): fix(sse): send torrent page deltas instead of full snapshots ([#​2047](autobrr/qui#2047)) ([@​s0up4200](https://github.com/s0up4200)) - [`a4d252b`](autobrr/qui@a4d252b): fix(sse): size full-sync timeout to prevent permanent disconnect on large instances ([#​2037](autobrr/qui#2037)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`4f375c6`](autobrr/qui@4f375c6): fix(torrents): route unified view exports to the owning instance ([#​2018](autobrr/qui#2018)) ([@​s0up4200](https://github.com/s0up4200)) - [`d49e168`](autobrr/qui@d49e168): fix(web): move instance status bar back to bottom of screen ([#​2024](autobrr/qui#2024)) ([@​OlziYT](https://github.com/OlziYT)) - [`a69ae69`](autobrr/qui@a69ae69): fix(web): prevent framer-motion tab indicator from triggering layout shifts ([#​2025](autobrr/qui#2025)) ([@​OlziYT](https://github.com/OlziYT)) ##### Other Changes - [`860b5bb`](autobrr/qui@860b5bb): chore(deps): bump anthropics/claude-code-action from 1.0.140 to 1.0.148 in the github group ([#​2045](autobrr/qui#2045)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`0b23a7d`](autobrr/qui@0b23a7d): chore(deps): bump the github group with 2 updates ([#​2031](autobrr/qui#2031)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`1fea36b`](autobrr/qui@1fea36b): docs: document frontend testing conventions ([#​1984](autobrr/qui#1984)) ([@​nitrobass24](https://github.com/nitrobass24)) - [`f3443ec`](autobrr/qui@f3443ec): docs: promote multi-language support ([#​2009](autobrr/qui#2009)) ([@​s0up4200](https://github.com/s0up4200)) - [`df88e63`](autobrr/qui@df88e63): test(web): add coverage for hooks and lib/api.ts contract layer ([#​1931](autobrr/qui#1931)) ([#​1998](autobrr/qui#1998)) ([@​nitrobass24](https://github.com/nitrobass24)) **Full Changelog**: <autobrr/qui@v1.20.0...v1.21.0> ##### Docker images - `docker pull ghcr.io/autobrr/qui:v1.21.0` - `docker pull ghcr.io/autobrr/qui:latest` ##### What to do next? - Join our [Discord server](https://discord.autobrr.com/qui) Thank you for using qui! </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/Warsaw) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDMuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI0My4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbInJlbm92YXRlL2NvbnRhaW5lciIsInR5cGUvbWlub3IiXX0=--> Reviewed-on: https://git.ajgon.casa/deedee/mark13/pulls/160
Summary
Documents the frontend-test conventions that aren't obvious from the config or existing docs — the ones that cost real time to (re)discover while building out coverage during the #1963 table decomposition.
AGENTS.md— new Frontend tests subsection*.test.ts(x); extract logic into hooks/lib so it's unit-testable without mounting the whole tree.globals: false+ jsdom + no setup file → import test globals from"vitest", no jest-dom matchers, assert with plain DOM.vi.hoisted()for mock values invi.mockfactories.CONTRIBUTING.md— one expectation bulletWhy here
CONTRIBUTING.mdalready covers the mechanics (run commands, colocation, CI) and explicitly defers "deeper conventions" toAGENTS.md/CLAUDE.md— so the how lives inAGENTS.md(note:CLAUDE.mdis a symlink toAGENTS.md, so this updates both).Testing
Docs-only — no code paths affected.
Opened as draft for wording review.
Summary by CodeRabbit