feat(login): show the backend's server-version verdict, and drop a dead route builder
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 29m23s
🏗️ Build and Test JellyTau / Supply Chain (push) Successful in 44s
📱 Test APK / Build test APK (push) Successful in 43m47s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 6m33s
Traceability Validation / Check Requirement Traces (push) Successful in 14s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 5m21s
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 29m23s
🏗️ Build and Test JellyTau / Supply Chain (push) Successful in 44s
📱 Test APK / Build test APK (push) Successful in 43m47s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 6m33s
Traceability Validation / Check Requirement Traces (push) Successful in 14s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 5m21s
Two frontend halves of the version-compatibility work.
The login flow now renders ServerCompatibility. A server below the floor blocks
with a message naming the minimum; a server newer than this build gets a
non-blocking note and proceeds; an unreadable version says nothing at all,
because refusing — or even warning — on a version string we could not parse would
punish the user for a limitation of ours.
The frontend never receives a version number to reason about, only the opaque
verdict, for the same reason it never receives an item-type list. Rust decides
whether the server is usable; the frontend decides only how that reads.
Separately, imageCache.getCachedImageUrl is deleted. It built
${serverUrl}/Items/${itemId}/Images/${imageType} in Svelte — a Jellyfin route in
the presentation layer, which is domain logic by this project's own litmus test
(would it change if Jellyfin changed its API?). check:boundary does not catch it:
the tripwire flags item-type array literals, not route strings.
It was also entirely unused. Nothing outside its own file and test ever called
it; the live path is CachedImage.svelte -> commands.imageGetUrl -> Rust, which
was already correct. So the leak was in dead code and the fix is a deletion
rather than a migration.
One consequence left deliberately unacted: that function was the last
convertFileSrc caller, so the asset-protocol grant narrowed to
$APPDATA/thumbnails/** under DR-198 now has no caller at all. Dropping a
capability grant is a security change that deserves its own commit and its own
testing on Android, not a side effect of deleting dead code. Noted in the file.
TRACES: UR-012, UR-085 | DR-285, DR-286
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
|
||||
import { describe, it, expect, beforeEach, vi } from "vitest";
|
||||
import {
|
||||
getCachedImageUrl,
|
||||
getCacheStats,
|
||||
setCacheLimit,
|
||||
clearCache,
|
||||
@@ -50,43 +49,6 @@ describe("image cache service", () => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("getCachedImageUrl", () => {
|
||||
it("should build server URL with default image type", async () => {
|
||||
const url = await getCachedImageUrl("http://server.local:8096", "item-123");
|
||||
expect(url).toContain("http://server.local:8096/Items/item-123/Images/Primary");
|
||||
});
|
||||
|
||||
it("should build server URL with custom image type", async () => {
|
||||
const url = await getCachedImageUrl("http://server.local:8096", "item-123", "Backdrop");
|
||||
expect(url).toContain("Backdrop");
|
||||
});
|
||||
|
||||
it("should include image options in URL", async () => {
|
||||
const url = await getCachedImageUrl("http://server.local:8096", "item-123", "Primary", {
|
||||
maxWidth: 300,
|
||||
maxHeight: 400,
|
||||
quality: 90,
|
||||
tag: "abc123",
|
||||
});
|
||||
expect(url).toContain("maxWidth=300");
|
||||
expect(url).toContain("maxHeight=400");
|
||||
expect(url).toContain("quality=90");
|
||||
expect(url).toContain("tag=abc123");
|
||||
});
|
||||
|
||||
it("should trigger background caching", async () => {
|
||||
const { invoke } = await import("@tauri-apps/api/core");
|
||||
const invokeSpy = vi.mocked(invoke);
|
||||
|
||||
await getCachedImageUrl("http://server.local:8096", "item-123");
|
||||
|
||||
const saveCall = invokeSpy.mock.calls.find((call) => call[0] === "thumbnail_save");
|
||||
expect(saveCall).toBeDefined();
|
||||
expect(saveCall![1]).toHaveProperty("itemId", "item-123");
|
||||
expect(saveCall![1]).toHaveProperty("imageType", "Primary");
|
||||
});
|
||||
});
|
||||
|
||||
describe("cache statistics", () => {
|
||||
it("should get cache statistics", async () => {
|
||||
const stats = await getCacheStats();
|
||||
|
||||
Reference in New Issue
Block a user