tests/testthat/test-join_weather-integration.R

testthat::test_that("join_weather integrates: plans, fetches (mocked), caches, joins", {
  testthat::skip_if_not_installed("nasapower")
  
  # Use a temp cache dir so tests don't touch user/project cache
  tmp <- withr::local_tempdir()
  withr::local_options(list(
    # Make behaviour deterministic and avoid huge splitting
    weatherjoin.split_penalty_hours = 72,
    weatherjoin.pad_hours = 0,
    weatherjoin.max_parts = 50,
    weatherjoin.dummy_hour = 12,
    # Force fetch path (even if cache exists in tmp dir)
    weatherjoin.cache_refresh = "always",
    weatherjoin.cache_match_mode = "cover",
    weatherjoin.cache_param_match = "superset",
    weatherjoin.cache_max_age_days = 30,
    # rds cache format to avoid fst version warning
    weatherjoin.cache_format = "rds"
  ))
  
  # Minimal event table (2 times around the same hour)
  x <- data.frame(
    lat = 51.5,
    lon = -0.1,
    event_time = as.POSIXct(c("2024-06-01 12:10:00", "2024-06-01 12:50:00"), tz = "UTC")
  )
  
  # --- Mock nasapower::get_power() ---
  # We return a small hourly grid covering the request window with deterministic values.
  mock_get_power <- function(community, lonlat, site_elevation, pars, dates, temporal_api, time_standard, ...) {
    # 'dates' in your code is typically c(start_date, end_date) as character "YYYY-MM-DD"
    # We'll build hourly data for the whole date span.
    start <- as.POSIXct(paste0(dates[1], " 00:00:00"), tz = "UTC")
    end   <- as.POSIXct(paste0(dates[2], " 23:00:00"), tz = "UTC")
    tt <- seq(start, end, by = "hour")
    
    out <- data.frame(
      YEAR = as.integer(format(tt, "%Y")),
      MO   = as.integer(format(tt, "%m")),
      DY   = as.integer(format(tt, "%d")),
      HR   = as.integer(format(tt, "%H"))
    )
    
    # Provide the requested params as numeric columns
    pars_up <- toupper(pars)
    if ("T2M" %in% pars_up) out$T2M <- rep(15.4, nrow(out))
    if ("PRECTOTCORR" %in% pars_up) out$PRECTOTCORR <- rep(0.2, nrow(out))
    
    # Provide the same attribute shape you parse elsewhere (optional but realistic)
    attr(out, "POWER.Parameters") <- paste(
      sprintf("%-15s mock parameter", pars_up),
      collapse = " ;\n "
    )
    
    out
  }
  
  # Mock within the nasapower namespace for the duration of the test
  testthat::local_mocked_bindings(
    get_power = mock_get_power,
    .package = "nasapower"
  )
  
  # Run the real join_weather() (it will call mocked nasapower::get_power())
  out <- weatherjoin::join_weather(
    x = x,
    params = c("T2M", "PRECTOTCORR"),
    time = "event_time",
    time_api = "hourly",
    lat_col = "lat",
    lon_col = "lon",
    tz = "UTC",
    roll = "nearest",
    roll_max_hours = 1,
    cache_scope = "project",
    cache_dir = tmp,
    community = "ag",
    site_elevation = "constant",
    elev_constant = 100
  )
  
  testthat::expect_true(all(c("T2M", "PRECTOTCORR") %in% names(out)))
  testthat::expect_true(all(!is.na(out$T2M)))
  testthat::expect_true(all(!is.na(out$PRECTOTCORR)))
  
  # Rolling join should still match (values are constant anyway)
  testthat::expect_equal(out$T2M, c(15.4, 15.4))
  testthat::expect_equal(out$PRECTOTCORR, c(0.2, 0.2))
})

Try the weatherjoin package in your browser

Any scripts or data that you put into this service are public.

weatherjoin documentation built on Feb. 4, 2026, 5:11 p.m.