use crate::engine::named_range::{NameScope, NamedDefinition};
use crate::engine::{Engine, EvalConfig};
use crate::reference::{CellRef, Coord, RangeRef};
use crate::test_workbook::TestWorkbook;
use formualizer_common::LiteralValue;
use formualizer_parse::parser::parse;
fn approx_eq(a: f64, b: f64) -> bool {
(a - b).abs() < 1e-9
}
#[test]
fn evaluate_cell_walks_named_range_deps_for_dirty_upstreams() {
let mut engine = Engine::new(TestWorkbook::new(), EvalConfig::default());
engine.graph.add_sheet("Inputs").unwrap();
engine.graph.add_sheet("Model").unwrap();
let model_sheet = engine.graph.sheet_id_mut("Model");
let range_start = CellRef::new(model_sheet, Coord::from_excel(1, 2, true, true));
let range_end = CellRef::new(model_sheet, Coord::from_excel(1, 3, true, true));
engine
.define_name(
"RANGE_REF",
NamedDefinition::Range(RangeRef::new(range_start, range_end)),
NameScope::Workbook,
)
.unwrap();
engine
.set_cell_value("Inputs", 1, 1, LiteralValue::Number(10.0))
.unwrap();
engine
.set_cell_formula("Model", 1, 1, parse("=Inputs!A1*1").unwrap())
.unwrap();
engine
.set_cell_formula("Model", 1, 2, parse("=Inputs!A1*2").unwrap())
.unwrap();
engine
.set_cell_formula("Model", 1, 3, parse("=Inputs!A1*3").unwrap())
.unwrap();
engine
.set_cell_formula("Model", 2, 1, parse("=Model!A1+SUM(RANGE_REF)").unwrap())
.unwrap();
engine.evaluate_all().unwrap();
let baseline = engine.get_cell_value("Model", 2, 1).unwrap();
assert!(
matches!(baseline, LiteralValue::Number(n) if approx_eq(n, 60.0)),
"baseline expected 60, got {baseline:?}",
);
engine
.set_cell_value("Inputs", 1, 1, LiteralValue::Number(100.0))
.unwrap();
let target = engine.evaluate_cell("Model", 2, 1).unwrap().unwrap();
assert!(
matches!(target, LiteralValue::Number(n) if approx_eq(n, 600.0)),
"after override, target should be 100 + 200 + 300 = 600; got {target:?}",
);
}