library(cepis) source(file.path("helper", "utils.R")) with_server( list(route("/01001000", response(200L, json(SE_ADDRESS)))), function(client, server) { address <- cep_lookup("01001-000", client) check("lookup reads the address", identical(address$localidade, "S\u00e3o Paulo")) check("lookup reads the state", identical(address$uf, "SP")) check("lookup keeps the CEP unmasked", identical(address$cep, "01001000")) check("formatted_cep masks the address", identical(formatted_cep(address), "01001-000")) check("an address without geo has geo NULL", is.null(address$geo)) check("the address is a cepis_address", inherits(address, "cepis_address")) } ) precise <- c(SE_ADDRESS, list(geo = list( lat = -23.5, lon = -46.6, raio_m = 120L, precisao = "logradouro" ))) with_server( list(route("/01310100", response(200L, json(precise)))), function(client, server) { address <- cep_lookup("01310100", client) check("the coordinate is read", isTRUE(all.equal(address$geo$lat, -23.5))) check("raio_m is an integer", identical(address$geo$raio_m, 120L)) check("a street coordinate is precise", isTRUE(address$geo$is_precise)) } ) municipality <- c(SE_ADDRESS, list(geo = list( lat = -23.5, lon = -46.6, raio_m = 22000L, precisao = "localidade" ))) with_server( list(route("/01001000", response(200L, json(municipality)))), function(client, server) { address <- cep_lookup("01001000", client) check( "a municipality coordinate is not precise", isFALSE(address$geo$is_precise) ) } ) broken <- c(SE_ADDRESS, list(geo = list(lat = "not a number"))) with_server( list(route("/01001000", response(200L, json(broken)))), function(client, server) { address <- cep_lookup("01001000", client) check("a malformed geo is dropped", is.null(address$geo)) check( "a malformed geo does not lose the address", identical(address$localidade, "S\u00e3o Paulo") ) } ) grown <- c(SE_ADDRESS, list(campo_do_futuro = "value")) with_server( list(route("/01001000", response(200L, json(grown)))), function(client, server) { address <- cep_lookup("01001000", client) check( "an unknown field is kept in raw", identical(address$raw$campo_do_futuro, "value") ) } ) with_server( list(route( "/99999999", response(404L, json(list(erro = "cep_nao_encontrado", mensagem = "gone"))) )), function(client, server) { condition <- check_condition( "a missing CEP signals cepis_not_found", cep_lookup("99999999", client), "cepis_not_found" ) check("the condition carries the CEP", identical(condition$cep, "99999999")) check("404 is not retried, it is a definitive answer", calls(server, "/99999999") == 1L) } ) not_found_body <- function(faixa = NULL) { body <- list( erro = "cep_nao_encontrado", mensagem = "CEP n\u00e3o existe na base do DNE" ) if (!is.null(faixa)) { body$faixa <- faixa } json(body) } # 25845000 is the DNE's own first number for Areal, and one of the 957 that # were never issued: the guess the faixa exists to answer. with_server( list(route("/25845000", response(404L, not_found_body(AREAL_FAIXA)))), function(client, server) { condition <- check_condition( "a CEP inside a municipality's range is still not found", cep_lookup("25845000", client), "cepis_not_found" ) faixa <- condition$faixa check("the condition carries the faixa", inherits(faixa, "cepis_faixa")) check("the faixa names the municipality", identical(faixa$localidade, "Areal")) check("the faixa carries the state", identical(faixa$uf, "RJ")) check("the faixa carries the IBGE code", identical(faixa$ibge, "3300225")) check("the faixa counts the CEPs that exist", identical(faixa$ceps, 118L)) check( "the bounds are the CEPs that exist, unmasked", identical(c(faixa$cep_ini, faixa$cep_fim), c("25845001", "25849899")) ) check( "the message names the municipality", grepl("Areal/RJ", conditionMessage(condition), fixed = TRUE) ) check("the faixa prints", length(capture.output(print(faixa))) == 2L) check("a 404 with a faixa is not retried either", calls(server, "/25845000") == 1L) } ) with_server( list(route("/99999999", response(404L, not_found_body()))), function(client, server) { condition <- check_condition( "a CEP in a band nobody owns is not found too", cep_lookup("99999999", client), "cepis_not_found" ) check("an omitted faixa is NULL", is.null(condition$faixa)) check("the CEP is still carried", identical(condition$cep, "99999999")) check( "the message claims no range", !grepl("belongs to", conditionMessage(condition), fixed = TRUE) ) } ) # A faixa is decoration on an error. None of these may cost the caller the # error itself, which is the only thing it asked for. unusable <- list( "a null faixa" = "{\"erro\":\"x\",\"faixa\":null}", "an empty faixa" = "{\"erro\":\"x\",\"faixa\":{}}", "a faixa that is an array" = "{\"erro\":\"x\",\"faixa\":[]}", "a faixa that is a string" = "{\"erro\":\"x\",\"faixa\":\"Areal\"}", "a faixa with no municipality" = "{\"erro\":\"x\",\"faixa\":{\"uf\":\"RJ\"}}", "a faixa with an empty municipality" = "{\"erro\":\"x\",\"faixa\":{\"localidade\":\"\",\"uf\":\"RJ\"}}", "a truncated body" = "{\"erro\":\"cep_nao", "a body that is not JSON at all" = "captive portal", "an empty body" = "" ) for (label in names(unusable)) { with_server( list(route("/99999999", response(404L, unusable[[label]]))), function(client, server) { condition <- check_condition( paste0(label, " is still a clean cepis_not_found"), cep_lookup("99999999", client), "cepis_not_found" ) check(paste0(label, " yields no faixa"), is.null(condition$faixa)) } ) } odd_count <- c(AREAL_FAIXA[names(AREAL_FAIXA) != "ceps"], list(ceps = "many")) with_server( list(route("/25845000", response(404L, not_found_body(odd_count)))), function(client, server) { condition <- caught(cep_lookup("25845000", client)) check( "an unreadable count does not lose the municipality", identical(condition$faixa$localidade, "Areal") ) check("an unreadable count reads as zero", identical(condition$faixa$ceps, 0L)) } ) with_server( list(route("/01001000", response(200L, json(SE_ADDRESS)))), function(client, server) { check_condition( "a malformed CEP never leaves the machine", cep_lookup("123", client), "cepis_invalid_cep" ) check("no request was made for it", calls(server) == 0L) } ) with_server( list(route( "/00000000", response(400L, json(list(erro = "cep_invalido", mensagem = "rejected by the API"))) )), function(client, server) { condition <- check_condition( "a 400 becomes cepis_invalid_cep", cep_lookup("00000000", client), "cepis_invalid_cep" ) check( "it carries the message the API sent", grepl("rejected by the API", conditionMessage(condition), fixed = TRUE) ) } ) with_server( list(route("/01001000", response(200L, "captive portal"))), function(client, server) { check_condition( "a body that is not JSON signals cepis_invalid_response", cep_lookup("01001000", client), "cepis_invalid_response" ) } )