From e544b946c94447235e4b54b9eb031c78d9660823 Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Tue, 14 Jul 2026 14:11:59 +0100 Subject: [PATCH] fix tests --- pipeline/transform/test_merge.py | 14 ++++++++++++++ server-rs/src/data/property/mod.rs | 19 +++++++++++++++++++ server-rs/src/og_middleware.rs | 9 +++++---- video/src/runner.ts | 6 ++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/pipeline/transform/test_merge.py b/pipeline/transform/test_merge.py index 6062fd2..0ea245b 100644 --- a/pipeline/transform/test_merge.py +++ b/pipeline/transform/test_merge.py @@ -1900,6 +1900,10 @@ def test_finalize_listings_promotes_overlay_columns_and_filters_to_listing_rows( "_actual_listing_date": [None, None], "_actual_listing_status": ["For sale", "For sale"], "_actual_listing_features": [["Garden"], ["Parking"]], + "_actual_price_history": [ + [{"date": "2024-01-01", "price": 600_000, "reason": "Reduced"}], + None, + ], "_actual_bedrooms": [3, 4], "_actual_bathrooms": [1, 2], "_actual_price_qualifier": ["", ""], @@ -1930,6 +1934,9 @@ def test_finalize_listings_promotes_overlay_columns_and_filters_to_listing_rows( "_actual_listing_date": pl.Datetime("us"), "_actual_listing_status": pl.Utf8, "_actual_listing_features": pl.List(pl.Utf8), + "_actual_price_history": pl.List( + pl.Struct({"date": pl.Utf8, "price": pl.Int64, "reason": pl.Utf8}) + ), "_actual_bedrooms": pl.Int32, "_actual_bathrooms": pl.Int32, "_actual_price_qualifier": pl.Utf8, @@ -1997,6 +2004,10 @@ def test_finalize_listings_dedupes_fanned_out_listing_rows() -> None: "_actual_listing_date": [None, None], "_actual_listing_status": ["For sale", "For sale"], "_actual_listing_features": [["Garden"], ["Garden"]], + "_actual_price_history": [ + [{"date": "2024-01-01", "price": 600_000, "reason": "Reduced"}], + [{"date": "2024-01-01", "price": 600_000, "reason": "Reduced"}], + ], "_actual_bedrooms": [3, 3], "_actual_bathrooms": [1, 1], "_actual_price_qualifier": ["", ""], @@ -2027,6 +2038,9 @@ def test_finalize_listings_dedupes_fanned_out_listing_rows() -> None: "_actual_listing_date": pl.Datetime("us"), "_actual_listing_status": pl.Utf8, "_actual_listing_features": pl.List(pl.Utf8), + "_actual_price_history": pl.List( + pl.Struct({"date": pl.Utf8, "price": pl.Int64, "reason": pl.Utf8}) + ), "_actual_bedrooms": pl.Int32, "_actual_bathrooms": pl.Int32, "_actual_price_qualifier": pl.Utf8, diff --git a/server-rs/src/data/property/mod.rs b/server-rs/src/data/property/mod.rs index 432b511..f5051e1 100644 --- a/server-rs/src/data/property/mod.rs +++ b/server-rs/src/data/property/mod.rs @@ -304,4 +304,23 @@ impl PropertyData { price_qualifier: FxHashMap::default(), } } + + /// Numeric-only instance with explicit quantization params, so tests can + /// exercise value decoding via `get_feature`. `values` is row-major u16 + /// (row * num_features + feat_idx); every feature is treated as numeric. + pub(crate) fn numeric_for_tests( + values: Vec, + num_features: usize, + dequant_a: Vec, + quant_min: Vec, + ) -> Self { + let mut data = Self::empty_for_tests(); + data.num_features = num_features; + data.num_numeric = num_features; + data.quant_range = vec![0.0; num_features]; + data.dequant_a = dequant_a; + data.quant_min = quant_min; + data.feature_data = SpillVec::owned(values); + data + } } diff --git a/server-rs/src/og_middleware.rs b/server-rs/src/og_middleware.rs index ea8ce57..9f597c6 100644 --- a/server-rs/src/og_middleware.rs +++ b/server-rs/src/og_middleware.rs @@ -300,10 +300,11 @@ fn route_seo_tags( let query_e = escape_attr(query_string); // Generated data pages have a clean URL with no query, but their OG card must frame the finding's // map view rather than the default whole-England map. Use the registry's screenshot query. - let screenshot_query_base = match crate::generated_data_pages::data_page(trim_trailing_slash(path)) { - Some(dp) if !dp.screenshot_query.is_empty() => dp.screenshot_query, - _ => query_string, - }; + let screenshot_query_base = + match crate::generated_data_pages::data_page(trim_trailing_slash(path)) { + Some(dp) if !dp.screenshot_query.is_empty() => dp.screenshot_query, + _ => query_string, + }; let screenshot_query_string = query_string_with_language(screenshot_query_base, language); let screenshot_query_e = escape_attr(&screenshot_query_string); let public_url_e = escape_attr(public_url.trim_end_matches('/')); diff --git a/video/src/runner.ts b/video/src/runner.ts index 298f330..1f56229 100644 --- a/video/src/runner.ts +++ b/video/src/runner.ts @@ -483,6 +483,12 @@ async function tryResolveTarget( const locator = ctx.page.locator(target.selector).first(); try { await locator.waitFor({ state: 'visible', timeout: timeoutMs }); + // Playwright's "visible" only means the element has a box; a filter-card + // button can sit scrolled out of the bottom sheet's viewport, and a blind + // click at its coordinates would land on the map behind the sheet. + // Scrolling it into view first makes the click (and the recording of it) + // honest. + await locator.scrollIntoViewIfNeeded({ timeout: timeoutMs }).catch(() => {}); const box = await locator.boundingBox({ timeout: timeoutMs }); if (!box) return null; return { x: box.x + box.width / 2, y: box.y + box.height / 2 };