fix tests
This commit is contained in:
parent
b8363aa993
commit
59270e8a4f
@ -84,6 +84,7 @@ RUN cd src-tauri && cargo fetch && cd ..
|
||||
FROM builder AS test
|
||||
WORKDIR /app
|
||||
RUN echo "Running tests..." && \
|
||||
bunx svelte-kit sync && \
|
||||
bun run test && \
|
||||
cd src-tauri && cargo test && cd .. && \
|
||||
echo "All tests passed!"
|
||||
|
||||
@ -12,7 +12,7 @@ services:
|
||||
- .:/app
|
||||
environment:
|
||||
- RUST_BACKTRACE=1
|
||||
command: bash -c "bun test && cd src-tauri && cargo test && cd .. && echo 'All tests passed!'"
|
||||
command: bash -c "bunx svelte-kit sync && bun test && cd src-tauri && cargo test && cd .. && echo 'All tests passed!'"
|
||||
|
||||
# Android build service - builds APK after tests pass
|
||||
android-build:
|
||||
|
||||
@ -369,6 +369,7 @@ pub fn repository_get_image_url(
|
||||
|
||||
/// Get subtitle URL for a media item
|
||||
#[tauri::command]
|
||||
#[allow(dead_code)]
|
||||
pub fn repository_get_subtitle_url(
|
||||
manager: State<'_, RepositoryManagerWrapper>,
|
||||
handle: String,
|
||||
@ -383,6 +384,7 @@ pub fn repository_get_subtitle_url(
|
||||
|
||||
/// Get video download URL with quality preset
|
||||
#[tauri::command]
|
||||
#[allow(dead_code)]
|
||||
pub fn repository_get_video_download_url(
|
||||
manager: State<'_, RepositoryManagerWrapper>,
|
||||
handle: String,
|
||||
|
||||
@ -147,6 +147,8 @@ pub trait MediaRepository: Send + Sync {
|
||||
) -> String;
|
||||
|
||||
/// Get subtitle URL (synchronous - just constructs URL)
|
||||
/// Called by frontend via Tauri invoke (getSubtitleUrl in VideoPlayer.svelte)
|
||||
#[allow(dead_code)]
|
||||
fn get_subtitle_url(
|
||||
&self,
|
||||
item_id: &str,
|
||||
@ -156,6 +158,8 @@ pub trait MediaRepository: Send + Sync {
|
||||
) -> String;
|
||||
|
||||
/// Get video download URL (synchronous - just constructs URL)
|
||||
/// Called by frontend via Tauri invoke (getVideoDownloadUrl in VideoDownloadButton.svelte)
|
||||
#[allow(dead_code)]
|
||||
fn get_video_download_url(
|
||||
&self,
|
||||
item_id: &str,
|
||||
|
||||
@ -6,6 +6,21 @@
|
||||
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
export interface AutoplaySettings {
|
||||
enabled: boolean;
|
||||
countdownSeconds: number;
|
||||
}
|
||||
|
||||
export async function getAutoplaySettings(): Promise<AutoplaySettings> {
|
||||
return invoke("player_get_autoplay_settings");
|
||||
}
|
||||
|
||||
export async function setAutoplaySettings(
|
||||
settings: AutoplaySettings
|
||||
): Promise<AutoplaySettings> {
|
||||
return invoke("player_set_autoplay_settings", { settings });
|
||||
}
|
||||
|
||||
export async function cancelAutoplayCountdown(): Promise<void> {
|
||||
return invoke("player_cancel_autoplay_countdown");
|
||||
}
|
||||
|
||||
@ -2,7 +2,11 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { RepositoryClient } from "./repository-client";
|
||||
|
||||
vi.mock("@tauri-apps/api/core");
|
||||
const mockInvoke = vi.fn();
|
||||
|
||||
vi.mock("@tauri-apps/api/core", () => ({
|
||||
invoke: mockInvoke,
|
||||
}));
|
||||
|
||||
/**
|
||||
* Integration tests documenting Phase 1 & 2 refactoring:
|
||||
|
||||
@ -2,7 +2,11 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { RepositoryClient } from "./repository-client";
|
||||
|
||||
vi.mock("@tauri-apps/api/core");
|
||||
const mockInvoke = vi.fn();
|
||||
|
||||
vi.mock("@tauri-apps/api/core", () => ({
|
||||
invoke: mockInvoke,
|
||||
}));
|
||||
|
||||
describe("RepositoryClient", () => {
|
||||
let client: RepositoryClient;
|
||||
|
||||
@ -25,8 +25,8 @@
|
||||
playlist: { singular: "playlist", plural: "playlists" },
|
||||
};
|
||||
|
||||
const labels = itemTypeLabels[itemType] || { singular: itemType, plural: `${itemType}s` };
|
||||
const label = count === 1 ? labels.singular : labels.plural;
|
||||
const labels = $derived(itemTypeLabels[itemType] || { singular: itemType, plural: `${itemType}s` });
|
||||
const label = $derived(count === 1 ? labels.singular : labels.plural);
|
||||
</script>
|
||||
|
||||
<p class={`text-sm text-gray-400 ${className}`}>
|
||||
|
||||
@ -160,6 +160,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
role="region"
|
||||
class="relative h-[500px] rounded-xl overflow-hidden group mb-8 touch-pan-y"
|
||||
ontouchstart={handleTouchStart}
|
||||
ontouchmove={handleTouchMove}
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
};
|
||||
|
||||
const circumference = 2 * Math.PI * 15;
|
||||
const offset = circumference - (state.progress || 0) * circumference;
|
||||
const offset = $derived(circumference - (state.progress || 0) * circumference);
|
||||
</script>
|
||||
|
||||
<button
|
||||
|
||||
@ -156,13 +156,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
const aspectRatioClass = config.itemDisplayMode === "poster" ? "aspect-[2/3]" : "aspect-square";
|
||||
const gridColsClass =
|
||||
const aspectRatioClass = $derived(config.itemDisplayMode === "poster" ? "aspect-[2/3]" : "aspect-square");
|
||||
const gridColsClass = $derived(
|
||||
config.itemDisplayMode === "poster"
|
||||
? "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5"
|
||||
: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6";
|
||||
const searchPlaceholder = config.searchPlaceholder || `Search ${config.title.toLowerCase()}...`;
|
||||
const noItemsMessage = config.noItemsMessage || `No ${config.itemTypes[0]?.toLowerCase() || "items"} found in this genre`;
|
||||
: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6"
|
||||
);
|
||||
const searchPlaceholder = $derived(config.searchPlaceholder || `Search ${config.title.toLowerCase()}...`);
|
||||
const noItemsMessage = $derived(config.noItemsMessage || `No ${config.itemTypes[0]?.toLowerCase() || "items"} found in this genre`);
|
||||
</script>
|
||||
|
||||
<div class="space-y-6">
|
||||
|
||||
@ -42,10 +42,14 @@
|
||||
let loading = $state(true);
|
||||
let searchQuery = $state("");
|
||||
let debouncedSearchQuery = $state("");
|
||||
let sortBy = $state<string>(config.defaultSort);
|
||||
let sortBy = $state<string>("");
|
||||
let sortOrder = $state<"Ascending" | "Descending">("Ascending");
|
||||
let searchTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
$effect(() => {
|
||||
sortBy = config.defaultSort;
|
||||
});
|
||||
|
||||
const { markLoaded } = useServerReachabilityReload(async () => {
|
||||
await loadItems();
|
||||
});
|
||||
@ -117,7 +121,7 @@
|
||||
goto(config.backPath);
|
||||
}
|
||||
|
||||
const searchPlaceholder = config.searchPlaceholder || `Search ${config.title.toLowerCase()}...`;
|
||||
const searchPlaceholder = $derived(config.searchPlaceholder || `Search ${config.title.toLowerCase()}...`);
|
||||
|
||||
function handleItemClick(item: MediaItem) {
|
||||
// Navigate to detail page for browseable items
|
||||
|
||||
@ -254,13 +254,15 @@
|
||||
<div class="text-gray-300 truncate flex flex-wrap items-center gap-1">
|
||||
{#if track.artistItems && track.artistItems.length > 0}
|
||||
{#each track.artistItems as artist, idx}
|
||||
<button
|
||||
type="button"
|
||||
<span
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onclick={(e) => handleArtistClick(artist.id, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline truncate"
|
||||
onkeydown={(e) => e.key === 'Enter' && handleArtistClick(artist.id, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline truncate cursor-pointer"
|
||||
>
|
||||
{artist.name}
|
||||
</button>
|
||||
</span>
|
||||
{#if idx < track.artistItems.length - 1}
|
||||
<span>,</span>
|
||||
{/if}
|
||||
@ -275,13 +277,15 @@
|
||||
{#if showAlbum}
|
||||
<div class="text-gray-300 truncate">
|
||||
{#if track.albumId}
|
||||
<button
|
||||
type="button"
|
||||
<span
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onclick={(e) => handleAlbumClick(track.albumId, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline truncate"
|
||||
onkeydown={(e) => e.key === 'Enter' && handleAlbumClick(track.albumId, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline truncate cursor-pointer"
|
||||
>
|
||||
{track.albumName || "-"}
|
||||
</button>
|
||||
</span>
|
||||
{:else}
|
||||
{track.albumName || "-"}
|
||||
{/if}
|
||||
@ -361,13 +365,15 @@
|
||||
{#if showArtist && showAlbum}
|
||||
{#if track.artistItems && track.artistItems.length > 0}
|
||||
{#each track.artistItems as artist, idx}
|
||||
<button
|
||||
type="button"
|
||||
<span
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onclick={(e) => handleArtistClick(artist.id, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline"
|
||||
onkeydown={(e) => e.key === 'Enter' && handleArtistClick(artist.id, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline cursor-pointer"
|
||||
>
|
||||
{artist.name}
|
||||
</button>
|
||||
</span>
|
||||
{#if idx < track.artistItems.length - 1}
|
||||
<span>,</span>
|
||||
{/if}
|
||||
@ -377,26 +383,30 @@
|
||||
{/if}
|
||||
<span>•</span>
|
||||
{#if track.albumId}
|
||||
<button
|
||||
type="button"
|
||||
<span
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onclick={(e) => handleAlbumClick(track.albumId, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline"
|
||||
onkeydown={(e) => e.key === 'Enter' && handleAlbumClick(track.albumId, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline cursor-pointer"
|
||||
>
|
||||
{track.albumName || "-"}
|
||||
</button>
|
||||
</span>
|
||||
{:else}
|
||||
{track.albumName || "-"}
|
||||
{/if}
|
||||
{:else if showArtist}
|
||||
{#if track.artistItems && track.artistItems.length > 0}
|
||||
{#each track.artistItems as artist, idx}
|
||||
<button
|
||||
type="button"
|
||||
<span
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onclick={(e) => handleArtistClick(artist.id, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline"
|
||||
onkeydown={(e) => e.key === 'Enter' && handleArtistClick(artist.id, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline cursor-pointer"
|
||||
>
|
||||
{artist.name}
|
||||
</button>
|
||||
</span>
|
||||
{#if idx < track.artistItems.length - 1}
|
||||
<span>,</span>
|
||||
{/if}
|
||||
@ -406,13 +416,15 @@
|
||||
{/if}
|
||||
{:else if showAlbum}
|
||||
{#if track.albumId}
|
||||
<button
|
||||
type="button"
|
||||
<span
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onclick={(e) => handleAlbumClick(track.albumId, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline"
|
||||
onkeydown={(e) => e.key === 'Enter' && handleAlbumClick(track.albumId, e)}
|
||||
class="text-[var(--color-jellyfin)] hover:underline cursor-pointer"
|
||||
>
|
||||
{track.albumName || "-"}
|
||||
</button>
|
||||
</span>
|
||||
{:else}
|
||||
{track.albumName || "-"}
|
||||
{/if}
|
||||
|
||||
@ -284,6 +284,7 @@
|
||||
</button>
|
||||
|
||||
<div
|
||||
role="region"
|
||||
class="px-4 py-3 flex items-center gap-4 touch-pan-y relative"
|
||||
ontouchstart={handleTouchStart}
|
||||
ontouchmove={handleTouchMove}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user