test_that("inmet_read correctly parses ZIP files", { test_cache <- file.path(tempdir(), "rmet_test_read") create_mock_inmet_data(test_cache, year = 2020) df <- inmet_read(years = 2020, dest_dir = test_cache, quiet = TRUE) expect_s3_class(df, "data.frame") expect_equal(nrow(df), 3) expect_equal(df$precip_mm[1], 0.0) expect_true(is.na(df$radiation_kjm2[1])) expect_equal(df$station_code[1], "A801") expect_equal(df$state[1], "RS") expect_s3_class(df$datetime, "POSIXct") df_filtered <- inmet_read( years = 2020, start_date = "2020-09-25", end_date = "2020-09-25", dest_dir = test_cache, quiet = TRUE ) expect_equal(nrow(df_filtered), 1) expect_equal(df_filtered$temp_dry_c[1], 18.5) df_sub <- inmet_read( years = 2020, stations = "A801", variables = c("precip_mm"), dest_dir = test_cache, quiet = TRUE ) expect_true("precip_mm" %in% names(df_sub)) expect_false("temp_dry_c" %in% names(df_sub)) }) test_that("inmet_read errors on NA years", { expect_error(inmet_read(years = NA_integer_), "integers") }) test_that("inmet_read errors when ZIP is missing", { td <- file.path(tempdir(), "rmet_read_nozip") dir.create(td, showWarnings = FALSE) expect_error( inmet_read(years = 2020, dest_dir = td), "not found" ) }) test_that("inmet_read quiet = FALSE emits messages", { td <- file.path(tempdir(), "rmet_read_quiet") create_mock_inmet_data(td, year = 2020) expect_message( inmet_read(years = 2020, dest_dir = td, quiet = FALSE), "Reading year" ) }) test_that("inmet_read warns on unknown variables", { td <- file.path(tempdir(), "rmet_read_vars") create_mock_inmet_data(td, year = 2020) expect_warning( inmet_read(years = 2020, dest_dir = td, variables = c("precip_mm", "nonexistent_col"), quiet = TRUE), "Unknown variables ignored" ) }) test_that("inmet_read warns when date filter removes all rows", { td <- file.path(tempdir(), "rmet_read_datefilter") create_mock_inmet_data(td, year = 2020) expect_warning( result <- inmet_read(years = 2020, dest_dir = td, start_date = "2099-01-01", end_date = "2099-01-02", quiet = TRUE), "No data left after" ) expect_equal(nrow(result), 0L) }) test_that("inmet_read warns when station filter matches nothing", { td <- file.path(tempdir(), "rmet_read_nostation") create_mock_inmet_data(td, year = 2020) expect_warning( expect_warning( result <- inmet_read(years = 2020, dest_dir = td, stations = "ZZZZ", quiet = TRUE), "No data was read" ), "No matching stations found" ) expect_equal(nrow(result), 0L) }) test_that("inmet_read warns on corrupt CSV inside ZIP", { td <- file.path(tempdir(), "rmet_read_corrupt") dir.create(td, showWarnings = FALSE) csv_name <- "INMET_S_RS_A801_PORTO_ALEGRE_01-01-2020_A_31-12-2020.CSV" csv_path <- file.path(tempdir(), csv_name) writeLines(c("HEADER", ";;;;", "INVALID;;;DATA"), csv_path) zip_path <- file.path(td, "2020.zip") old_wd <- setwd(tempdir()) on.exit(setwd(old_wd), add = TRUE) utils::zip(zipfile = zip_path, files = csv_name) file.remove(csv_path) expect_warning( expect_warning( result <- inmet_read(years = 2020, dest_dir = td, quiet = TRUE), "No data was read" ), "Could not parse" ) }) test_that("inmet_extract extracts CSVs to output directory", { td <- file.path(tempdir(), "rmet_extract_in") out <- file.path(tempdir(), "rmet_extract_out") create_mock_inmet_data(td, year = 2020) expect_message( paths <- inmet_extract(years = 2020, dest_dir = td, out_dir = out, quiet = FALSE), "Extracting year" ) expect_true(length(paths) > 0) expect_true(any(file.exists(paths))) }) test_that("inmet_extract warns when ZIP missing", { td <- file.path(tempdir(), "rmet_extract_nozip") out <- file.path(tempdir(), "rmet_extract_nozip_out") dir.create(td, showWarnings = FALSE) expect_warning( inmet_extract(years = 2020, dest_dir = td, out_dir = out, quiet = TRUE), "not found" ) }) test_that(".convert_tz handles unknown timezone", { expect_warning( result <- rmet:::.convert_tz( as.POSIXct("2020-01-01", tz = "UTC"), "Not/ATimezone" ), "Unknown timezone" ) expect_s3_class(result, "POSIXct") }) test_that(".safe_rbind returns NULL on empty input", { expect_null(rmet:::.safe_rbind(list())) }) test_that(".safe_rbind fills missing columns with NA", { a <- data.frame(x = 1, y = 2) b <- data.frame(x = 3, z = 4) result <- rmet:::.safe_rbind(list(a, b)) expect_true("y" %in% names(result)) expect_true("z" %in% names(result)) expect_true(is.na(result$y[2])) expect_true(is.na(result$z[1])) }) test_that("errors when unzip fails", { td <- file.path(tempdir(), "rmet_unzip_fail") create_mock_inmet_data(td, 2020) testthat::with_mocked_bindings( unzip = function(...) stop("fail unzip"), .package = "utils", { expect_error( inmet_read(years = 2020, dest_dir = td, quiet = TRUE), "Cannot open ZIP" ) } ) }) test_that("fallback datetime parsing is triggered", { td <- file.path(tempdir(), "rmet_bad_dt") create_mock_inmet_bad_datetime(td) df <- inmet_read(years = 2020, dest_dir = td, quiet = TRUE) expect_s3_class(df$datetime, "POSIXct") }) test_that(".safe_rbind handles completely disjoint columns", { a <- data.frame(a = 1) b <- data.frame(b = 2) c <- data.frame(c = 3) result <- rmet:::.safe_rbind(list(a, b, c)) expect_equal(nrow(result), 3) expect_true(all(c("a","b","c") %in% names(result))) }) test_that("inmet_read warns when inner unzip fails to extract a file", { td <- file.path(tempdir(), "rmet_inner_unzip_fail") create_mock_inmet_data(td, year = 2020) real_unzip <- utils::unzip call_count <- 0L testthat::with_mocked_bindings( unzip = function(zipfile, list = FALSE, files = NULL, exdir = tempdir(), ...) { if (isTRUE(list)) { return(real_unzip(zipfile, list = TRUE)) } call_count <<- call_count + 1L if (call_count == 1L) stop("simulated extract failure") real_unzip(zipfile, files = files, exdir = exdir, ...) }, .package = "utils", { expect_warning( expect_warning( inmet_read(years = 2020, dest_dir = td, quiet = TRUE), "No data was read" ), "Could not extract" ) } ) }) test_that("inmet_read handles CSV where all data rows are NA (parse returns NULL)", { td <- file.path(tempdir(), "rmet_allna") create_mock_inmet_allna(td, year = 2020) expect_warning( result <- inmet_read(years = 2020, dest_dir = td, quiet = TRUE), "No data was read" ) expect_equal(nrow(result), 0L) })