Skip to content

Commit a267cde

Browse files
committed
Built site for [email protected]: 1714ca4
1 parent 88240a7 commit a267cde

14 files changed

+1299
-43
lines changed

CLAUDE.html

Lines changed: 220 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CLAUDE.md

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working
4+
with code in this repository.
5+
6+
## Overview
7+
8+
shinytest2 is an R package that provides automated testing for Shiny
9+
applications using a headless Chromium browser via the chromote package.
10+
It integrates with testthat for snapshot-based testing of Shiny apps.
11+
12+
## Core Architecture
13+
14+
### Main Components
15+
16+
- **AppDriver (R6 class)**: The central testing interface defined in
17+
[R/app-driver.R](https://rstudio.github.io/shinytest2/R/app-driver.R).
18+
This R6 class manages:
19+
20+
- Launching Shiny apps in background R processes (via callr)
21+
- Controlling a headless Chrome browser (via chromote)
22+
- Capturing app state (inputs, outputs, exports)
23+
- Taking screenshots and executing JavaScript
24+
- Waiting for reactivity to stabilize
25+
26+
- **Test Recording**:
27+
[R/record-test.R](https://rstudio.github.io/shinytest2/R/record-test.R)
28+
implements an interactive test recorder that launches a special Shiny
29+
app to record user interactions and generate test code automatically.
30+
31+
- **Expectations**: The package provides several expectation methods
32+
split across files like
33+
[R/app-driver-expect-values.R](https://rstudio.github.io/shinytest2/R/app-driver-expect-values.R),
34+
[R/app-driver-expect-screenshot.R](https://rstudio.github.io/shinytest2/R/app-driver-expect-screenshot.R),
35+
etc. These wrap testthat’s snapshot functions.
36+
37+
### Key Design Patterns
38+
39+
1. **Split R6 Methods**: The AppDriver R6 class is split across
40+
multiple files (app-driver-\*.R) for maintainability. Each file
41+
handles a specific aspect (expectations, waiting, JavaScript
42+
execution, etc.).
43+
44+
2. **Background Processes**: Shiny apps run in separate R processes via
45+
callr to isolate them from the testing environment.
46+
47+
3. **Chromote Integration**: The package heavily uses chromote to
48+
control a headless Chrome browser for realistic user interaction
49+
simulation.
50+
51+
4. **Snapshot Testing**: Integrates with testthat’s snapshot testing
52+
infrastructure. Snapshots are stored in tests/testthat/\_snaps/.
53+
54+
5. **Test Mode**: Shiny apps must run with `test.mode = TRUE` to expose
55+
internal values via
56+
[`shiny::exportTestValues()`](https://rdrr.io/pkg/shiny/man/exportTestValues.html).
57+
58+
## Common Development Tasks
59+
60+
### Running Tests
61+
62+
``` r
63+
# Run all package tests
64+
devtools::test()
65+
66+
# Run specific test file
67+
testthat::test_file("tests/testthat/test-app-driver.R")
68+
69+
# Run tests with filter
70+
devtools::test(filter = "screenshot")
71+
```
72+
73+
### Building the Package
74+
75+
``` r
76+
# Load package for development
77+
devtools::load_all()
78+
79+
# Check package
80+
devtools::check()
81+
82+
# Build documentation
83+
devtools::document()
84+
85+
# Build website
86+
pkgdown::build_site()
87+
```
88+
89+
### Testing During Development
90+
91+
``` r
92+
# Create an AppDriver for interactive testing
93+
library(shinytest2)
94+
app <- AppDriver$new("path/to/app")
95+
app$view() # Opens browser for visual inspection
96+
app$get_values()
97+
app$set_inputs(input_name = value)
98+
app$stop()
99+
```
100+
101+
### Working with C++ Code
102+
103+
The package includes C++ code (in src/) compiled via cpp11. After
104+
modifying C++ code:
105+
106+
``` r
107+
# Rebuild and reload package
108+
devtools::load_all()
109+
```
110+
111+
## Important Implementation Details
112+
113+
### AppDriver Lifecycle
114+
115+
1. `$new()` initializes the driver:
116+
- Starts background R process with Shiny app
117+
- Launches ChromoteSession
118+
- Injects shiny-tracer.js for monitoring
119+
- Optionally waits for app to stabilize
120+
2. `$stop()` cleans up:
121+
- Stops Shiny process (SIGINT → SIGTERM → SIGKILL)
122+
- Closes ChromoteSession
123+
- Cleans up logs if requested
124+
125+
### Waiting Mechanisms
126+
127+
- `$wait_for_idle()`: Waits for Shiny to be idle (no reactivity) for a
128+
specified duration
129+
- `$wait_for_value()`: Waits for a specific input/output/export to have
130+
a non-ignored value
131+
- `$wait_for_js()`: Waits for JavaScript expression to evaluate to true
132+
- All set_inputs() calls wait by default until an output updates
133+
134+
### Screenshot Comparison
135+
136+
- Default selector changed in v0.3.0 from `"html"` to
137+
`"scrollable_area"`
138+
- [`compare_screenshot_threshold()`](https://rstudio.github.io/shinytest2/reference/compare_screenshot_threshold.md)
139+
in
140+
[R/compare-screenshot-threshold.R](https://rstudio.github.io/shinytest2/R/compare-screenshot-threshold.R)
141+
provides threshold-based comparison using convolution to handle minor
142+
pixel differences
143+
- Screenshots are platform-dependent; use `variant = platform_variant()`
144+
for cross-platform testing
145+
146+
### Test File Organization
147+
148+
- Package follows standard R package structure with tests in
149+
tests/testthat/
150+
- Recorded tests typically saved as test-app-.R
151+
- Support files (helper functions, data) should go in tests/testthat/
152+
and are loaded via
153+
[`load_app_support()`](https://rstudio.github.io/shinytest2/reference/app_support.md)
154+
155+
## Migration from shinytest
156+
157+
This package replaces the deprecated shinytest package. Key function:
158+
[`migrate_from_shinytest()`](https://rstudio.github.io/shinytest2/reference/migrate_from_shinytest.md)
159+
in [R/migrate.R](https://rstudio.github.io/shinytest2/R/migrate.R)
160+
converts old shinytest tests to shinytest2 format.
161+
162+
## Logging and Debugging
163+
164+
- `$get_logs()` returns a data.frame with timestamped logs from three
165+
sources:
166+
- “shinytest2”: AppDriver logging via `$log_message()`
167+
- “shiny”: stdout/stderr from the background Shiny process
168+
- “chromote”: Browser console, exceptions, and WebSocket traffic (if
169+
`options(shiny.trace = TRUE)`)
170+
- Set `options(shiny.trace = TRUE)` in the app’s options to capture all
171+
WebSocket messages
172+
173+
## CI/CD
174+
175+
The package uses rstudio/shiny-workflows GitHub Actions: - R-CMD-check
176+
runs on multiple platforms - Website deployment via pkgdown - Test apps
177+
can be tested in CI using the custom action at actions/test-app
178+
179+
## Testing Philosophy
180+
181+
- Prefer `$expect_values()` over `$expect_screenshot()` for robustness
182+
- Prefer `$expect_text()` over `$expect_html()` to avoid brittleness
183+
from internal DOM changes
184+
- Use `$expect_screenshot()` sparingly as screenshots are very brittle
185+
to:
186+
- R version changes
187+
- OS differences
188+
- Font differences
189+
- Package version updates
190+
191+
## Package Dependencies
192+
193+
Critical dependencies to be aware of: - **chromote** (≥ 0.5.0): Browser
194+
automation - **testthat** (≥ 3.3.1): Testing framework - **callr**:
195+
Background R processes - **shiny**: The framework being tested -
196+
**cpp11**: C++ integration for performance-critical operations

articles/in-depth.html

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)