Expand integration suite to cover all months of 2026, minor refactorings
This commit is contained in:
7
justfile
7
justfile
@@ -25,8 +25,11 @@ test-all:
|
|||||||
bench:
|
bench:
|
||||||
cd {{tauri_path}} && cargo bench
|
cd {{tauri_path}} && cargo bench
|
||||||
|
|
||||||
# profile:
|
cov:
|
||||||
# cd {{tauri_path}} && cargo flamegraph
|
cd {{tauri_path}} && cargo llvm-cov run
|
||||||
|
|
||||||
|
mutants:
|
||||||
|
cd {{tauri_path}} && cargo mutants
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf node_modules
|
rm -rf node_modules
|
||||||
|
|||||||
@@ -104,6 +104,18 @@ impl UserConfig {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_month(&mut self, month: u8) {
|
||||||
|
self.month = Month::try_from(month).unwrap();
|
||||||
|
|
||||||
|
self.total_days = self.month.num_days(self.year).unwrap();
|
||||||
|
|
||||||
|
self.total_slots = (1..=self.total_days)
|
||||||
|
.map(|d| if Day(d).is_open_shift() { 2 } else { 1 })
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
self.total_holiday_slots = self.total_holiday_slots()
|
||||||
|
}
|
||||||
|
|
||||||
fn total_holiday_slots(&self) -> u8 {
|
fn total_holiday_slots(&self) -> u8 {
|
||||||
(1..=self.total_days)
|
(1..=self.total_days)
|
||||||
.filter(|&d| self.is_holiday_or_weekend(Day(d)))
|
.filter(|&d| self.is_holiday_or_weekend(Day(d)))
|
||||||
@@ -212,7 +224,7 @@ impl TryFrom<UserConfigDTO> for UserConfig {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
config::UserConfig,
|
config::{ToxicPair, UserConfig},
|
||||||
fixtures::complex_config,
|
fixtures::complex_config,
|
||||||
schedule::ShiftType,
|
schedule::ShiftType,
|
||||||
slot::{Day, ShiftPosition, Slot},
|
slot::{Day, ShiftPosition, Slot},
|
||||||
@@ -248,4 +260,18 @@ mod tests {
|
|||||||
assert!(complex_config.is_holiday_or_weekend_slot(sun));
|
assert!(complex_config.is_holiday_or_weekend_slot(sun));
|
||||||
assert!(complex_config.is_holiday_or_weekend_slot(manual_holiday));
|
assert!(complex_config.is_holiday_or_weekend_slot(manual_holiday));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_toxic_pair_matches() {
|
||||||
|
let pair_1 = ToxicPair::new(1, 2);
|
||||||
|
let pair_1_r = ToxicPair::new(2, 1);
|
||||||
|
let pair_2 = ToxicPair::new(3, 1);
|
||||||
|
|
||||||
|
assert!(pair_1.matches(&pair_1_r));
|
||||||
|
assert!(pair_1_r.matches(&pair_1));
|
||||||
|
assert!(!pair_1.matches(&pair_2));
|
||||||
|
assert!(!pair_2.matches(&pair_1));
|
||||||
|
assert!(!pair_1_r.matches(&pair_2));
|
||||||
|
assert!(!pair_2.matches(&pair_1_r));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::{
|
|||||||
config::UserConfig,
|
config::UserConfig,
|
||||||
errors::ExportError,
|
errors::ExportError,
|
||||||
schedule::MonthlySchedule,
|
schedule::MonthlySchedule,
|
||||||
slot::{month_to_greek, weekday_to_greek, Day, ShiftPosition, Slot},
|
slot::{Day, ShiftPosition, Slot},
|
||||||
workload::WorkloadTracker,
|
workload::WorkloadTracker,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -97,21 +97,21 @@ impl MonthlySchedule {
|
|||||||
let day = Day(d);
|
let day = Day(d);
|
||||||
let is_weekend = day.is_weekend(config.month.number_from_month(), config.year);
|
let is_weekend = day.is_weekend(config.month.number_from_month(), config.year);
|
||||||
let slot_first = Slot::new(Day(d), ShiftPosition::First);
|
let slot_first = Slot::new(Day(d), ShiftPosition::First);
|
||||||
let slot_first_res_id = self.get_resident_id(&slot_first);
|
let slot_first_r_id = self.get_resident_id(&slot_first);
|
||||||
let res_name_1 = config
|
let res_name_1 = config
|
||||||
.residents
|
.residents
|
||||||
.iter()
|
.iter()
|
||||||
.find(|r| Some(&r.id) == slot_first_res_id)
|
.find(|r| Some(&r.id) == slot_first_r_id)
|
||||||
.map(|r| r.name.as_str())
|
.map(|r| r.name.as_str())
|
||||||
.unwrap_or("-");
|
.unwrap_or("-");
|
||||||
|
|
||||||
let res_name_2 = if day.is_open_shift() {
|
let res_name_2 = if day.is_open_shift() {
|
||||||
let slot_second = Slot::new(Day(d), ShiftPosition::Second);
|
let slot_second = Slot::new(Day(d), ShiftPosition::Second);
|
||||||
let slot_second_res_id = self.get_resident_id(&slot_second);
|
let slot_second_r_id = self.get_resident_id(&slot_second);
|
||||||
config
|
config
|
||||||
.residents
|
.residents
|
||||||
.iter()
|
.iter()
|
||||||
.find(|r| Some(&r.id) == slot_second_res_id)
|
.find(|r| Some(&r.id) == slot_second_r_id)
|
||||||
.map(|r| r.name.as_str())
|
.map(|r| r.name.as_str())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -133,9 +133,9 @@ impl MonthlySchedule {
|
|||||||
),
|
),
|
||||||
TableCell::new().add_paragraph(
|
TableCell::new().add_paragraph(
|
||||||
Paragraph::new()
|
Paragraph::new()
|
||||||
.add_run(make_run(weekday_to_greek(
|
.add_run(make_run(
|
||||||
Day(d).weekday(config.month.number_from_month(), config.year),
|
Day(d).weekday_to_greek(config.month.number_from_month(), config.year),
|
||||||
)))
|
))
|
||||||
.fonts(RunFonts::new().ascii("Arial")),
|
.fonts(RunFonts::new().ascii("Arial")),
|
||||||
),
|
),
|
||||||
TableCell::new().add_paragraph(
|
TableCell::new().add_paragraph(
|
||||||
@@ -172,3 +172,21 @@ impl MonthlySchedule {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn month_to_greek(month: u32) -> &'static str {
|
||||||
|
match month {
|
||||||
|
1 => "Ιανουάριος",
|
||||||
|
2 => "Φεβρουάριος",
|
||||||
|
3 => "Μάρτιος",
|
||||||
|
4 => "Απρίλιος",
|
||||||
|
5 => "Μάιος",
|
||||||
|
6 => "Ιούνιος",
|
||||||
|
7 => "Ιούλιος",
|
||||||
|
8 => "Αύγουστος",
|
||||||
|
9 => "Σεπτέμβριος",
|
||||||
|
10 => "Οκτώβριος",
|
||||||
|
11 => "Νοέμβριος",
|
||||||
|
12 => "Δεκέμβριος",
|
||||||
|
_ => panic!("Unable to find translation for month {}", month),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,12 +5,11 @@ use crate::{
|
|||||||
slot::{Day, ShiftPosition, Slot},
|
slot::{Day, ShiftPosition, Slot},
|
||||||
};
|
};
|
||||||
|
|
||||||
use chrono::Month;
|
|
||||||
use rstest::fixture;
|
use rstest::fixture;
|
||||||
|
|
||||||
#[fixture]
|
#[fixture]
|
||||||
pub fn minimal_config() -> UserConfig {
|
pub fn minimal_config() -> UserConfig {
|
||||||
UserConfig::new(Month::April.number_from_month() as u8, 2026).with_residents(vec![
|
UserConfig::default().with_residents(vec![
|
||||||
Resident::new(1, "R1"),
|
Resident::new(1, "R1"),
|
||||||
Resident::new(2, "R2"),
|
Resident::new(2, "R2"),
|
||||||
Resident::new(3, "R3"),
|
Resident::new(3, "R3"),
|
||||||
@@ -21,7 +20,7 @@ pub fn minimal_config() -> UserConfig {
|
|||||||
|
|
||||||
#[fixture]
|
#[fixture]
|
||||||
pub fn maximal_config() -> UserConfig {
|
pub fn maximal_config() -> UserConfig {
|
||||||
UserConfig::new(Month::April.number_from_month() as u8, 2026)
|
UserConfig::default()
|
||||||
.with_holidays(vec![2, 3, 10, 11, 12, 25])
|
.with_holidays(vec![2, 3, 10, 11, 12, 25])
|
||||||
.with_residents(vec![
|
.with_residents(vec![
|
||||||
Resident::new(1, "R1").with_max_shifts(3),
|
Resident::new(1, "R1").with_max_shifts(3),
|
||||||
@@ -47,7 +46,7 @@ pub fn maximal_config() -> UserConfig {
|
|||||||
|
|
||||||
#[fixture]
|
#[fixture]
|
||||||
pub fn manual_shifts_heavy_config() -> UserConfig {
|
pub fn manual_shifts_heavy_config() -> UserConfig {
|
||||||
UserConfig::new(Month::April.number_from_month() as u8, 2026).with_residents(vec![
|
UserConfig::default().with_residents(vec![
|
||||||
Resident::new(1, "R1").with_manual_shifts(vec![
|
Resident::new(1, "R1").with_manual_shifts(vec![
|
||||||
Slot::new(Day(1), ShiftPosition::First),
|
Slot::new(Day(1), ShiftPosition::First),
|
||||||
Slot::new(Day(3), ShiftPosition::First),
|
Slot::new(Day(3), ShiftPosition::First),
|
||||||
@@ -66,7 +65,7 @@ pub fn manual_shifts_heavy_config() -> UserConfig {
|
|||||||
|
|
||||||
#[fixture]
|
#[fixture]
|
||||||
pub fn complex_config() -> UserConfig {
|
pub fn complex_config() -> UserConfig {
|
||||||
UserConfig::new(Month::April.number_from_month() as u8, 2026)
|
UserConfig::default()
|
||||||
.with_holidays(vec![5, 10, 12, 19])
|
.with_holidays(vec![5, 10, 12, 19])
|
||||||
.with_residents(vec![
|
.with_residents(vec![
|
||||||
Resident::new(1, "R1")
|
Resident::new(1, "R1")
|
||||||
@@ -96,7 +95,7 @@ pub fn complex_config() -> UserConfig {
|
|||||||
|
|
||||||
#[fixture]
|
#[fixture]
|
||||||
pub fn hard_config() -> UserConfig {
|
pub fn hard_config() -> UserConfig {
|
||||||
UserConfig::new(Month::April.number_from_month() as u8, 2026)
|
UserConfig::default()
|
||||||
.with_holidays(vec![25])
|
.with_holidays(vec![25])
|
||||||
.with_residents(vec![
|
.with_residents(vec![
|
||||||
Resident::new(1, "R1")
|
Resident::new(1, "R1")
|
||||||
|
|||||||
@@ -107,9 +107,7 @@ pub fn run() {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use ctor::ctor;
|
use ctor::ctor;
|
||||||
use rstest::rstest;
|
|
||||||
|
|
||||||
#[ctor]
|
#[ctor]
|
||||||
fn global_setup() {
|
fn global_setup() {
|
||||||
@@ -118,9 +116,4 @@ mod tests {
|
|||||||
.is_test(true)
|
.is_test(true)
|
||||||
.try_init();
|
.try_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
|
||||||
pub fn test_endpoints() {
|
|
||||||
// see how tauri mocks endpoint tests
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use std::collections::HashMap;
|
|||||||
use crate::{
|
use crate::{
|
||||||
config::UserConfig,
|
config::UserConfig,
|
||||||
resident::ResidentId,
|
resident::ResidentId,
|
||||||
slot::{weekday_to_greek, Day, ShiftPosition, Slot},
|
slot::{Day, ShiftPosition, Slot},
|
||||||
workload::WorkloadTracker,
|
workload::WorkloadTracker,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -63,18 +63,6 @@ impl MonthlySchedule {
|
|||||||
.any(|s| self.get_resident_id(s) == self.get_resident_id(slot))
|
.any(|s| self.get_resident_id(s) == self.get_resident_id(slot))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resident_worked_on_day(&self, day: Day, res_id: ResidentId) -> bool {
|
|
||||||
if day.0 < 1 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let first = Slot::new(day, ShiftPosition::First);
|
|
||||||
let second = Slot::new(day, ShiftPosition::Second);
|
|
||||||
|
|
||||||
self.get_resident_id(&first) == Some(&res_id)
|
|
||||||
|| self.get_resident_id(&second) == Some(&res_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print(&self, config: &UserConfig) -> String {
|
pub fn pretty_print(&self, config: &UserConfig) -> String {
|
||||||
let mut sorted: Vec<_> = self.0.iter().collect();
|
let mut sorted: Vec<_> = self.0.iter().collect();
|
||||||
sorted.sort_by_key(|(slot, _)| (slot.day, slot.position));
|
sorted.sort_by_key(|(slot, _)| (slot.day, slot.position));
|
||||||
@@ -91,10 +79,8 @@ impl MonthlySchedule {
|
|||||||
output.push_str(&format!(
|
output.push_str(&format!(
|
||||||
"Ημέρα {:2} - {:9} - {:11}: {},\n",
|
"Ημέρα {:2} - {:9} - {:11}: {},\n",
|
||||||
slot.day.0,
|
slot.day.0,
|
||||||
weekday_to_greek(
|
|
||||||
slot.day
|
slot.day
|
||||||
.weekday(config.month.number_from_month(), config.year)
|
.weekday_to_greek(config.month.number_from_month(), config.year),
|
||||||
),
|
|
||||||
slot.shift_type_str(),
|
slot.shift_type_str(),
|
||||||
res_name
|
res_name
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ impl Slot {
|
|||||||
self.day == Day(1) && self.position == ShiftPosition::First
|
self.day == Day(1) && self.position == ShiftPosition::First
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_first_day(&self) -> bool {
|
||||||
|
self.day == Day(1)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_open_first(&self) -> bool {
|
pub fn is_open_first(&self) -> bool {
|
||||||
self.is_open_shift() && self.position == ShiftPosition::First
|
self.is_open_shift() && self.position == ShiftPosition::First
|
||||||
}
|
}
|
||||||
@@ -160,20 +164,9 @@ impl Day {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn weekday(&self, month: u32, year: i32) -> Weekday {
|
pub fn weekday_to_greek(&self, month: u32, year: i32) -> &'static str {
|
||||||
let date = NaiveDate::from_ymd_opt(year, month, self.0 as u32).unwrap();
|
let date = NaiveDate::from_ymd_opt(year, month, self.0 as u32).unwrap();
|
||||||
date.weekday()
|
match date.weekday() {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, PartialOrd, Ord, Eq, Debug, Hash, Clone, Copy)]
|
|
||||||
pub enum ShiftPosition {
|
|
||||||
First,
|
|
||||||
Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn weekday_to_greek(weekday: Weekday) -> &'static str {
|
|
||||||
match weekday {
|
|
||||||
Weekday::Mon => "Δευτέρα",
|
Weekday::Mon => "Δευτέρα",
|
||||||
Weekday::Tue => "Τρίτη",
|
Weekday::Tue => "Τρίτη",
|
||||||
Weekday::Wed => "Τετάρτη",
|
Weekday::Wed => "Τετάρτη",
|
||||||
@@ -183,23 +176,12 @@ pub fn weekday_to_greek(weekday: Weekday) -> &'static str {
|
|||||||
Weekday::Sun => "Κυριακή",
|
Weekday::Sun => "Κυριακή",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn month_to_greek(month: u32) -> &'static str {
|
|
||||||
match month {
|
|
||||||
1 => "Ιανουάριος",
|
|
||||||
2 => "Φεβρουάριος",
|
|
||||||
3 => "Μάρτιος",
|
|
||||||
4 => "Απρίλιος",
|
|
||||||
5 => "Μάιος",
|
|
||||||
6 => "Ιούνιος",
|
|
||||||
7 => "Ιούλιος",
|
|
||||||
8 => "Αύγουστος",
|
|
||||||
9 => "Σεπτέμβριος",
|
|
||||||
10 => "Οκτώβριος",
|
|
||||||
11 => "Νοέμβριος",
|
|
||||||
12 => "Δεκέμβριος",
|
|
||||||
_ => panic!("Unable to find translation for month {}", month),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, PartialOrd, Ord, Eq, Debug, Hash, Clone, Copy)]
|
||||||
|
pub enum ShiftPosition {
|
||||||
|
First,
|
||||||
|
Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -225,6 +207,14 @@ mod tests {
|
|||||||
assert!(!slot_2.is_first());
|
assert!(!slot_2.is_first());
|
||||||
assert!(!slot_3.is_first());
|
assert!(!slot_3.is_first());
|
||||||
|
|
||||||
|
assert!(slot_1.is_first_day());
|
||||||
|
assert!(slot_2.is_first_day());
|
||||||
|
assert!(!slot_3.is_first_day());
|
||||||
|
|
||||||
|
assert!(slot_1.is_open_first());
|
||||||
|
assert!(!slot_2.is_open_first());
|
||||||
|
assert!(!slot_3.is_open_first());
|
||||||
|
|
||||||
assert!(!slot_1.is_open_second());
|
assert!(!slot_1.is_open_second());
|
||||||
assert!(slot_2.is_open_second());
|
assert!(slot_2.is_open_second());
|
||||||
assert!(!slot_3.is_open_second());
|
assert!(!slot_3.is_open_second());
|
||||||
|
|||||||
@@ -22,10 +22,14 @@ mod integration_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_minimal_config(minimal_config: UserConfig) -> anyhow::Result<()> {
|
fn test_minimal_config(
|
||||||
|
#[values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] month_idx: u8,
|
||||||
|
mut minimal_config: UserConfig,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
minimal_config.update_month(month_idx);
|
||||||
|
let scheduler = Scheduler::new_with_config(minimal_config.clone());
|
||||||
let mut schedule = MonthlySchedule::new();
|
let mut schedule = MonthlySchedule::new();
|
||||||
let mut tracker = WorkloadTracker::default();
|
let mut tracker = WorkloadTracker::default();
|
||||||
let scheduler = Scheduler::new_with_config(minimal_config.clone());
|
|
||||||
|
|
||||||
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
||||||
println!("{}", schedule.report(&minimal_config, &tracker));
|
println!("{}", schedule.report(&minimal_config, &tracker));
|
||||||
@@ -36,10 +40,14 @@ mod integration_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_maximal_config(maximal_config: UserConfig) -> anyhow::Result<()> {
|
fn test_maximal_config(
|
||||||
|
#[values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] month_idx: u8,
|
||||||
|
mut maximal_config: UserConfig,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
maximal_config.update_month(month_idx);
|
||||||
|
let scheduler = Scheduler::new_with_config(maximal_config.clone());
|
||||||
let mut schedule = MonthlySchedule::new();
|
let mut schedule = MonthlySchedule::new();
|
||||||
let mut tracker = WorkloadTracker::default();
|
let mut tracker = WorkloadTracker::default();
|
||||||
let scheduler = Scheduler::new_with_config(maximal_config.clone());
|
|
||||||
|
|
||||||
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
||||||
println!("{}", schedule.report(&maximal_config, &tracker));
|
println!("{}", schedule.report(&maximal_config, &tracker));
|
||||||
@@ -51,11 +59,13 @@ mod integration_tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_manual_shifts_heavy_config(
|
fn test_manual_shifts_heavy_config(
|
||||||
manual_shifts_heavy_config: UserConfig,
|
#[values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] month_idx: u8,
|
||||||
|
mut manual_shifts_heavy_config: UserConfig,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
manual_shifts_heavy_config.update_month(month_idx);
|
||||||
|
let scheduler = Scheduler::new_with_config(manual_shifts_heavy_config.clone());
|
||||||
let mut schedule = MonthlySchedule::new();
|
let mut schedule = MonthlySchedule::new();
|
||||||
let mut tracker = WorkloadTracker::default();
|
let mut tracker = WorkloadTracker::default();
|
||||||
let scheduler = Scheduler::new_with_config(manual_shifts_heavy_config.clone());
|
|
||||||
|
|
||||||
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
||||||
println!("{}", schedule.report(&manual_shifts_heavy_config, &tracker));
|
println!("{}", schedule.report(&manual_shifts_heavy_config, &tracker));
|
||||||
@@ -66,10 +76,14 @@ mod integration_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_complex_config(complex_config: UserConfig) -> anyhow::Result<()> {
|
fn test_complex_config(
|
||||||
|
#[values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] month_idx: u8,
|
||||||
|
mut complex_config: UserConfig,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
complex_config.update_month(month_idx);
|
||||||
|
let scheduler = Scheduler::new_with_config(complex_config.clone());
|
||||||
let mut schedule = MonthlySchedule::new();
|
let mut schedule = MonthlySchedule::new();
|
||||||
let mut tracker = WorkloadTracker::default();
|
let mut tracker = WorkloadTracker::default();
|
||||||
let scheduler = Scheduler::new_with_config(complex_config.clone());
|
|
||||||
|
|
||||||
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
||||||
println!("{}", schedule.report(&complex_config, &tracker));
|
println!("{}", schedule.report(&complex_config, &tracker));
|
||||||
@@ -80,10 +94,14 @@ mod integration_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_hard_config(hard_config: UserConfig) -> anyhow::Result<()> {
|
fn test_hard_config(
|
||||||
|
#[values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] month_idx: u8,
|
||||||
|
mut hard_config: UserConfig,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
hard_config.update_month(month_idx);
|
||||||
|
let scheduler = Scheduler::new_with_config(hard_config.clone());
|
||||||
let mut schedule = MonthlySchedule::new();
|
let mut schedule = MonthlySchedule::new();
|
||||||
let mut tracker = WorkloadTracker::default();
|
let mut tracker = WorkloadTracker::default();
|
||||||
let scheduler = Scheduler::new_with_config(hard_config.clone());
|
|
||||||
|
|
||||||
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
let solved = scheduler.run(&mut schedule, &mut tracker)?;
|
||||||
println!("{}", schedule.report(&hard_config, &tracker));
|
println!("{}", schedule.report(&hard_config, &tracker));
|
||||||
@@ -95,9 +113,9 @@ mod integration_tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_export_pipeline(minimal_config: UserConfig) -> anyhow::Result<()> {
|
fn test_export_pipeline(minimal_config: UserConfig) -> anyhow::Result<()> {
|
||||||
|
let scheduler = Scheduler::new_with_config(minimal_config.clone());
|
||||||
let mut schedule = MonthlySchedule::new();
|
let mut schedule = MonthlySchedule::new();
|
||||||
let mut tracker = WorkloadTracker::default();
|
let mut tracker = WorkloadTracker::default();
|
||||||
let scheduler = Scheduler::new_with_config(minimal_config.clone());
|
|
||||||
assert!(scheduler.run(&mut schedule, &mut tracker)?);
|
assert!(scheduler.run(&mut schedule, &mut tracker)?);
|
||||||
|
|
||||||
schedule.export_as_docx(&minimal_config)?;
|
schedule.export_as_docx(&minimal_config)?;
|
||||||
@@ -105,6 +123,7 @@ mod integration_tests {
|
|||||||
let metadata = std::fs::metadata("rota.docx")?;
|
let metadata = std::fs::metadata("rota.docx")?;
|
||||||
assert!(metadata.len() > 0);
|
assert!(metadata.len() > 0);
|
||||||
std::fs::remove_file("rota.docx")?;
|
std::fs::remove_file("rota.docx")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user