.cursor/skills/script-test/SKILL.md
Generate a companion verification script that exercises a target script with known inputs and asserts expected outputs. Uses the fm-debug infrastructure to report pass/fail results back to the agent. At Tier 1 the developer runs the test script manually. At Tier 3 the agent deploys, runs, and reads results autonomously. Triggers on phrases like "test this script", "write a test", "verification script", "assert results", or "prove this works".
npx skillsauth add petrowsky/agentic-fm script-testInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate a FileMaker test script that exercises a target script with known inputs, captures the results, and reports pass/fail via the Agentic-fm Debug infrastructure.
Read agent/config/automation.json and check project_tier (preferred) or default_tier.
agent/debug/output.jsonIdentify the script to test. Read the human-readable version from agent/xml_parsed/scripts_sanitized/ and determine:
If the developer has provided expected inputs and outputs, use those. Otherwise, derive test cases from the script logic.
Create a test plan with concrete test cases:
## Test plan: [Target Script Name]
### Test 1: Happy path
- Input: JSONSetElement ( "{}" ; [ "invoiceID" ; "INV-001" ; JSONString ] )
- Expected result: { "success": true }
- Expected side effect: Invoices::Status = "Sent"
### Test 2: Empty parameter
- Input: ""
- Expected result: { "success": false, "error": "missing parameter" }
- Expected side effect: none
### Test 3: Record not found
- Input: JSONSetElement ( "{}" ; [ "invoiceID" ; "NONEXISTENT" ; JSONString ] )
- Expected result: { "success": false, "error": "not found" }
- Expected side effect: none
Present the test plan to the developer for confirmation before generating.
Build a test script as fmxmlsnippet that:
Perform ScriptGet ( ScriptResult ) immediately after Perform Script# PURPOSE: Test script for [Target Script Name]
Allow User Abort [ Off ]
Set Error Capture [ On ]
# Build results array
Set Variable [ $results ; "[]" ]
Set Variable [ $testCount ; 0 ]
Set Variable [ $passCount ; 0 ]
# --- Test 1: Happy path ---
Set Variable [ $testName ; "Happy path" ]
Set Variable [ $input ; JSONSetElement ( "{}" ; [ "invoiceID" ; "INV-001" ; JSONString ] ) ]
Set Variable [ $expected ; JSONSetElement ( "{}" ; [ "success" ; True ; JSONBoolean ] ) ]
Perform Script [ "Target Script" ; Parameter: $input ]
Set Variable [ $actual ; Get ( ScriptResult ) ]
Set Variable [ $errData ; JSONSetElement ( "{}" ;
[ "lastError" ; Get ( LastError ) ; JSONNumber ] ;
[ "lastErrorDetail" ; Get ( LastErrorDetail ) ; JSONString ] ;
[ "lastErrorLocation" ; Get ( LastErrorLocation ) ; JSONString ]
) ]
# Assert
Set Variable [ $pass ; JSONGetElement ( $actual ; "success" ) = JSONGetElement ( $expected ; "success" ) ]
Set Variable [ $testCount ; $testCount + 1 ]
Set Variable [ $passCount ; $passCount + If ( $pass ; 1 ; 0 ) ]
Set Variable [ $results ; JSONSetElement ( $results ;
[ $testCount ; JSONSetElement ( "{}" ;
[ "test" ; $testName ; JSONString ] ;
[ "pass" ; $pass ; JSONBoolean ] ;
[ "expected" ; $expected ; JSONRaw ] ;
[ "actual" ; $actual ; JSONRaw ] ;
[ "errData" ; $errData ; JSONRaw ]
) ; JSONRaw ]
) ]
# --- (repeat for each test case) ---
# Report results via Agentic-fm Debug
Perform Script [ "Agentic-fm Debug" ; Parameter: JSONSetElement ( "{}" ;
[ "label" ; "Test results: Target Script" ; JSONString ] ;
[ "vars" ; JSONSetElement ( "{}" ;
[ "testCount" ; $testCount ; JSONNumber ] ;
[ "passCount" ; $passCount ; JSONNumber ] ;
[ "allPassed" ; $testCount = $passCount ; JSONBoolean ] ;
[ "results" ; $results ; JSONRaw ]
) ; JSONRaw ]
) ]
Exit Script [ JSONSetElement ( "{}" ;
[ "testCount" ; $testCount ; JSONNumber ] ;
[ "passCount" ; $passCount ; JSONNumber ] ;
[ "allPassed" ; $testCount = $passCount ; JSONBoolean ]
) ]
Use these comparison patterns depending on what's being tested:
| Assertion type | Pattern |
|---|---|
| Exact match | $actual = $expected |
| JSON key match | JSONGetElement ( $actual ; "key" ) = "expectedValue" |
| Not empty | not IsEmpty ( $actual ) |
| Error code | JSONGetElement ( $errData ; "lastError" ) = 0 |
| Contains | Position ( $actual ; "substring" ; 1 ; 1 ) > 0 |
grep "Agentic-fm Debug" "agent/context/{solution}/scripts.index"
Also look up the target script's ID for the Perform Script step reference.
python3 agent/scripts/validate_snippet.py agent/sandbox/Test_{ScriptName}.xml
POST {companion_url}/clipboard, create the script via Tier 3 raw AppleScript (Cmd+N → Rename → Cmd+V → Cmd+S)POST {companion_url}/trigger with { "fm_app_name": "...", "script": "Test_{ScriptName}", "target_file": "SolutionName" }agent/debug/output.jsonPresent the test script on the clipboard:
The test script is on your clipboard. To install and run it:
- In Script Workspace, press Cmd+N to create a new script
- Rename it to Test_{ScriptName}
- Cmd+V — paste the test script
- Cmd+S — save
- Run the test script
- Let me know when it's done — I'll read
agent/debug/output.jsondirectly.
Read agent/debug/output.json and parse the test results:
{
"vars": {
"testCount": 3,
"passCount": 2,
"allPassed": false,
"results": [
{ "test": "Happy path", "pass": true, ... },
{ "test": "Empty parameter", "pass": true, ... },
{ "test": "Record not found", "pass": false, "expected": "...", "actual": "..." }
]
}
}
For each failing test:
expected vs actual to identify the discrepancyerrData for any FM error that occurredPresent a summary:
## Test Results: [Target Script]
✅ 2/3 tests passed
| Test | Result | Notes |
|---|---|---|
| Happy path | PASS | |
| Empty parameter | PASS | |
| Record not found | FAIL | Expected error response, got empty string |
### Failing test analysis
Test 3 failed because the target script exits without a result when
the find returns 0 records. The script should Exit Script with an error
JSON when Get(FoundCount) = 0.
After testing is complete:
If a bug was found, suggest using script-debug or script-refactor to fix it.
Test_ prefix — e.g., Test_Process Invoice — so they're easy to identify and clean up$errData so unexpected errors are visibledevelopment
Generate a complete web application inside a FileMaker Web Viewer — self-contained HTML/CSS/JS styled with the FM theme, plus companion FM bridge scripts for bidirectional data flow. Use when the developer says "web viewer", "webviewer app", "HTML in FileMaker", "build web viewer", or when the layout-design skill delegates to the web-first output path. Recommended for modern, responsive UI, complex interactions (drag-and-drop, charts, rich text), or solutions considering future migration off FileMaker.
development
Trace references to a FileMaker object across the entire solution. Supports usage reports ("where is this field used?"), impact analysis ("what breaks if I rename this?"), and dead object scans ("show unused fields/scripts"). Use when the developer says "trace", "find references", "where is X used", "impact of renaming", "unused fields/scripts", "dead code", "what references X", or "is X used anywhere".
development
Analyze a FileMaker solution and produce a structured profile covering data model, business logic, UI layer, integrations, and health metrics. Uses on-disk pre-processing to handle solutions of any size without sending raw XML through the agent. Use when the developer says "analyze solution", "solution overview", "solution analysis", "solution profile", "solution spec", "what does this solution do", "solution summary", or wants a high-level understanding of an entire FileMaker solution.
development
Interactive setup wizard for agentic-fm. Detects what's already configured, walks the user through each remaining step, and verifies completion before proceeding. Use when the developer says "help me set up", "setup", "get started", "onboard", "first time setup", "install agentic-fm", "configure agentic-fm", or is clearly new to the project and needs guidance.