1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-22 03:05:32 +02:00

fix(core)+test: propagate sync query errors; cover new playlist/sync functions

archive.rs:
- get_archived_playlist_child_urls: collect() as rusqlite::Result<HashSet<_>>
  instead of filter_map(ok) so row-level errors surface rather than silently
  skipping and causing duplicate downloads

capture.rs:
- match get_archived_playlist_child_urls result and fail_run on error instead
  of unwrap_or_default, preventing silent re-downloads on DB failure

Tests added to capture.rs:
- locator_to_playlist_url_accepts_playlist_shorthands (yt:playlist/, ytm:playlist/, full URL)
- locator_to_playlist_url_accepts_channel_shorthands (yt:@handle)
- locator_to_playlist_url_rejects_non_playlist_sources (single video, tweet, web page)

Tests added to archive.rs (all use in-memory DB via make_tag_test_db):
- find_container_entry_id_returns_none_when_absent
- find_container_entry_id_returns_root_entry
- find_container_entry_id_ignores_child_entries (child with parent_entry_id set)
- get_archived_playlist_child_urls_empty_when_no_playlist
- get_archived_playlist_child_urls_returns_children
- get_archived_playlist_child_urls_excludes_other_playlists
This commit is contained in:
TheGeneralist 2026-07-20 22:38:56 +02:00
parent 814aa76a1d
commit 096c98a678
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
2 changed files with 128 additions and 4 deletions

View file

@ -1089,8 +1089,13 @@ pub fn perform_capture(
&format!("Failed to complete run item for existing container: {e:#}"),
));
}
let archived = archive::get_archived_playlist_child_urls(&conn, &canonical_url)
.unwrap_or_default();
let archived = match archive::get_archived_playlist_child_urls(&conn, &canonical_url) {
Ok(set) => set,
Err(e) => return Err(fail_run(
&conn, &run, &item,
&format!("Failed to query archived playlist children: {e:#}"),
)),
};
(existing_id, archived)
}
Ok(None) => {
@ -2621,4 +2626,41 @@ mod tests {
);
}
#[test]
fn locator_to_playlist_url_accepts_playlist_shorthands() {
// yt: playlist shorthand
assert_eq!(
locator_to_playlist_url("yt:playlist/PLtest123"),
Some("https://www.youtube.com/playlist?list=PLtest123".to_string()),
);
// YouTube Music playlist shorthand
assert_eq!(
locator_to_playlist_url("ytm:playlist/PLmus456"),
Some("https://music.youtube.com/playlist?list=PLmus456".to_string()),
);
// Full YT playlist URL passes through (expand_shorthand_to_url is identity for full URLs)
let full = "https://www.youtube.com/playlist?list=PLabc";
assert_eq!(locator_to_playlist_url(full), Some(full.to_string()));
}
#[test]
fn locator_to_playlist_url_accepts_channel_shorthands() {
let url = locator_to_playlist_url("yt:@MyChan");
assert!(url.is_some(), "channel @ shorthand should return Some");
let u = url.unwrap();
assert!(u.contains("youtube.com"), "should be a youtube URL: {u}");
}
#[test]
fn locator_to_playlist_url_rejects_non_playlist_sources() {
// Single video
assert_eq!(locator_to_playlist_url("yt:dQw4w9WgXcQ"), None);
// Tweet
assert_eq!(locator_to_playlist_url("tweet:1234567890"), None);
// YTM track
assert_eq!(locator_to_playlist_url("ytm:MntbN1DdEP0"), None);
// Plain web URL
assert_eq!(locator_to_playlist_url("https://example.com/page"), None);
}
}