← All blueprints
πŸ§ͺ

E2E Test Author LangGraph

blueprint Β· 5 agents Β· 3 MCP servers
1520β˜… stars
214forks
4.8rating

What it does

A planner turns the user story into concrete scenarios: the happy path, the edge cases, the failure states worth asserting. A coder writes Playwright tests for them. A runner executes the tests against the real page in a browser. On failure, a healer diagnoses: a drifted selector or a wrong assertion gets fixed and re-run; a genuine application bug is kept as a failing test and flagged, never papered over. The loop continues until the suite passes honestly or the budget is spent, then a reporter opens the tests as a pull request.

The cast Β· 5 agents

Codercodercoding

Write a Playwright test per scenario. Prefer role- and text-based locators over brittle CSS paths. If the healer sent fixes, apply exactly those. Save the files.

fs.write_file
Healerhealerreasoning

For each failure, decide the cause: a selector that drifted, an assertion that misreads intended behavior, or a genuine application bug. Return an object with a 'green' boolean (true when every remaining failure is a genuine bug or nothing fails), the selector/assertion fixes for the coder, and the genuine bugs. Never rewrite a test just to make a real bug pass.

no tools Β· reasoning only
Runnerrunnerfast

Run each test's steps against the real page in the browser: navigate, act, and check the assertions by inspecting the page state. Report pass or fail per test with what the page actually showed on failure.

browser.openbrowser.clickbrowser.snapshot
Plannerplannerreasoning

Derive the scenarios this story needs covered: the happy path, boundary inputs, and the failure states a user could hit. Keep the list short and high-value. Do not write code.

no tools Β· reasoning only
Reporterreporterfast

Open a pull request with the suite, the scenarios covered, and β€” prominently β€” any genuine bugs the tests exposed, each with its failing test as the reproduction.

code.open_pr

Flow

β†’ Planner β†’ scenarios
↻ loop until verdict.green == true Β· max 4
β†’ Coder β†’ suite
β†’ Runner β†’ runResult
β†’ Healer β†’ verdict
β†’ Reporter β†’ pr

Interface

Inputs
storystring
The user story or PR to derive tests from, plus the app URL.
Outputs
prstring
The pull request with the passing suite, and any genuine bugs found.

Depends on Β· 3 MCP servers

🌐Playwrightio.github.microsoft/playwright-mcpbrowserBVerified
πŸ”Œio.github.modelcontextprotocol/filesystemnot in the registry yetfs
πŸ”Œio.github.github/github-mcpnot in the registry yetcode
– Export runnable code
# Generated by @socketcat/compiler for target: langgraph
# blueprint: com.socketcat/e2e-test-author v1.0.0   schema: socketcat.dev/blueprint/v0
# This code is yours. Edit it freely. The socketcat_runtime helper is optional and can be vendored.

from typing import TypedDict
from langgraph.graph import StateGraph, START, END
import socketcat_runtime as _rt

class State(TypedDict, total=False):
    story: object
    pr: object
    scenarios: object
    __loop_1: object
    suite: object
    runResult: object
    verdict: object

def node_AgentInvoke_0(state):
    return _rt.run_agent("planner", state, {"story":"story"}, "scenarios")

def node_LoopHeader_1(state):
    return {}

def node_LoopTick_2(state):
    return {"__loop_1": state.get("__loop_1", 0) + 1}

def node_Nop_3(state):
    return {}

def node_AgentInvoke_4(state):
    return _rt.run_agent("coder", state, {"verdict":"verdict","scenarios":"scenarios"}, "suite")

def node_AgentInvoke_5(state):
    return _rt.run_agent("runner", state, {"suite":"suite"}, "runResult")

def node_AgentInvoke_6(state):
    return _rt.run_agent("healer", state, {"runResult":"runResult","scenarios":"scenarios"}, "verdict")

def node_AgentInvoke_7(state):
    return _rt.run_agent("reporter", state, {"suite":"suite","verdict":"verdict"}, "pr")

def route_LoopHeader_1(state):
    count = state.get("__loop_1", 0)
    return "exit" if (_rt.cond("verdict.green == true", state) or count >= 4) else "loop"

def build():
    b = StateGraph(State)
    b.add_node("AgentInvoke_0", node_AgentInvoke_0)
    b.add_node("LoopHeader_1", node_LoopHeader_1)
    b.add_node("LoopTick_2", node_LoopTick_2)
    b.add_node("Nop_3", node_Nop_3)
    b.add_node("AgentInvoke_4", node_AgentInvoke_4)
    b.add_node("AgentInvoke_5", node_AgentInvoke_5)
    b.add_node("AgentInvoke_6", node_AgentInvoke_6)
    b.add_node("AgentInvoke_7", node_AgentInvoke_7)
    b.add_edge(START, "AgentInvoke_0")
    b.add_edge("AgentInvoke_0", "AgentInvoke_4")
    b.add_conditional_edges("LoopHeader_1", route_LoopHeader_1, {"loop": "AgentInvoke_4", "exit": "Nop_3"})
    b.add_edge("LoopTick_2", "LoopHeader_1")
    b.add_edge("Nop_3", "AgentInvoke_7")
    b.add_edge("AgentInvoke_4", "AgentInvoke_5")
    b.add_edge("AgentInvoke_5", "AgentInvoke_6")
    b.add_edge("AgentInvoke_6", "LoopTick_2")
    b.add_edge("AgentInvoke_7", END)
    return b.compile()

INPUTS = ["story"]
OUTPUTS = ["pr"]

if __name__ == "__main__":
    _rt.main(build, INPUTS, OUTPUTS)
β–Έblueprint.json (the portable format)
{
  "id": "com.socketcat/e2e-test-author",
  "flow": {
    "type": "sequence",
    "blocks": [
      {
        "in": {
          "story": "story"
        },
        "out": "scenarios",
        "use": "planner",
        "type": "agent"
      },
      {
        "max": 4,
        "type": "loop",
        "until": "verdict.green == true",
        "blocks": [
          {
            "in": {
              "verdict": "verdict",
              "scenarios": "scenarios"
            },
            "out": "suite",
            "use": "coder",
            "type": "agent"
          },
          {
            "in": {
              "suite": "suite"
            },
            "out": "runResult",
            "use": "runner",
            "type": "agent"
          },
          {
            "in": {
              "runResult": "runResult",
              "scenarios": "scenarios"
            },
            "out": "verdict",
            "use": "healer",
            "type": "agent"
          }
        ]
      },
      {
        "in": {
          "suite": "suite",
          "verdict": "verdict"
        },
        "out": "pr",
        "use": "reporter",
        "type": "agent"
      }
    ]
  },
  "tags": [
    "testing",
    "playwright",
    "self-healing",
    "qa"
  ],
  "title": "E2E Test Author",
  "agents": {
    "coder": {
      "model": {
        "hint": "coding"
      },
      "title": "Coder",
      "tools": [
        "fs.write_file"
      ],
      "instructions": "Write a Playwright test per scenario. Prefer role- and text-based locators over brittle CSS paths. If the healer sent fixes, apply exactly those. Save the files."
    },
    "healer": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Healer",
      "output": {
        "type": "object",
        "required": [
          "green"
        ],
        "properties": {
          "bugs": {
            "type": "array"
          },
          "fixes": {
            "type": "array"
          },
          "green": {
            "type": "boolean"
          }
        }
      },
      "instructions": "For each failure, decide the cause: a selector that drifted, an assertion that misreads intended behavior, or a genuine application bug. Return an object with a 'green' boolean (true when every remaining failure is a genuine bug or nothing fails), the selector/assertion fixes for the coder, and the genuine bugs. Never rewrite a test just to make a real bug pass."
    },
    "runner": {
      "model": {
        "hint": "fast"
      },
      "title": "Runner",
      "tools": [
        "browser.open",
        "browser.click",
        "browser.snapshot"
      ],
      "instructions": "Run each test's steps against the real page in the browser: navigate, act, and check the assertions by inspecting the page state. Report pass or fail per test with what the page actually showed on failure."
    },
    "planner": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Planner",
      "instructions": "Derive the scenarios this story needs covered: the happy path, boundary inputs, and the failure states a user could hit. Keep the list short and high-value. Do not write code."
    },
    "reporter": {
      "model": {
        "hint": "fast"
      },
      "title": "Reporter",
      "tools": [
        "code.open_pr"
      ],
      "instructions": "Open a pull request with the suite, the scenarios covered, and β€” prominently β€” any genuine bugs the tests exposed, each with its failing test as the reproduction."
    }
  },
  "estate": {
    "suite": {
      "type": "object",
      "description": "The current test files."
    },
    "verdict": {
      "type": "object",
      "description": "The healer's call, including a 'green' flag and real bugs found."
    },
    "runResult": {
      "type": "object",
      "description": "The runner's pass/fail results with failure detail."
    },
    "scenarios": {
      "type": "array",
      "description": "The planner's list of scenarios to cover."
    }
  },
  "$schema": "socketcat.dev/blueprint/v0",
  "authors": [
    {
      "url": "https://socketcat.com",
      "name": "SocketCat"
    }
  ],
  "license": "MIT",
  "servers": [
    {
      "ref": "io.github.microsoft/playwright-mcp",
      "alias": "browser"
    },
    {
      "ref": "io.github.modelcontextprotocol/filesystem",
      "alias": "fs"
    },
    {
      "ref": "io.github.github/github-mcp",
      "alias": "code"
    }
  ],
  "summary": "Plans scenarios from a user story, writes Playwright tests, runs them in a real browser, and self-heals failures until they pass for the right reason.",
  "targets": [
    "langgraph",
    "*"
  ],
  "version": "1.0.0",
  "interface": {
    "inputs": {
      "story": {
        "type": "string",
        "description": "The user story or PR to derive tests from, plus the app URL."
      }
    },
    "outputs": {
      "pr": {
        "type": "string",
        "description": "The pull request with the passing suite, and any genuine bugs found."
      }
    }
  },
  "extensions": {
    "dev.langgraph": {
      "checkpointer": "memory"
    }
  },
  "description": "A planner turns the user story into concrete scenarios: the happy path, the edge cases, the failure states worth asserting. A coder writes Playwright tests for them. A runner executes the tests against the real page in a browser. On failure, a healer diagnoses: a drifted selector or a wrong assertion gets fixed and re-run; a genuine application bug is kept as a failing test and flagged, never papered over. The loop continues until the suite passes honestly or the budget is spent, then a reporter opens the tests as a pull request."
}