Renames Sources/PlumTV→TVAnarchy and PlumTVCore→TVAnarchyCore (the rename the auto-commit service couldn't stage — it git-add'd the old, now-gone paths and aborted every cycle), and commits the accumulated work: - Library: black-built index fast path (LibraryIndex + scanFromIndex) with NFS-walk fallback; incremental --add on download-complete; mtime staleness gate; loose-file series-collapse fix; determinate scan/index progress. - Cover art: keyless TVmaze cartoon-vs-live-action disambiguation (type/year). - Player: sleep timer (timed + end-of-episode); visibility-gated polling. - Home: Continue Watching cover art + live refresh; Recently Added; adult gate. - Logs: multi-line selection + copy; truncated giant tx-list errors. - Hover previews (opt-in) via black ffmpeg + scp. Also gitignores foreign project trees (governor/mcp/fleet/recommender) that sit in this directory but belong to their own repos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
2.7 KiB
Swift
67 lines
2.7 KiB
Swift
import XCTest
|
|
@testable import TVAnarchyCore
|
|
|
|
/// The deterministic metadata core — filename → structured fields. Cases are
|
|
/// real-shaped release names (incl. the messy registry style with " — " notes).
|
|
final class FilenameParserTests: XCTestCase {
|
|
func testEpisodeRelease() {
|
|
let p = FilenameParser.parse(filename: "Psych.S01E04.720p.WEB-DL.x264-GROUP")
|
|
XCTAssertEqual(p.title, "Psych")
|
|
XCTAssertEqual(p.season, 1)
|
|
XCTAssertEqual(p.episode, 4)
|
|
XCTAssertEqual(p.quality, "720p")
|
|
XCTAssertEqual(p.codec?.lowercased(), "x264")
|
|
XCTAssertEqual(p.releaseSource?.lowercased(), "web-dl")
|
|
}
|
|
|
|
func testYearKeptOutOfTitle() {
|
|
let p = FilenameParser.parse(filename: "Psych 2006 Season 6 Complete 720p AMZN WEB-DL x264")
|
|
XCTAssertEqual(p.title, "Psych")
|
|
XCTAssertEqual(p.year, 2006)
|
|
XCTAssertEqual(p.quality, "720p")
|
|
}
|
|
|
|
func testDottedNameAndHevc() {
|
|
let p = FilenameParser.parse(filename: "Twin.Peaks.S01.COMPLETE.1080p.BluRay.x265.HEVC-PSA")
|
|
XCTAssertEqual(p.title, "Twin Peaks")
|
|
XCTAssertEqual(p.season, 1)
|
|
XCTAssertEqual(p.quality, "1080p")
|
|
XCTAssertEqual(p.codec?.lowercased(), "x265")
|
|
}
|
|
|
|
func testParseFromPathStripsDirAndExt() {
|
|
let p = FilenameParser.parse(path: "/m/cartoons/Futurama/Futurama S03E01 The Honking.mp4")
|
|
XCTAssertEqual(p.title, "Futurama")
|
|
XCTAssertEqual(p.season, 3)
|
|
XCTAssertEqual(p.episode, 1)
|
|
}
|
|
|
|
func testMovieWithYearNoEpisode() {
|
|
let p = FilenameParser.parse(filename: "The.Mists.Of.Avalon.2001.DVDRip.XviD-DiVAS")
|
|
XCTAssertEqual(p.title, "The Mists Of Avalon")
|
|
XCTAssertEqual(p.year, 2001)
|
|
XCTAssertNil(p.season)
|
|
XCTAssertNil(p.episode)
|
|
XCTAssertEqual(p.codec?.lowercased(), "xvid")
|
|
}
|
|
|
|
func testEnrichResultPartialDecode() throws {
|
|
// The real graceful-degrade shape (TMDB key unset, IMDb present).
|
|
let json = #"""
|
|
{"query":"Psych","year":2006,"tmdb_error":"TMDB_API_KEY unset",
|
|
"imdb_rating":8.4,"imdb_votes":120400,"genres":["Comedy","Crime","Mystery"]}
|
|
"""#
|
|
let r = try JSONDecoder().decode(EnrichResult.self, from: Data(json.utf8))
|
|
XCTAssertEqual(r.imdb_rating, 8.4)
|
|
XCTAssertEqual(r.imdb_votes, 120400)
|
|
XCTAssertEqual(r.genres, ["Comedy", "Crime", "Mystery"])
|
|
XCTAssertNil(r.poster_url)
|
|
XCTAssertEqual(r.tmdb_error, "TMDB_API_KEY unset")
|
|
|
|
var meta = MediaMeta(path: "/m/Psych", parsed: ParsedFilename(title: "Psych", year: 2006))
|
|
meta.apply(r, at: Date(timeIntervalSince1970: 0))
|
|
XCTAssertEqual(meta.imdbRating, 8.4)
|
|
XCTAssertNil(meta.posterURL)
|
|
XCTAssertNotNil(meta.enrichedAt)
|
|
}
|
|
}
|