# Copyright (c) 2026 Quosient Ltd. # SPDX-License-Identifier: MIT library(testthat) library(ebx) test_that("ClientConfig initializes with default values", { config <- ClientConfig$new() expect_equal(config$base_url, "https://api.earthblox.io") expect_equal(config$api_prefix, "/v1beta") expect_equal(config$oauth_path, "/services/oauth/token/") # The driver is LocalFilePersistence when the secrets directory is writable, # or MemoryPersistence when it is not (e.g. on hosted/CI environments). expect_true( inherits(config$persistence_driver, "LocalFilePersistence") || inherits(config$persistence_driver, "MemoryPersistence") ) }) test_that("ClientConfig selects MemoryPersistence when secrets directory is not writable", { skip_on_cran() # Verify that chmod 0555 actually prevents writes on this system (it does not # when running as root or on some CI configurations). Skip if it does not. chmod_blocks_writes <- local({ probe_dir <- file.path(tempdir(), paste0("ebx_chmod_probe_", Sys.getpid())) dir.create(probe_dir, showWarnings = FALSE) Sys.chmod(probe_dir, mode = "0555") tf <- tempfile(tmpdir = probe_dir) created <- tryCatch( file.create(tf), warning = function(w) FALSE, error = function(e) FALSE ) Sys.chmod(probe_dir, mode = "0755") unlink(probe_dir, recursive = TRUE) !isTRUE(created) }) skip_if( !chmod_blocks_writes, "chmod 0555 does not prevent writes on this system (e.g. running as root)" ) # Create a directory and make it non-writable so that file.create() inside # the driver-selection logic will fail. non_writable <- file.path(tempdir(), paste0("ebx_test_nowrt_", Sys.getpid())) dir.create(non_writable, recursive = TRUE) Sys.chmod(non_writable, mode = "0555") on.exit({ Sys.chmod(non_writable, mode = "0755") unlink(non_writable, recursive = TRUE) }, add = TRUE) # Override API_SECRETS_PATH in the ebx namespace to a non-existent subdirectory # of the non-writable directory. The walk-up loop in ClientConfig$new() will # resolve the nearest existing ancestor to non_writable, which cannot be # written to, triggering the MemoryPersistence fallback. fake_path <- file.path(non_writable, "ebx", "secrets") ns <- asNamespace("ebx") old_path <- get("API_SECRETS_PATH", envir = ns) unlockBinding("API_SECRETS_PATH", ns) assign("API_SECRETS_PATH", fake_path, envir = ns) on.exit({ assign("API_SECRETS_PATH", old_path, envir = ns) lockBinding("API_SECRETS_PATH", ns) }, add = TRUE) config <- ClientConfig$new() expect_s3_class(config$persistence_driver, "MemoryPersistence") }) test_that("ClientConfig respects environment variables", { # Set environment variables Sys.setenv(EBX_API_EMULATOR_HOST = "http://localhost:8080") Sys.setenv(EBX_API_PREFIX_PATH = "/api/v2") config <- ClientConfig$new() expect_equal(config$base_url, "http://localhost:8080") expect_equal(config$api_prefix, "/api/v2") # Cleanup Sys.unsetenv("EBX_API_EMULATOR_HOST") Sys.unsetenv("EBX_API_PREFIX_PATH") }) test_that("ClientConfig generates correct API base URL", { config <- ClientConfig$new() api_url <- config$get_api_base_url() expect_equal(api_url, "https://api.earthblox.io/v1beta") }) test_that("ClientConfig generates correct OAuth URL", { config <- ClientConfig$new() oauth_url <- config$get_oauth_url() expect_equal(oauth_url, "https://api.earthblox.io/services/oauth/token/") }) test_that("ServiceClientConfig has empty API prefix", { config <- ServiceClientConfig$new() expect_equal(config$api_prefix, "") expect_equal(config$base_url, "https://api.earthblox.io") })