Skip to content

Commit 1ab8366

Browse files
committed
Merge commit 'c45ce9352281f886e7dcc82d3dd59407c1c3834a'
2 parents 2459dbd + c45ce93 commit 1ab8366

File tree

143 files changed

+6896
-1128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+6896
-1128
lines changed

.claude/settings.local.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
"Bash(find:*)",
66
"Bash(R:*)",
77
"Bash(rm:*)",
8-
"Bash(air format:*)"
8+
"Bash(air format:*)",
9+
"Edit(R/**)",
10+
"Edit(tests/**)",
11+
"Edit(vignettes/**)"
912
],
1013
"deny": []
1114
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Claude Code Review
2+
3+
on:
4+
pull_request:
5+
types: [opened]
6+
# Optional: Only run on specific file changes
7+
# paths:
8+
# - "src/**/*.ts"
9+
# - "src/**/*.tsx"
10+
# - "src/**/*.js"
11+
# - "src/**/*.jsx"
12+
13+
jobs:
14+
claude-review:
15+
# Optional: Filter by PR author
16+
# if: |
17+
# github.event.pull_request.user.login == 'external-contributor' ||
18+
# github.event.pull_request.user.login == 'new-developer' ||
19+
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20+
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
pull-requests: read
25+
issues: read
26+
id-token: write
27+
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 1
33+
34+
- name: Run Claude Code Review
35+
id: claude-review
36+
uses: anthropics/claude-code-action@beta
37+
with:
38+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
39+
40+
# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1)
41+
# model: "claude-opus-4-1-20250805"
42+
43+
# Direct prompt for automated review (no @claude mention needed)
44+
direct_prompt: |
45+
Please review this pull request and MINIMAL provide feedback on
46+
potential bugs or issues. Never praise or flatter. Be concise.
47+
Use simple, clear language. If you don't have anything significant
48+
to add, just reply LGTM.
49+
50+
# Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
51+
# use_sticky_comment: true
52+
53+
# Optional: Add specific tools for running tests or linting
54+
# allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
55+
56+
# Optional: Skip review for certain conditions
57+
# if: |
58+
# !contains(github.event.pull_request.title, '[skip-review]') &&
59+
# !contains(github.event.pull_request.title, '[WIP]')

.github/workflows/claude.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Claude Code
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
pull_request_review_comment:
7+
types: [created]
8+
issues:
9+
types: [opened, assigned]
10+
pull_request_review:
11+
types: [submitted]
12+
13+
jobs:
14+
claude:
15+
if: |
16+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
pull-requests: read
24+
issues: read
25+
id-token: write
26+
actions: read # Required for Claude to read CI results on PRs
27+
steps:
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
with:
31+
fetch-depth: 1
32+
33+
- name: Install air
34+
uses: posit-dev/setup-air@v1
35+
36+
- uses: r-lib/actions/setup-r@v2
37+
with:
38+
use-public-rspm: true
39+
40+
- uses: r-lib/actions/setup-r-dependencies@v2
41+
with:
42+
extra-packages: any::rcmdcheck,roxygen2
43+
needs: check
44+
45+
- name: Run Claude Code
46+
id: claude
47+
uses: anthropics/claude-code-action@beta
48+
with:
49+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
50+
51+
# This is an optional setting that allows Claude to read CI results on PRs
52+
additional_permissions: |
53+
actions: read
54+
55+
# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1)
56+
# model: "claude-opus-4-1-20250805"
57+
58+
# Optional: Customize the trigger phrase (default: @claude)
59+
# trigger_phrase: "/claude"
60+
61+
# Optional: Trigger when specific user is assigned to an issue
62+
# assignee_trigger: "claude-bot"
63+
64+
# Optional: Allow Claude to run specific commands
65+
allowed_tools: "Bash(R:*);Bash(air format:*)"
66+
67+
# Optional: Add custom instructions for Claude to customize its behavior for your project
68+
# custom_instructions: |
69+
# Follow our coding standards
70+
# Ensure all new code has tests
71+
# Use TypeScript for new files
72+
73+
# Optional: Custom environment variables for Claude
74+
# claude_env: |
75+
# NODE_ENV: test

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Suggests:
4040
curl (>= 0.9.5),
4141
diffviewer (>= 0.1.0),
4242
digest (>= 0.6.33),
43+
gh,
4344
knitr,
4445
rmarkdown,
4546
rstudioapi,

NAMESPACE

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ export(it)
158158
export(local_edition)
159159
export(local_mock)
160160
export(local_mocked_bindings)
161+
export(local_mocked_r6_class)
162+
export(local_mocked_s3_method)
163+
export(local_mocked_s4_method)
161164
export(local_on_cran)
162165
export(local_reproducible_output)
163166
export(local_snapshotter)
@@ -192,6 +195,7 @@ export(skip_on_os)
192195
export(skip_on_travis)
193196
export(skip_unless_r)
194197
export(snapshot_accept)
198+
export(snapshot_download_gh)
195199
export(snapshot_reject)
196200
export(snapshot_review)
197201
export(source_dir)
@@ -233,4 +237,5 @@ importFrom(brio,readLines)
233237
importFrom(brio,writeLines)
234238
importFrom(lifecycle,deprecated)
235239
importFrom(magrittr,"%>%")
240+
importFrom(methods,new)
236241
useDynLib(testthat, .registration = TRUE)

NEWS.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# testthat (development version)
22

3+
* In `R CMD check`, snapshots now only advise on how to resolve failures once (#2207).
4+
* `snapshot_review()` includes a reject button and only displays the file navigation and the skip button if there are multiple files to review (#2025).
5+
* New `snapshot_download_gh()` makes it easy to get snapshots off GitHub and into your local package (#1779).
6+
* New `local_mocked_s3_method()`, `local_mocked_s4_method()`, and `local_mocked_r6_class()` allow you to mock S3 and S4 methods and R6 classes (#1892, #1916)
7+
* `expect_snapshot_file(name=)` must have a unique file path. If a snapshot file attempts to be saved with a duplicate `name`, an error will be thrown. (#1592)
8+
* `test_dir()`, `test_file()`, `test_package()`, `test_check()`, `test_local()`, `source_file()` gain a `shuffle` argument uses `sample()` to randomly reorder the top-level expressions in each test file (#1942). This random reordering surfaces dependencies between tests and code outside of any test, as well as dependencies between tests. This helps you find and eliminate unintentional dependencies.
9+
* `snapshot_accept(test)` now works when the test file name contains `.` (#1669).
10+
* `local_mock()` and `with_mock()` have been deprecated because they are no longer permitted in R 4.5.
11+
* `snapshot_review()` now passes `...` on to `shiny::runApp()` (#1928).
12+
* `expect_named()` now gives more informative errors (#2091).
13+
* `expect_*()` functions consistently and rigorously check their inputs (#1754).
14+
* `test_that()` no longer warns about the absence of `{}` since it no longer seems to be necessary.
15+
* `test_that()`, `describe()`, and `it()` can now be arbitrarily nested. Each component will skip only if it and its subtests don't contain any expectations. The interactive stop reporter has been fixed so it doesn't duplicate failures. (#2063, #2188).
16+
* Test filtering now works with `it()`, and the `desc` argument can take a character vector in order to recursively filter subtests (i.e. `it()` nested inside of `describe()`) (#2118).
317
* New `snapshot_reject()` rejects all modified snapshots by deleting the `.new` variants (#1923).
418
* New `SlowReporter` makes it easier to find the slowest tests in your package. The easiest way to run it is with `devtools::test(reporter = "slow")` (#1466).
519
* Power `expect_mapequal()` with `waldo::compare(list_as_map = TRUE)` (#1521).
@@ -34,7 +48,7 @@
3448
* Fixed an issue preventing compilation from succeeding due to deprecation / removal of `std::uncaught_exception()` (@kevinushey, #2047).
3549
* New `skip_unless_r()` to skip running tests on unsuitable versions of R, e.g. `skip_unless_r(">= 4.1.0")` to skip tests that require, say, `...names` (@MichaelChirico, #2022)
3650
* `skip_on_os()` gains an option `"emscripten"` of the `os` argument to skip tests on Emscripten (@eitsupi, #2103).
37-
* New expectation, `expect_shape()`, for testing the shape (i.e., the `length()`, `nrow()`, `ncol()`, or `dim()`), all in one place (#1423, @michaelchirico).
51+
* New expectation, `expect_shape()`, for testing the shape (i.e., the `nrow()`, `ncol()`, or `dim()`), all in one place (#1423, @michaelchirico).
3852

3953
# testthat 3.2.3
4054

R/auto-test.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ auto_test_package <- function(
8383
test_path <- normalizePath(file.path(path, "tests", "testthat"))
8484

8585
# Start by loading all code and running all tests
86-
withr::local_envvar("NOT_CRAN" = "true")
86+
local_assume_not_on_cran()
8787
pkgload::load_all(path)
8888
test_dir(
8989
test_path,

R/describe.R

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
describe <- function(description, code) {
6161
local_description_push(description)
6262

63-
test_code(code, parent.frame(), skip_on_empty = FALSE)
63+
code <- substitute(code)
64+
test_code(code, parent.frame())
6465
}
6566

6667
#' @export
@@ -69,5 +70,5 @@ it <- function(description, code = NULL) {
6970
local_description_push(description)
7071

7172
code <- substitute(code)
72-
test_code(code, env = parent.frame(), skip_on_empty = FALSE)
73+
test_code(code, parent.frame())
7374
}

R/edition.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ edition_deprecate <- function(in_edition, what, instead = NULL) {
2727
return()
2828
}
2929

30-
warn(c(
31-
paste0("`", what, "` was deprecated in ", edition_name(in_edition), "."),
30+
cli::cli_warn(c(
31+
"{.code {what}} was deprecated in {edition_name(in_edition)}.",
3232
i = instead
3333
))
3434
}
@@ -40,7 +40,7 @@ edition_require <- function(in_edition, what) {
4040
return()
4141
}
4242

43-
stop(paste0("`", what, "` requires ", edition_name(in_edition), "."))
43+
cli::cli_abort("{.code {what}} requires {edition_name(in_edition)}.")
4444
}
4545

4646
edition_name <- function(x) {

R/expect-comparison.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ expect_compare_ <- function(
3939

4040
cmp <- op(act$val, exp$val)
4141
if (length(cmp) != 1 || !is.logical(cmp)) {
42-
abort(
43-
"Result of comparison must be a single logical value",
42+
cli::cli_abort(
43+
"Result of comparison must be a single logical value.",
4444
call = trace_env
4545
)
4646
}
@@ -112,14 +112,14 @@ expect_gte <- function(object, expected, label = NULL, expected.label = NULL) {
112112
#' @param ... All arguments passed on to `expect_lt()`/`expect_gt()`.
113113
#' @keywords internal
114114
expect_less_than <- function(...) {
115-
warning("Deprecated: please use `expect_lt()` instead", call. = FALSE)
115+
cli::cli_warn("Deprecated: please use {.fn expect_lt} instead.")
116116
expect_lt(...)
117117
}
118118

119119
#' @rdname expect_less_than
120120
#' @export
121121
expect_more_than <- function(...) {
122-
warning("Deprecated: please use `expect_gt()` instead", call. = FALSE)
122+
cli::cli_warn("Deprecated: please use {.fn expect_gt} instead.")
123123
expect_gt(...)
124124
}
125125

0 commit comments

Comments
 (0)