pub struct TestWorld { /* private fields */ }Expand description
Declarative test environment builder.
§Example
use agtrace_testing::TestWorld;
let world = TestWorld::new()
.with_project("project-a")
.enter_dir("project-a");
let result = world.run(&["session", "list"]).unwrap();
assert!(result.success());Implementations§
Source§impl TestWorld
impl TestWorld
Sourcepub fn builder() -> TestWorldBuilder
pub fn builder() -> TestWorldBuilder
Create a builder for constructing a TestWorld.
§Example
use agtrace_testing::TestWorld;
let world = TestWorld::builder()
.without_data_dir()
.build();Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new isolated test environment with default settings.
This is a convenience method that creates a fully initialized environment.
For testing edge cases, use TestWorld::builder().
Sourcepub fn remove_config(&self) -> Result<()>
pub fn remove_config(&self) -> Result<()>
Remove config.toml to simulate loss or fresh install.
§Example
let world = TestWorld::new();
world.remove_config().unwrap();
assert!(!world.assert_config_exists());Sourcepub fn remove_database(&self) -> Result<()>
pub fn remove_database(&self) -> Result<()>
Remove agtrace.db to simulate database loss.
§Example
let world = TestWorld::new();
world.remove_database().unwrap();
assert!(!world.assert_database_exists());Sourcepub fn write_raw_config(&self, content: &str) -> Result<()>
pub fn write_raw_config(&self, content: &str) -> Result<()>
Write arbitrary content to config.toml.
Creates the data directory if it doesn’t exist.
§Example
let world = TestWorld::builder().without_data_dir().build();
world.write_raw_config(r#"
[providers.claude_code]
enabled = true
log_root = "/custom/path"
"#).unwrap();
assert!(world.assert_config_exists());Sourcepub fn assert_database_exists(&self) -> bool
pub fn assert_database_exists(&self) -> bool
Check if agtrace.db exists.
Sourcepub fn assert_config_exists(&self) -> bool
pub fn assert_config_exists(&self) -> bool
Check if config.toml exists.
Sourcepub fn enter_dir<P: AsRef<Path>>(self, path: P) -> Self
pub fn enter_dir<P: AsRef<Path>>(self, path: P) -> Self
Change the current working directory (relative to temp root).
This is crucial for testing CWD-dependent logic.
This method consumes self for use in builder pattern chains.
For changing directory multiple times in a test, use set_cwd() instead.
Sourcepub fn set_cwd<P: AsRef<Path>>(&mut self, path: P)
pub fn set_cwd<P: AsRef<Path>>(&mut self, path: P)
Set the current working directory without consuming self.
This is useful when you need to change directories multiple times during a test.
§Example
let mut world = TestWorld::new()
.with_project("project-a")
.with_project("project-b");
// Move to project-a
world.set_cwd("project-a");
let result = world.run(&["session", "list"]).unwrap();
// Move to project-b
world.set_cwd("project-b");
let result = world.run(&["session", "list"]).unwrap();Sourcepub fn with_env(self, key: impl Into<String>, value: impl Into<String>) -> Self
pub fn with_env(self, key: impl Into<String>, value: impl Into<String>) -> Self
Set an environment variable for CLI execution.
Sourcepub fn with_project(self, project_name: &str) -> Self
pub fn with_project(self, project_name: &str) -> Self
Create a project directory structure.
Sourcepub fn configure_command<'a>(&self, cmd: &'a mut Command) -> &'a mut Command
pub fn configure_command<'a>(&self, cmd: &'a mut Command) -> &'a mut Command
Configure a CLI command with this test environment’s settings.
The caller must provide the base command (e.g., from cargo_bin_cmd!("agtrace")).
This method configures it with the appropriate data-dir, cwd, and env vars.
Sourcepub fn copy_sample(&self, sample_name: &str, dest_name: &str) -> Result<()>
pub fn copy_sample(&self, sample_name: &str, dest_name: &str) -> Result<()>
Copy a sample file to the log root.
Sourcepub fn copy_sample_to_project(
&self,
sample_name: &str,
dest_name: &str,
project_dir: &str,
) -> Result<()>
pub fn copy_sample_to_project( &self, sample_name: &str, dest_name: &str, project_dir: &str, ) -> Result<()>
Copy a sample file to a Claude-encoded project directory.
Sourcepub fn copy_sample_to_project_with_cwd(
&self,
sample_name: &str,
dest_name: &str,
target_project_dir: &str,
provider: TestProvider,
) -> Result<()>
pub fn copy_sample_to_project_with_cwd( &self, sample_name: &str, dest_name: &str, target_project_dir: &str, provider: TestProvider, ) -> Result<()>
Copy a sample file to a project with cwd and sessionId replacement.
This is the recommended method for creating isolated test sessions.
Sourcepub fn run(&self, args: &[&str]) -> Result<CliResult>
pub fn run(&self, args: &[&str]) -> Result<CliResult>
Execute a command using the project’s binary and return the result.
This is a convenience method that creates a command, configures it with the test environment settings, and executes it.
§Example
let world = TestWorld::new();
let result = world.run(&["session", "list"]).unwrap();
assert!(result.success());§Note
This method uses Command::cargo_bin() which requires the binary to be
built and the CARGO_BIN_EXE_ environment variable to be set (which
cargo test does automatically).
Sourcepub fn run_in_dir<P: AsRef<Path>>(
&mut self,
args: &[&str],
dir: P,
) -> Result<CliResult>
pub fn run_in_dir<P: AsRef<Path>>( &mut self, args: &[&str], dir: P, ) -> Result<CliResult>
Execute a command in a specific directory temporarily.
This helper temporarily changes the working directory, runs the command,
and restores the original directory. This is useful for testing commands
that depend on the current working directory without permanently changing
the TestWorld state.
§Example
let mut world = TestWorld::new()
.with_project("project-a")
.with_project("project-b");
// Run in project-a
let result_a = world.run_in_dir(&["session", "list"], "project-a").unwrap();
// Run in project-b (without manually changing cwd)
let result_b = world.run_in_dir(&["session", "list"], "project-b").unwrap();
// Original cwd is preservedSourcepub fn enable_provider(&self, provider: TestProvider) -> Result<()>
pub fn enable_provider(&self, provider: TestProvider) -> Result<()>
Enable a provider and configure it in the test environment.
This method:
- Creates the provider’s log directory
- Runs
provider setcommand to update config.toml - Enables the provider
§Example
let world = TestWorld::new();
world.enable_provider(TestProvider::Claude).unwrap();
world.enable_provider(TestProvider::Gemini).unwrap();This tests the CLI’s configuration routing logic.
Sourcepub fn get_session_file_path(
&self,
provider: TestProvider,
filename: &str,
) -> Result<PathBuf>
pub fn get_session_file_path( &self, provider: TestProvider, filename: &str, ) -> Result<PathBuf>
Get the full path to a session file.
This helper resolves the provider-specific directory encoding and returns the absolute path to the session file.
TODO(CRITICAL): This is a LAYER VIOLATION - test code should NOT know provider implementation details
Current issue:
- Testing layer depends on provider-specific directory encoding logic
- Same if/else branching duplicated in fixtures.rs
- Hardcoded knowledge of Claude’s “-” encoding vs Gemini’s hash-based subdirs
Required fix:
- Add
encode_project_path(project_root: &Path) -> PathBufto LogDiscovery trait - Each provider implements its own encoding (Claude: “-Users-foo-bar”, Gemini: hash, Codex: flat)
- Remove this if/else branching and call
adapter.discovery.encode_project_path() - Consolidate with fixtures.rs logic
This abstraction belongs in agtrace-providers, NOT in test utilities.
Sourcepub fn add_session(
&self,
provider: TestProvider,
dest_filename: &str,
) -> Result<()>
pub fn add_session( &self, provider: TestProvider, dest_filename: &str, ) -> Result<()>
Add a session log for the specified provider.
This method:
- Determines the provider’s log directory
- Places a sample session file in the correct location
- Handles provider-specific directory encoding via the provider adapter
§Example
let mut world = TestWorld::new()
.with_project("my-project")
.enter_dir("my-project");
world.enable_provider(TestProvider::Claude).unwrap();
// Add a Claude session for the current project
world.add_session(TestProvider::Claude, "session1.jsonl").unwrap();This tests the CLI’s ability to find logs in the correct provider directory.
Sourcepub fn set_file_mtime(
&self,
provider: TestProvider,
filename: &str,
mtime: SystemTime,
) -> Result<()>
pub fn set_file_mtime( &self, provider: TestProvider, filename: &str, mtime: SystemTime, ) -> Result<()>
Set file modification time for testing time-based logic.
This is useful for testing features that depend on file modification times, such as watch mode’s “most recently updated” session detection.
§Example
let mut world = TestWorld::new();
world.enable_provider(TestProvider::Claude).unwrap();
world.add_session(TestProvider::Claude, "session1.jsonl").unwrap();
// Set older modification time
let old_time = SystemTime::now() - Duration::from_secs(3600);
world.set_file_mtime(TestProvider::Claude, "session1.jsonl", old_time).unwrap();