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>
38 lines
1.8 KiB
Swift
38 lines
1.8 KiB
Swift
import XCTest
|
|
@testable import TVAnarchyCore
|
|
|
|
final class CommandTemplateTests: XCTestCase {
|
|
func testSubstitutionAndOptionalDrop() {
|
|
let t = ["/usr/local/bin/black-tv", "play-show", "{query}", "{season?}", "{episode?}"]
|
|
// optional episode absent → its word is dropped entirely
|
|
let r = CommandTemplate.render(t, ["query": "Psych", "season": "3", "episode": nil])
|
|
XCTAssertEqual(r, "'/usr/local/bin/black-tv' 'play-show' 'Psych' '3'")
|
|
}
|
|
|
|
func testAllOptionalsPresent() {
|
|
let t = ["btv", "play-show", "{query}", "{season?}", "{episode?}"]
|
|
XCTAssertEqual(CommandTemplate.render(t, ["query": "X", "season": "1", "episode": "4"]),
|
|
"'btv' 'play-show' 'X' '1' '4'")
|
|
}
|
|
|
|
func testShqEscapesDangerousValues() {
|
|
// apostrophes, spaces, and shell metachars must be neutralized
|
|
let r = CommandTemplate.render(["btv", "play", "{path}"],
|
|
["path": "/m/It's $HOME & co/ep.mkv"])
|
|
// Fully single-quoted (only the apostrophe is broken out & re-escaped), so
|
|
// the remote shell sees one literal word — `$HOME`/`&` can't expand or split.
|
|
XCTAssertEqual(r, "'btv' 'play' '/m/It'\\''s $HOME & co/ep.mkv'")
|
|
}
|
|
|
|
func testRequiredMissingBecomesEmptyWord() {
|
|
XCTAssertEqual(CommandTemplate.render(["a", "{x}"], [:]), "'a' ''")
|
|
}
|
|
|
|
func testPlaceholderParsing() {
|
|
XCTAssertEqual(CommandTemplate.placeholder("{query}")?.name, "query")
|
|
XCTAssertEqual(CommandTemplate.placeholder("{query}")?.optional, false)
|
|
XCTAssertEqual(CommandTemplate.placeholder("{season?}")?.optional, true)
|
|
XCTAssertNil(CommandTemplate.placeholder("literal"))
|
|
XCTAssertNil(CommandTemplate.placeholder("{}"))
|
|
}
|
|
}
|