feat(core): season tracked rule over revealed episodes

This commit is contained in:
Miguel Palhas
2026-08-23 16:46:26 +01:00
parent 93ccea2de0
commit 135d4b8247
+66 -1
View File
@@ -29,11 +29,25 @@ pub fn apply_auto_track(series: &Series, seasons: &mut [RefreshedSeason]) {
}
}
/// Applies a season's tracking rule (`DESIGN.md` §4.1) to its
/// already-revealed episodes.
///
/// Turning tracking on marks every revealed episode wanted; future reveals
/// follow while the season stays tracked. Turning it off withdraws nothing:
/// leaf intent is never removed implicitly.
pub fn apply_tracked(tracked: bool, episodes: &mut [Episode]) {
if tracked {
for episode in episodes {
episode.wanted = true;
}
}
}
#[cfg(test)]
mod tests {
use std::time::SystemTime;
use super::{apply_auto_track, RefreshedSeason};
use super::{apply_auto_track, apply_tracked, RefreshedSeason};
use crate::{
Episode, EpisodeId, Language, MediaState, RootId, Season, SeasonId, Series, SeriesId,
TitleOverrides,
@@ -131,4 +145,55 @@ mod tests {
assert!(!refresh[0].season.tracked);
assert!(refresh[0].episodes.iter().all(|episode| !episode.wanted));
}
#[test]
fn tracked_on_marks_revealed_episodes_wanted() {
let cases: [&[bool]; 4] = [
&[],
&[false],
&[true, false, false],
&[false, true, false, true],
];
for wanted in cases {
let mut episodes = wanted
.iter()
.enumerate()
.map(|(index, wanted)| {
episode(1, u16::try_from(index + 1).expect("episode number fits"), *wanted)
})
.collect::<Vec<_>>();
apply_tracked(true, &mut episodes);
assert!(
episodes.iter().all(|episode| episode.wanted),
"tracked on must mark every revealed episode wanted, input {wanted:?}"
);
}
}
#[test]
fn tracked_off_withdraws_nothing() {
let cases: [&[bool]; 4] = [
&[],
&[false],
&[true, false, false],
&[false, true, false, true],
];
for wanted in cases {
let mut episodes = wanted
.iter()
.enumerate()
.map(|(index, wanted)| {
episode(1, u16::try_from(index + 1).expect("episode number fits"), *wanted)
})
.collect::<Vec<_>>();
let before = episodes.iter().map(|episode| episode.wanted).collect::<Vec<_>>();
apply_tracked(false, &mut episodes);
let after = episodes.iter().map(|episode| episode.wanted).collect::<Vec<_>>();
assert_eq!(before, after, "tracked off must not touch intent");
}
}
}