diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml new file mode 100644 index 0000000..5ef7c2c --- /dev/null +++ b/.github/workflows/test-coverage.yaml @@ -0,0 +1,33 @@ +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: test-coverage + +jobs: + test-coverage: + runs-on: ubuntu-24.04 + permissions: + contents: read + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::covr, any::xml2 + needs: coverage + + - name: Test coverage + run: | + cov <- covr::package_coverage(quiet = FALSE) + print(cov) + covr::to_cobertura(cov) + shell: Rscript {0} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6820133 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,28 @@ +# AGENTS.md + +Guidance for AI agents and contributors working on `magicaxis` (R package for base-graphics scientific plotting with minor ticks and log axes). + +## Layout +- `/R` one file per main function (`magaxis.R`, `magplot.R`, `magimage.R`, `magmap.R`, ...). `NAMESPACE` uses `exportPattern("^[[:alpha:]]+")`, so any function whose name starts with a letter is exported; prefix internal helpers with `.`. +- `/man` hand-written Rd files (no roxygen) — update the matching `.Rd` when changing arguments. +- `/tests/testthat` testthat (edition 3) tests; `/vignettes` knitr vignettes; `/data`, `/inst` supporting data. +- Extra `...` arguments are routed to base graphics via `ParmOff` (a GitHub-only dependency, `asgr/ParmOff`, see `Remotes` in `DESCRIPTION`). + +## Commands +```r +devtools::load_all(); devtools::test() # run tests +devtools::check() # or R CMD check +covr::package_coverage() # coverage +``` + +## Testing conventions +- Tests that draw must open a null device (`pdf(nullfile())` + `on.exit(dev.off())`), as in the `with_null_dev` helper in `tests/testthat/test-functions.R`; never rely on an interactive device. +- Prefer asserting on return values/structure; for pure plotting use `expect_no_error`. +- Add a test with any bug fix or new argument. + +## CI +- `.github/workflows/R-CMD-check.yaml`: R CMD check on Windows/macOS/Ubuntu. +- `.github/workflows/test-coverage.yaml`: covr coverage on Ubuntu. + +## Style +Keep the existing terse base-R style; do not reformat unrelated code. Bump `Version`/`Date` in `DESCRIPTION` for releases. diff --git a/tests/testthat/test-maglab-magmap.R b/tests/testthat/test-maglab-magmap.R new file mode 100644 index 0000000..2b433ec --- /dev/null +++ b/tests/testthat/test-maglab-magmap.R @@ -0,0 +1,38 @@ +## Tests for maglab and magmap (pure computation, no plotting). + +library(magicaxis) + +test_that("maglab returns tickat, labat and exp", { + out <- maglab(c(0, 10)) + expect_named(out, c("tickat", "labat", "exp")) + expect_true(all(is.finite(out$labat))) + expect_equal(out$tickat, out$labat) +}) + +test_that("maglab trim=TRUE keeps labels within limits", { + out <- maglab(c(0.5, 9.5), trim = TRUE) + expect_true(all(out$labat >= 0.5 & out$labat <= 9.5)) +}) + +test_that("maglab log=TRUE gives power-of-ten label locations", { + out <- maglab(c(1, 1000), log = TRUE) + expect_true(all(abs(log10(out$labat) - round(log10(out$labat))) < 1e-8)) + expect_true(min(out$labat) <= 1 && max(out$labat) >= 1000) +}) + +test_that("maglab usemultloc requires log=TRUE", { + expect_error(maglab(c(1, 100), usemultloc = TRUE, log = FALSE)) +}) + +test_that("magmap output lies within the requested range", { + out <- magmap(seq(1, 100), range = c(0, 1)) + expect_true(all(out$map >= 0 & out$map <= 1)) + expect_length(out$map, 100) +}) + +test_that("magmap flip=TRUE reverses a linear mapping", { + x <- seq(1, 10) + a <- magmap(x, type = "num", locut = 1, hicut = 10, range = c(0, 1))$map + b <- magmap(x, type = "num", locut = 1, hicut = 10, range = c(0, 1), flip = TRUE)$map + expect_equal(a, 1 - b) +})