Repository navigation
GUI Automation
Marc Jones edited this page Dec 30, 2025
·
1 revision
PdfEditor supports Roslyn C# scripting for GUI automation and testing. Scripts can interact with the MainWindowViewModel to automate workflows.
The ScriptingService executes C# scripts with the MainWindowViewModel as the global context. This enables:
- Automated testing of GUI workflows
- Batch processing via the GUI
- Scripted redaction operations
- Integration testing
Located at PdfEditor/Services/ScriptingService.cs:
public class ScriptingService
{
public async Task<ScriptExecutionResult> ExecuteAsync(string scriptCode);
public async Task<ScriptExecutionResult> ExecuteFileAsync(string scriptFilePath);
public List<string> ValidateScript(string scriptCode);
}Scripts run with:
-
Global
this: MainWindowViewModel instance - Available namespaces: System, System.IO, System.Linq, PdfEditor.*
- Type safety: Compile-time error checking
- Async support: Full async/await
| Method | Description |
|---|---|
LoadDocumentCommand(path) |
Load a PDF document |
RedactTextCommand(text) |
Redact all occurrences of text |
ApplyRedactionsCommand() |
Apply pending redactions |
SaveDocumentCommand(path) |
Save the document |
ExtractAllText() |
Extract all text from document |
| Property | Description |
|---|---|
CurrentDocument |
Info about loaded document |
FilePath |
Current file path |
PendingRedactions |
Collection of pending redactions |
LoadDocumentTimeoutSeconds |
Timeout for loading (default: 30) |
// automation-scripts/basic-redact.csx
await LoadDocumentCommand("/path/to/document.pdf");
await RedactTextCommand("CONFIDENTIAL");
await ApplyRedactionsCommand();
await SaveDocumentCommand("/path/to/output.pdf");// automation-scripts/test-birth-certificate.csx
await LoadDocumentCommand("/path/to/birth-certificate.pdf");
// Redact multiple terms
await RedactTextCommand("TORRINGTON");
await RedactTextCommand("CERTIFICATE");
await RedactTextCommand("FEE");
// Apply and save
await ApplyRedactionsCommand();
await SaveDocumentCommand("/tmp/redacted.pdf");
// Verify
var text = ExtractAllText();
if (text.Contains("TORRINGTON"))
throw new Exception("Redaction failed: TORRINGTON still present");
return "Success";// automation-scripts/batch-redact.csx
var files = Directory.GetFiles("/data/pdfs", "*.pdf");
foreach (var file in files)
{
await LoadDocumentCommand(file);
await RedactTextCommand("CONFIDENTIAL");
await ApplyRedactionsCommand();
var output = file.Replace(".pdf", "-redacted.pdf");
await SaveDocumentCommand(output);
Console.WriteLine($"Processed: {file}");
}
return $"Processed {files.Length} files";[Fact]
public async Task TestRedactionWorkflow()
{
var viewModel = CreateTestViewModel();
var scripting = new ScriptingService(viewModel);
var result = await scripting.ExecuteAsync(@"
await LoadDocumentCommand(""test.pdf"");
await RedactTextCommand(""SECRET"");
await ApplyRedactionsCommand();
return PendingRedactions.Count;
");
result.Success.Should().BeTrue();
result.ReturnValue.Should().Be(0);
}For potentially slow operations (issue #93):
// Set longer timeout for large documents
LoadDocumentTimeoutSeconds = 60;
await LoadDocumentCommand("/path/to/large.pdf");Validate scripts before execution:
var errors = scriptingService.ValidateScript(code);
if (errors.Any())
{
Console.WriteLine("Compilation errors:");
foreach (var error in errors)
Console.WriteLine($" {error}");
}Scripts throw exceptions on failure:
try
{
await LoadDocumentCommand("nonexistent.pdf");
}
catch (FileNotFoundException)
{
Console.WriteLine("File not found");
}
catch (TimeoutException)
{
Console.WriteLine("Load timed out");
}Current implementation:
- Scripts have full access to MainWindowViewModel
- No sandboxing - scripts can execute arbitrary code
- Only run trusted scripts
Best practices:
- Only run scripts from trusted sources
- Review scripts before execution
- Use in testing/development environments
Script execution is tested in:
-
AutomationScriptTests.cs- Script execution tests -
ScriptedGuiTests.cs- GUI workflow tests
automation-scripts/
├── test-birth-certificate.csx
├── test-verapdf-corpus-sample.csx
├── test-birth-certificate-specific-words.csx
└── README.md
-
Microsoft.CodeAnalysis.CSharp.Scriptingv5.0.0 - Size impact: ~2MB (Roslyn assemblies)
Last updated: 2024-12-29