Merge branch 'main' into feature/enhanced-toolkit-capabilities
This commit is contained in:
commit
bb8228f407
238
README.md
238
README.md
|
|
@ -1,237 +1,79 @@
|
|||
# BMad Method & BMad Core
|
||||
# BMad Method
|
||||
|
||||
[](https://www.npmjs.com/package/bmad-method)
|
||||
[](https://www.npmjs.com/package/bmad-method)
|
||||
[](https://www.npmjs.com/package/bmad-method)
|
||||
[](LICENSE)
|
||||
[](https://nodejs.org)
|
||||
[](https://discord.gg/gk8jAdXWmj)
|
||||
|
||||
---
|
||||
**Build More, Architect Dreams** — An AI-driven agile development framework with 21 specialized agents, 50+ guided workflows, and scale-adaptive intelligence that adjusts from bug fixes to enterprise systems.
|
||||
|
||||
<div align="center">
|
||||
## Why BMad?
|
||||
|
||||
## 🎉 NEW: BMAD V6 Installer - Create & Share Custom Content!
|
||||
Traditional AI tools do the thinking for you, producing average results. BMad agents act as expert collaborators who guide you through structured workflows to bring out your best thinking.
|
||||
|
||||
The completely revamped **BMAD V6 installer** now includes built-in support for creating, installing, and sharing custom modules, agents, workflows, templates, and tools! Build your own AI solutions or share them with your team - and real soon, with the whole BMad Community througha verified community sharing portal!
|
||||
- **Scale-Adaptive**: Automatically adjusts planning depth based on project complexity (Level 0-4)
|
||||
- **Structured Workflows**: Grounded in agile best practices across analysis, planning, architecture, and implementation
|
||||
- **Specialized Agents**: 12+ domain experts (PM, Architect, Developer, UX, Scrum Master, and more)
|
||||
- **Complete Lifecycle**: From brainstorming to deployment, with just-in-time documentation
|
||||
|
||||
**✨ What's New:**
|
||||
## Quick Start
|
||||
|
||||
- 📦 **Streamlined Custom Module Installation** - Package your custom content as installable modules
|
||||
- 🤖 **Agent & Workflow Sharing** - Distribute standalone agents and workflows
|
||||
- 🔄 **Unitary Module Support** - Install individual components without full modules
|
||||
- ⚙️ **Dependency Management** - Automatic handling of module dependencies
|
||||
- 🛡️ **Update-Safe Customization** - Your custom content persists through updates
|
||||
|
||||
**📚 Learn More:**
|
||||
|
||||
- [**Custom Content Overview**](http://docs.bmad-method.org/explanation/bmad-builder/custom-content-types/) - Discover all supported content types
|
||||
- [**Installation Guide**](http://docs.bmad-method.org/how-to/installation/install-custom-modules/) - Learn to create and install custom content
|
||||
- [**2 Very simple Custom Modules of questionable quality**](./samples/sample-custom-modules/README.md) - if you want to download and try to install a custom shared module, get an idea of how to bundle and share your own, or create your own personal agents, workflows and modules.
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## AI-Driven Agile Development That Scales From Bug Fixes to Enterprise
|
||||
|
||||
**Build More, Architect Dreams** (BMAD) with **21 specialized AI agents** across 4 official modules, and **50+ guided workflows** that adapt to your project's complexity—from quick bug fixes to enterprise platforms, and new step file workflows that allow for incredibly long workflows to stay on the rails longer than ever before!
|
||||
|
||||
Additionally - when we say 'Build More, Architect Dreams' - we mean it! The BMad Builder has landed, and now as of Alpha.15 is fully supported in the installation flow via NPX - custom stand along agents, workflows and the modules of your dreams! The community forge will soon open, endless possibility awaits!
|
||||
|
||||
> **🚀 v6 is a MASSIVE upgrade from v4!** Complete architectural overhaul, scale-adaptive intelligence, visual workflows, and the powerful BMad Core framework. v4 users: this changes everything. [See what's new →](#whats-new-in-v6)
|
||||
|
||||
> **📌 v6 Alpha Status:** Near-beta quality with vastly improved stability. Documentation is being finalized. New videos coming soon to [BMadCode YouTube](https://www.youtube.com/@BMadCode).
|
||||
|
||||
## 🎯 Why BMad Method?
|
||||
|
||||
Unlike generic AI coding assistants, BMad Method provides **structured, battle-tested workflows** powered by specialized agents who understand agile development. Each agent has deep domain expertise—from product management to architecture to testing—working together seamlessly.
|
||||
|
||||
**✨ Key Benefits:**
|
||||
|
||||
- **Scale-Adaptive Intelligence** - Automatically adjusts planning depth from bug fixes to enterprise systems
|
||||
- **Complete Development Lifecycle** - Analysis → Planning → Architecture → Implementation
|
||||
- **Specialized Expertise** - 19 agents with specific roles (PM, Architect, Developer, UX Designer, etc.)
|
||||
- **Proven Methodologies** - Built on agile best practices with AI amplification
|
||||
- **IDE Integration** - Works with Claude Code, Cursor, Windsurf, VS Code
|
||||
|
||||
## 🏗️ The Power of BMad Core
|
||||
|
||||
**BMad Method** is actually a sophisticated module built on top of **BMad Core** (**C**ollaboration **O**ptimized **R**eflection **E**ngine). This revolutionary architecture means:
|
||||
|
||||
- **BMad Core** provides the universal framework for human-AI collaboration
|
||||
- **BMad Method** leverages Core to deliver agile development workflows
|
||||
- **BMad Builder** lets YOU create custom modules as powerful as BMad Method itself
|
||||
|
||||
With **BMad Builder**, you can architect both simple agents and vastly complex domain-specific modules (legal, medical, finance, education, creative) that will soon be sharable in an **official community marketplace**. Imagine building and sharing your own specialized AI team!
|
||||
|
||||
## 📊 See It In Action
|
||||
|
||||
<p align="center">
|
||||
<img src="./docs/tutorials/getting-started/images/workflow-method-greenfield.svg" alt="BMad Method Workflow" width="100%">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<em>Complete BMad Method workflow showing all phases, agents, and decision points</em>
|
||||
</p>
|
||||
|
||||
## 🚀 Get Started in 3 Steps
|
||||
|
||||
### 1. Install BMad Method
|
||||
**Prerequisites**: [Node.js](https://nodejs.org) v20+
|
||||
|
||||
```bash
|
||||
# Install v6 RECOMMENDED
|
||||
npx bmad-method@alpha install
|
||||
```
|
||||
|
||||
Follow the installer prompts to configure your project. Then run:
|
||||
|
||||
```bash
|
||||
# Install v4 Legacy (not recommended if starting fresh)
|
||||
npx bmad-method install
|
||||
# OR
|
||||
npx bmad-method@latest install
|
||||
```
|
||||
|
||||
|
||||
### 2. Initialize Your Project
|
||||
|
||||
Load any agent in your IDE and run:
|
||||
|
||||
```
|
||||
*workflow-init
|
||||
```
|
||||
|
||||
This analyzes your project and recommends the right workflow track.
|
||||
This analyzes your project and recommends a track:
|
||||
|
||||
### 3. Choose Your Track
|
||||
| Track | Best For | Time to First Story |
|
||||
| --------------- | ------------------------- | ------------------- |
|
||||
| **Quick Flow** | Bug fixes, small features | ~5 minutes |
|
||||
| **BMad Method** | Products and platforms | ~15 minutes |
|
||||
| **Enterprise** | Compliance-heavy systems | ~30 minutes |
|
||||
|
||||
BMad Method adapts to your needs with three intelligent tracks:
|
||||
## Modules
|
||||
|
||||
| Track | Use For | Planning | Time to Start |
|
||||
| ----------------- | ------------------------- | ----------------------- | ------------- |
|
||||
| **⚡ Quick Flow** | Bug fixes, small features | Tech spec only | < 5 minutes |
|
||||
| **📋 BMad Method** | Products, platforms | PRD + Architecture + UX | < 15 minutes |
|
||||
| **🏢 Enterprise** | Compliance, scale | Full governance suite | < 30 minutes |
|
||||
| Module | Purpose |
|
||||
| ------------------------------------- | -------------------------------------------------------- |
|
||||
| **BMad Method (BMM)** | Core agile development with 34 workflows across 4 phases |
|
||||
| **BMad Builder (BMB)** | Create custom agents and domain-specific modules |
|
||||
| **Creative Intelligence Suite (CIS)** | Innovation, brainstorming, and problem-solving |
|
||||
|
||||
> **Not sure?** Run `*workflow-init` and let BMad analyze your project goal.
|
||||
## Documentation
|
||||
|
||||
## 🔄 How It Works: 4-Phase Methodology
|
||||
**[Full Documentation](http://docs.bmad-method.org)** — Tutorials, how-to guides, concepts, and reference
|
||||
|
||||
BMad Method guides you through a proven development lifecycle:
|
||||
|
||||
1. **📊 Analysis** (Optional) - Brainstorm, research, and explore solutions
|
||||
2. **📝 Planning** - Create PRDs, tech specs, or game design documents
|
||||
3. **🏗️ Solutioning** - Design architecture, UX, and technical approach
|
||||
4. **⚡ Implementation** - Story-driven development with continuous validation
|
||||
|
||||
Each phase has specialized workflows and agents working together to deliver exceptional results.
|
||||
|
||||
## 🤖 Meet Your Team
|
||||
|
||||
**12 Specialized Agents** working in concert:
|
||||
|
||||
| Development | Architecture | Product | Leadership |
|
||||
| ----------- | -------------- | ----------- | ------------ |
|
||||
| Developer | Architect | PM | Scrum Master |
|
||||
| UX Designer | Test Architect | Analyst | BMad Master |
|
||||
| | | Tech Writer | |
|
||||
|
||||
**Test Architect** integrates with `@seontechnologies/playwright-utils` for production-ready web app fixture-based utilities.
|
||||
|
||||
Each agent brings deep expertise and can be customized to match your team's style.
|
||||
|
||||
## 📦 What's Included
|
||||
|
||||
### Official Modules
|
||||
|
||||
- **BMad Method (BMM)** - Complete agile development framework
|
||||
- 12 specialized agents
|
||||
- 34 workflows across 4 phases
|
||||
- Stand Along Quick Spec Flow for a streamlined simple implementation process
|
||||
- [→ Documentation Hub](http://docs.bmad-method.org/explanation/bmm/)
|
||||
|
||||
- **BMad Builder (BMB)** - Create custom agents and workflows
|
||||
- Build anything from simple agents to complex modules
|
||||
- Create domain-specific solutions (legal, medical, finance, education)
|
||||
- [→ Builder Guide](http://docs.bmad-method.org/explanation/bmad-builder/)
|
||||
|
||||
- **Creative Intelligence Suite (CIS)** - Innovation & problem-solving
|
||||
- Brainstorming, design thinking, storytelling
|
||||
- 5 creative facilitation workflows
|
||||
- [→ Creative Workflows](http://docs.bmad-method.org/explanation/creative-intelligence/)
|
||||
|
||||
### Key Features
|
||||
|
||||
- **🎨 Customizable Agents** - Modify personalities, expertise, and communication styles
|
||||
- **🌐 Multi-Language Support** - Separate settings for communication and code output
|
||||
- **📄 Document Sharding** - 90% token savings for large projects
|
||||
- **🔄 Update-Safe** - Your customizations persist through updates
|
||||
- **🚀 Web Bundles** - Use in ChatGPT, Claude Projects, or Gemini Gems
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### Quick Links
|
||||
|
||||
- **[Quick Start Guide](http://docs.bmad-method.org/tutorials/getting-started/getting-started-bmadv6/)** - 15-minute introduction
|
||||
- **[Complete BMM Documentation](http://docs.bmad-method.org/explanation/bmm/)** - All guides and references
|
||||
- **[Agent Customization](http://docs.bmad-method.org/how-to/customization/customize-agents/)** - Personalize your agents
|
||||
- **[All Documentation](http://docs.bmad-method.org/)** - Complete documentation index
|
||||
- [Getting Started Tutorial](http://docs.bmad-method.org/tutorials/getting-started/getting-started-bmadv6/)
|
||||
- [Upgrading from Previous Versions](http://docs.bmad-method.org/how-to/installation/upgrade-to-v6/)
|
||||
|
||||
### For v4 Users
|
||||
|
||||
- **[v4 Documentation](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4/docs)**
|
||||
- **[v4 to v6 Upgrade Guide](http://docs.bmad-method.org/how-to/installation/upgrade-to-v6/)**
|
||||
|
||||
## 💬 Community & Support
|
||||
## Community
|
||||
|
||||
- **[Discord Community](https://discord.gg/gk8jAdXWmj)** - Get help, share projects
|
||||
- **[GitHub Issues](https://github.com/bmad-code-org/BMAD-METHOD/issues)** - Report bugs, request features
|
||||
- **[YouTube Channel](https://www.youtube.com/@BMadCode)** - Video tutorials and demos
|
||||
- **[Web Bundles](https://bmad-code-org.github.io/bmad-bundles/)** - Pre-built agent bundles (Currently not functioning, reworking soon)
|
||||
- **[Code of Conduct](.github/CODE_OF_CONDUCT.md)** - Community guidelines
|
||||
- [Discord](https://discord.gg/gk8jAdXWmj) — Get help, share ideas, collaborate
|
||||
- [YouTube](https://www.youtube.com/@BMadCode) — Video tutorials and updates
|
||||
- [GitHub Issues](https://github.com/bmad-code-org/BMAD-METHOD/issues) — Bug reports and feature requests
|
||||
- [Discussions](https://github.com/bmad-code-org/BMAD-METHOD/discussions) — Community conversations
|
||||
|
||||
## 🛠️ Development
|
||||
## Contributing
|
||||
|
||||
If you would like to contribute, first check the [CONTRIBUTING.md](CONTRIBUTING.md) for full development guidelines.
|
||||
We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
||||
|
||||
## What's New in v6
|
||||
## License
|
||||
|
||||
**v6 represents a complete architectural revolution from v4:**
|
||||
|
||||
### 🚀 Major Upgrades
|
||||
|
||||
- **BMad Core Framework** - Modular architecture enabling custom domain solutions
|
||||
- **Scale-Adaptive Intelligence** - Automatic adjustment from bug fixes to enterprise
|
||||
- **Visual Workflows** - Beautiful SVG diagrams showing complete methodology
|
||||
- **BMad Builder Module** - Create and share your own AI agent teams
|
||||
- **50+ Workflows** - Up from 20 in v4, covering every development scenario
|
||||
- **19 Specialized Agents** - Enhanced with customizable personalities and expertise
|
||||
- **Update-Safe Customization** - Your configs persist through all updates
|
||||
- **Web Bundles** - Use agents in ChatGPT, Claude, and Gemini
|
||||
- **Multi-Language Support** - Separate settings for communication and code
|
||||
- **Document Sharding** - 90% token savings for large projects
|
||||
|
||||
### 🔄 For v4 Users
|
||||
|
||||
- **[Comprehensive Upgrade Guide](http://docs.bmad-method.org/how-to/installation/upgrade-to-v6/)** - Step-by-step migration
|
||||
- **[v4 Documentation Archive](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4)** - Legacy reference
|
||||
- Backwards compatibility where possible
|
||||
- Smooth migration path with installer detection
|
||||
|
||||
## 📄 License
|
||||
|
||||
MIT License - See [LICENSE](LICENSE) for details.
|
||||
|
||||
**Trademarks:** BMad™ and BMAD-METHOD™ are trademarks of BMad Code, LLC.
|
||||
|
||||
Supported by: <a href="https://m.do.co/c/00f11bd932bb"><img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="24" alt="DigitalOcean" style="vertical-align: middle;"></a>
|
||||
MIT License — see [LICENSE](LICENSE) for details.
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/bmad-code-org/BMAD-METHOD/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=bmad-code-org/BMAD-METHOD" alt="Contributors">
|
||||
</a>
|
||||
</p>
|
||||
**BMad** and **BMAD-METHOD** are trademarks of BMad Code, LLC.
|
||||
|
||||
<p align="center">
|
||||
<sub>Built with ❤️ for the human-AI collaboration community</sub>
|
||||
</p>
|
||||
[](https://github.com/bmad-code-org/BMAD-METHOD/graphs/contributors)
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ template: splash
|
|||
|
||||
The page you're looking for doesn't exist or has been moved.
|
||||
|
||||
[Return to Home](/)
|
||||
[Return to Home](/docs/index.md)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Documentation Style Guide
|
||||
|
||||
Internal guidelines for maintaining consistent, high-quality documentation across the BMAD Method project. This document is not included in the Starlight sidebar — it's for contributors and maintainers, not end users.
|
||||
Internal guidelines for maintaining consistent, high-quality documentation across the BMad Method project. This document is not included in the Starlight sidebar — it's for contributors and maintainers, not end users.
|
||||
|
||||
## Quick Principles
|
||||
|
||||
|
|
@ -9,6 +9,27 @@ Internal guidelines for maintaining consistent, high-quality documentation acros
|
|||
3. **Strategic visuals** — Use admonitions, tables, and diagrams purposefully
|
||||
4. **Scannable content** — Headers, lists, and callouts help readers find what they need
|
||||
|
||||
## Validation Steps
|
||||
|
||||
Before submitting documentation changes, run these checks from the repo root:
|
||||
|
||||
1. **Fix link format** — Convert relative links (`./`, `../`) to site-relative paths (`/path/`)
|
||||
```bash
|
||||
npm run docs:fix-links # Preview changes
|
||||
npm run docs:fix-links -- --write # Apply changes
|
||||
```
|
||||
|
||||
2. **Validate links** — Check all links point to existing files
|
||||
```bash
|
||||
npm run docs:validate-links # Preview issues
|
||||
npm run docs:validate-links -- --write # Auto-fix where possible
|
||||
```
|
||||
|
||||
3. **Build the site** — Verify no build errors
|
||||
```bash
|
||||
npm run docs:build
|
||||
```
|
||||
|
||||
## Tutorial Structure
|
||||
|
||||
Every tutorial should follow this structure:
|
||||
|
|
@ -223,16 +244,33 @@ Instead, break into separate sections or use an admonition for context.
|
|||
|
||||
## FAQ Sections
|
||||
|
||||
Format as bold question followed by answer paragraph:
|
||||
Use a TOC with jump links, `###` headers for questions, and direct answers:
|
||||
|
||||
```md
|
||||
**Do I always need architecture?**
|
||||
## Questions
|
||||
|
||||
- [Do I always need architecture?](#do-i-always-need-architecture)
|
||||
- [Can I change my plan later?](#can-i-change-my-plan-later)
|
||||
|
||||
### Do I always need architecture?
|
||||
|
||||
Only for BMad Method and Enterprise tracks. Quick Flow skips to implementation.
|
||||
|
||||
**Can I change my plan later?**
|
||||
### Can I change my plan later?
|
||||
|
||||
Yes. The SM agent has a `correct-course` workflow for handling scope changes.
|
||||
|
||||
**Have a question not answered here?** Please [open an issue](...) or ask in [Discord](...) so we can add it!
|
||||
```
|
||||
|
||||
### FAQ Guidelines
|
||||
|
||||
- **TOC at top** — Jump links under `## Questions` for quick navigation
|
||||
- **`###` headers** — Questions are scannable and linkable (no `Q:` prefix)
|
||||
- **Direct answers** — No `**A:**` prefix, just the answer
|
||||
- **No "Related Documentation"** — Sidebar handles navigation; avoid repetitive links
|
||||
- **End with CTA** — "Have a question not answered here?" with issue/Discord links
|
||||
|
||||
## Folder Structure Blocks
|
||||
|
||||
Show project structure in "What You've Accomplished":
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
title: Downloads
|
||||
---
|
||||
|
||||
Download BMAD Method resources for offline use, AI training, or integration.
|
||||
Download BMad Method resources for offline use, AI training, or integration.
|
||||
|
||||
## Source Bundles
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| **[bmad-sources.zip](/downloads/bmad-sources.zip)** | Complete BMAD source files |
|
||||
| **[bmad-sources.zip](/downloads/bmad-sources.zip)** | Complete BMad source files |
|
||||
| **[bmad-prompts.zip](/downloads/bmad-prompts.zip)** | Agent and workflow prompts only |
|
||||
|
||||
## LLM-Optimized Files
|
||||
|
|
@ -54,7 +54,7 @@ npx bmad-method@alpha install
|
|||
|
||||
## API Access
|
||||
|
||||
For programmatic access to BMAD documentation:
|
||||
For programmatic access to BMad documentation:
|
||||
|
||||
```bash
|
||||
# Get documentation index
|
||||
|
|
@ -66,7 +66,7 @@ curl https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt
|
|||
|
||||
## Contributing
|
||||
|
||||
Want to improve BMAD Method? Check out:
|
||||
Want to improve BMad Method? Check out:
|
||||
|
||||
- [Contributing Guide](https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CONTRIBUTING.md)
|
||||
- [GitHub Repository](https://github.com/bmad-code-org/BMAD-METHOD)
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ title: "Quick Flow Solo Dev Agent (Barry)"
|
|||
|
||||
## Overview
|
||||
|
||||
Barry is the elite solo developer who lives and breathes the BMAD Quick Flow workflow. He takes projects from concept to deployment with ruthless efficiency - no handoffs, no delays, just pure focused development. Barry architects specs, writes the code, and ships features faster than entire teams. When you need it done right and done now, Barry's your dev.
|
||||
Barry is the elite solo developer who lives and breathes the BMad Quick Flow workflow. He takes projects from concept to deployment with ruthless efficiency - no handoffs, no delays, just pure focused development. Barry architects specs, writes the code, and ships features faster than entire teams. When you need it done right and done now, Barry's your dev.
|
||||
|
||||
### Agent Persona
|
||||
|
||||
**Name:** Barry
|
||||
**Title:** Quick Flow Solo Dev
|
||||
|
||||
**Identity:** Barry is an elite developer who thrives on autonomous execution. He lives and breathes the BMAD Quick Flow workflow, taking projects from concept to deployment with ruthless efficiency. No handoffs, no delays - just pure, focused development. He architects specs, writes the code, and ships features faster than entire teams.
|
||||
**Identity:** Barry is an elite developer who thrives on autonomous execution. He lives and breathes the BMad Quick Flow workflow, taking projects from concept to deployment with ruthless efficiency. No handoffs, no delays - just pure, focused development. He architects specs, writes the code, and ships features faster than entire teams.
|
||||
|
||||
**Communication Style:** Direct, confident, and implementation-focused. Uses tech slang and gets straight to the point. No fluff, just results. Every response moves the project forward.
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ Barry is the elite solo developer who lives and breathes the BMAD Quick Flow wor
|
|||
|
||||
## Menu Commands
|
||||
|
||||
Barry owns the entire BMAD Quick Flow path, providing a streamlined 3-step development process that eliminates handoffs and maximizes velocity.
|
||||
Barry owns the entire BMad Quick Flow path, providing a streamlined 3-step development process that eliminates handoffs and maximizes velocity.
|
||||
|
||||
### 1. **create-tech-spec**
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ Barry owns the entire BMAD Quick Flow path, providing a streamlined 3-step devel
|
|||
|
||||
---
|
||||
|
||||
## The BMAD Quick Flow Process
|
||||
## The BMad Quick Flow Process
|
||||
|
||||
Barry orchestrates a simple, efficient 3-step process:
|
||||
|
||||
|
|
@ -310,11 +310,11 @@ Implement OAuth 2.0 authentication with JWT tokens and role-based access control
|
|||
|
||||
## Related Documentation
|
||||
|
||||
- **[Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md)** - Getting started with BMM
|
||||
- **[Agents Guide](../../explanation/core-concepts/agent-roles.md)** - Complete agent reference
|
||||
- **[Four Phases](../../explanation/architecture/four-phases.md)** - Understanding development tracks
|
||||
- **[Workflow Implementation](../../how-to/workflows/run-sprint-planning.md)** - Implementation workflows
|
||||
- **[Party Mode](../../explanation/features/party-mode.md)** - Multi-agent collaboration
|
||||
- **[Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md)** - Getting started with BMM
|
||||
- **[Agents Guide](/docs/explanation/core-concepts/agent-roles.md)** - Complete agent reference
|
||||
- **[Four Phases](/docs/explanation/architecture/four-phases.md)** - Understanding development tracks
|
||||
- **[Workflow Implementation](/docs/how-to/workflows/run-sprint-planning.md)** - Implementation workflows
|
||||
- **[Party Mode](/docs/explanation/features/party-mode.md)** - Multi-agent collaboration
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: "Understanding Agents"
|
||||
description: Understanding BMAD agents and their roles
|
||||
description: Understanding BMad agents and their roles
|
||||
---
|
||||
|
||||
|
||||
Comprehensive guides to BMAD's AI agents - their roles, capabilities, and how to work with them effectively.
|
||||
Comprehensive guides to BMad's AI agents - their roles, capabilities, and how to work with them effectively.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -12,17 +12,17 @@ Comprehensive guides to BMAD's AI agents - their roles, capabilities, and how to
|
|||
|
||||
### BMM Agents
|
||||
|
||||
- **[Agent Roles](../core-concepts/agent-roles.md)** - Overview of all BMM agent roles and responsibilities
|
||||
- **[Quick Flow Solo Dev (Barry)](./barry-quick-flow.md)** - The dedicated agent for rapid development
|
||||
- **[Agent Roles](/docs/explanation/core-concepts/agent-roles.md)** - Overview of all BMM agent roles and responsibilities
|
||||
- **[Quick Flow Solo Dev (Barry)](/docs/explanation/agents/barry-quick-flow.md)** - The dedicated agent for rapid development
|
||||
|
||||
### BMGD Agents
|
||||
|
||||
- **[Game Development Agents](../game-dev/agents.md)** - Complete guide to BMGD's specialized game dev agents
|
||||
- **[Game Development Agents](/docs/explanation/game-dev/agents.md)** - Complete guide to BMGD's specialized game dev agents
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- **[What Are Agents?](../core-concepts/what-are-agents.md)** - Core concept explanation
|
||||
- **[Party Mode](../features/party-mode.md)** - Multi-agent collaboration
|
||||
- **[Customize Agents](../../how-to/customization/customize-agents.md)** - How to customize agent behavior
|
||||
- **[What Are Agents?](/docs/explanation/core-concepts/what-are-agents.md)** - Core concept explanation
|
||||
- **[Party Mode](/docs/explanation/features/party-mode.md)** - Multi-agent collaboration
|
||||
- **[Customize Agents](/docs/how-to/customization/customize-agents.md)** - How to customize agent behavior
|
||||
|
|
|
|||
|
|
@ -121,6 +121,6 @@ Same as BMad Method with optional extended workflows.
|
|||
|
||||
## Related
|
||||
|
||||
- [Why Solutioning Matters](./why-solutioning-matters.md)
|
||||
- [Preventing Agent Conflicts](./preventing-agent-conflicts.md)
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md)
|
||||
- [Why Solutioning Matters](/docs/explanation/architecture/why-solutioning-matters.md)
|
||||
- [Preventing Agent Conflicts](/docs/explanation/architecture/preventing-agent-conflicts.md)
|
||||
- [Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md)
|
||||
|
|
|
|||
|
|
@ -133,6 +133,6 @@ Document written once, never updated
|
|||
|
||||
## Related
|
||||
|
||||
- [Why Solutioning Matters](./why-solutioning-matters.md)
|
||||
- [Four Phases](./four-phases.md)
|
||||
- [Create Architecture](../../how-to/workflows/create-architecture.md)
|
||||
- [Why Solutioning Matters](/docs/explanation/architecture/why-solutioning-matters.md)
|
||||
- [Four Phases](/docs/explanation/architecture/four-phases.md)
|
||||
- [Create Architecture](/docs/how-to/workflows/create-architecture.md)
|
||||
|
|
|
|||
|
|
@ -86,6 +86,6 @@ Catching alignment issues in solutioning is 10× faster than discovering them du
|
|||
|
||||
## Related
|
||||
|
||||
- [Four Phases](./four-phases.md) - Overview of all phases
|
||||
- [Preventing Agent Conflicts](./preventing-agent-conflicts.md) - Detailed conflict prevention
|
||||
- [Create Architecture](../../how-to/workflows/create-architecture.md) - How to do it
|
||||
- [Four Phases](/docs/explanation/architecture/four-phases.md) - Overview of all phases
|
||||
- [Preventing Agent Conflicts](/docs/explanation/architecture/preventing-agent-conflicts.md) - Detailed conflict prevention
|
||||
- [Create Architecture](/docs/how-to/workflows/create-architecture.md) - How to do it
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ title: "Custom Content"
|
|||
---
|
||||
|
||||
|
||||
BMAD supports several categories of officially supported custom content that extend the platform's capabilities. Custom content can be created manually or with the recommended assistance of the BMad Builder (BoMB) Module. The BoMB Agents provides workflows and expertise to plan and build any custom content you can imagine.
|
||||
BMad supports several categories of officially supported custom content that extend the platform's capabilities. Custom content can be created manually or with the recommended assistance of the BMad Builder (BoMB) Module. The BoMB Agents provides workflows and expertise to plan and build any custom content you can imagine.
|
||||
|
||||
This flexibility transforms the platform beyond its current capabilities, enabling:
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ This flexibility transforms the platform beyond its current capabilities, enabli
|
|||
|
||||
Custom modules range from simple collections of related agents, workflows, and tools designed to work independently, to complex, expansive systems like the BMad Method or even larger applications.
|
||||
|
||||
Custom modules are [installable](../../how-to/installation/install-custom-modules.md) using the standard BMAD method and support advanced features:
|
||||
Custom modules are [installable](/docs/how-to/installation/install-custom-modules.md) using the standard BMad method and support advanced features:
|
||||
|
||||
- Optional user information collection during installation/updates
|
||||
- Versioning and upgrade paths
|
||||
|
|
@ -52,13 +52,13 @@ Add-on modules can include:
|
|||
|
||||
## Custom Global Modules
|
||||
|
||||
Similar to Custom Stand-Alone Modules, but designed to add functionality that applies across all installed content. These modules provide cross-cutting capabilities that enhance the entire BMAD ecosystem.
|
||||
Similar to Custom Stand-Alone Modules, but designed to add functionality that applies across all installed content. These modules provide cross-cutting capabilities that enhance the entire BMad ecosystem.
|
||||
|
||||
Examples include:
|
||||
|
||||
- The current TTS (Text-to-Speech) functionality for Claude, which will soon be converted to a global module
|
||||
- The core module, which is always installed and provides all agents with party mode and advanced elicitation capabilities
|
||||
- Installation and update tools that work with any BMAD method configuration
|
||||
- Installation and update tools that work with any BMad method configuration
|
||||
|
||||
Upcoming standards will document best practices for building global content that affects installed modules through:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
---
|
||||
title: "BMad Builder (BMB)"
|
||||
description: Create custom agents, workflows, and modules for BMAD
|
||||
description: Create custom agents, workflows, and modules for BMad
|
||||
---
|
||||
|
||||
|
||||
Create custom agents, workflows, and modules for BMAD.
|
||||
Create custom agents, workflows, and modules for BMad.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
- **[Agent Creation Guide](../../tutorials/advanced/create-custom-agent.md)** - Step-by-step guide to building your first agent
|
||||
- **[Agent Creation Guide](/docs/tutorials/advanced/create-custom-agent.md)** - Step-by-step guide to building your first agent
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -56,11 +56,11 @@ Production-ready examples available in the BMB reference folder:
|
|||
## Installation Guide
|
||||
|
||||
For installing standalone simple and expert agents, see:
|
||||
- [Install Custom Modules](../../how-to/installation/install-custom-modules.md)
|
||||
- [Install Custom Modules](/docs/how-to/installation/install-custom-modules.md)
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [Custom Content Types](./custom-content-types.md) - Understanding content types
|
||||
- [Create Custom Agent](../../tutorials/advanced/create-custom-agent.md) - Tutorial
|
||||
- [Custom Content Types](/docs/explanation/bmad-builder/custom-content-types.md) - Understanding content types
|
||||
- [Create Custom Agent](/docs/tutorials/advanced/create-custom-agent.md) - Tutorial
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Complete guides for the BMad Method Module (BMM) - AI-powered agile development
|
|||
|
||||
**New to BMM?** Start here:
|
||||
|
||||
- **[Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md)** - Step-by-step guide to building your first project
|
||||
- **[Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md)** - Step-by-step guide to building your first project
|
||||
- Installation and setup
|
||||
- Understanding the four phases
|
||||
- Running your first workflows
|
||||
|
|
@ -36,26 +36,26 @@ First know there is the full BMad Method Process and then there is a Quick Flow
|
|||
- All 4 phases have optional steps in them, depending on how rigorous you want to go with planning, research ideation, validation, testing and traceability.
|
||||
- While there is a lot here, know that even this can be distilled down to a simple PRD, Epic and Story list and then jump into the dev cycle. But if that is all you want, you might be better off with the BMad Quick Flow described next
|
||||
|
||||
- **[BMAD Quick Flow](../../explanation/features/quick-flow.md)** - Fast-track development workflow
|
||||
- **[BMad Quick Flow](/docs/explanation/features/quick-flow.md)** - Fast-track development workflow
|
||||
- 3-step process: spec → dev → optional review
|
||||
- Perfect for bug fixes and small features
|
||||
- Rapid prototyping with production quality
|
||||
- Implementation in minutes, not days
|
||||
- Has a specialized single agent that does all of this: **[Quick Flow Solo Dev Agent](../agents/barry-quick-flow.md)**
|
||||
- Has a specialized single agent that does all of this: **[Quick Flow Solo Dev Agent](/docs/explanation/agents/barry-quick-flow.md)**
|
||||
|
||||
- **TEA engagement (optional)** - Choose TEA engagement: none, TEA-only (standalone), or integrated by track. See **[Test Architect Guide](../../explanation/features/tea-overview.md)**.
|
||||
- **TEA engagement (optional)** - Choose TEA engagement: none, TEA-only (standalone), or integrated by track. See **[Test Architect Guide](/docs/explanation/features/tea-overview.md)**.
|
||||
|
||||
## 🤖 Agents and Collaboration
|
||||
|
||||
Complete guide to BMM's AI agent team:
|
||||
|
||||
- **[Agents Guide](../../explanation/core-concepts/agent-roles.md)** - Comprehensive agent reference
|
||||
- **[Agents Guide](/docs/explanation/core-concepts/agent-roles.md)** - Comprehensive agent reference
|
||||
- 12 specialized BMM agents + BMad Master
|
||||
- Agent roles, workflows, and when to use them
|
||||
- Agent customization system
|
||||
- Best practices and common patterns
|
||||
|
||||
- **[Party Mode Guide](../../explanation/features/party-mode.md)** - Multi-agent collaboration
|
||||
- **[Party Mode Guide](/docs/explanation/features/party-mode.md)** - Multi-agent collaboration
|
||||
- How party mode works (19+ agents collaborate in real-time)
|
||||
- When to use it (strategic, creative, cross-functional, complex)
|
||||
- Example party compositions
|
||||
|
|
@ -67,7 +67,7 @@ Complete guide to BMM's AI agent team:
|
|||
|
||||
Comprehensive guide for brownfield development:
|
||||
|
||||
- **[Brownfield Development Guide](../../how-to/brownfield/index.md)** - Complete guide for existing codebases
|
||||
- **[Brownfield Development Guide](/docs/how-to/brownfield/index.md)** - Complete guide for existing codebases
|
||||
- Documentation phase strategies
|
||||
- Track selection for brownfield
|
||||
- Integration with existing patterns
|
||||
|
|
@ -78,49 +78,49 @@ Comprehensive guide for brownfield development:
|
|||
|
||||
Essential reference materials:
|
||||
|
||||
- **[Glossary](../../reference/glossary/index.md)** - Key terminology and concepts
|
||||
- **[FAQ](../faq/index.md)** - Frequently asked questions across all topics
|
||||
- **[Glossary](/docs/reference/glossary/index.md)** - Key terminology and concepts
|
||||
- **[FAQ](/docs/explanation/faq/index.md)** - Frequently asked questions across all topics
|
||||
|
||||
## 🎯 Choose Your Path
|
||||
|
||||
### I need to...
|
||||
|
||||
**Build something new (greenfield)**
|
||||
→ Start with [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md)
|
||||
→ Start with [Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md)
|
||||
|
||||
**Fix a bug or add small feature**
|
||||
→ Use the [Quick Flow Solo Dev](../agents/barry-quick-flow.md) directly with its dedicated stand alone [Quick Bmad Spec Flow](../features/quick-flow.md) process
|
||||
→ Use the [Quick Flow Solo Dev](/docs/explanation/agents/barry-quick-flow.md) directly with its dedicated stand alone [Quick Bmad Spec Flow](/docs/explanation/features/quick-flow.md) process
|
||||
|
||||
**Work with existing codebase (brownfield)**
|
||||
→ Read [Brownfield Development Guide](../../how-to/brownfield/index.md)
|
||||
→ Read [Brownfield Development Guide](/docs/how-to/brownfield/index.md)
|
||||
→ Pay special attention to documentation requirements for brownfield projects
|
||||
|
||||
## 📋 Workflow Guides
|
||||
|
||||
Comprehensive documentation for all BMM workflows organized by phase:
|
||||
|
||||
- **[Phase 1: Analysis Workflows](../../how-to/workflows/run-brainstorming-session.md)** - Optional exploration and research workflows (595 lines)
|
||||
- **[Phase 1: Analysis Workflows](/docs/how-to/workflows/run-brainstorming-session.md)** - Optional exploration and research workflows (595 lines)
|
||||
- brainstorm-project, product-brief, research, and more
|
||||
- When to use analysis workflows
|
||||
- Creative and strategic tools
|
||||
|
||||
- **[Phase 2: Planning Workflows](../../how-to/workflows/create-prd.md)** - Scale-adaptive planning (967 lines)
|
||||
- **[Phase 2: Planning Workflows](/docs/how-to/workflows/create-prd.md)** - Scale-adaptive planning (967 lines)
|
||||
- prd, tech-spec, gdd, narrative, ux
|
||||
- Track-based planning approach (Quick Flow, BMad Method, Enterprise Method)
|
||||
- Which planning workflow to use
|
||||
|
||||
- **[Phase 3: Solutioning Workflows](../../how-to/workflows/create-architecture.md)** - Architecture and validation (638 lines)
|
||||
- **[Phase 3: Solutioning Workflows](/docs/how-to/workflows/create-architecture.md)** - Architecture and validation (638 lines)
|
||||
- architecture, create-epics-and-stories, implementation-readiness
|
||||
- V6: Epics created AFTER architecture for better quality
|
||||
- Required for BMad Method and Enterprise Method tracks
|
||||
- Preventing agent conflicts
|
||||
|
||||
- **[Phase 4: Implementation Workflows](../../how-to/workflows/run-sprint-planning.md)** - Sprint-based development (1,634 lines)
|
||||
- **[Phase 4: Implementation Workflows](/docs/how-to/workflows/run-sprint-planning.md)** - Sprint-based development (1,634 lines)
|
||||
- sprint-planning, create-story, dev-story, code-review
|
||||
- Complete story lifecycle
|
||||
- One-story-at-a-time discipline
|
||||
|
||||
- **[Testing & QA Workflows](../../explanation/features/tea-overview.md)** - Comprehensive quality assurance (1,420 lines)
|
||||
- **[Testing & QA Workflows](/docs/explanation/features/tea-overview.md)** - Comprehensive quality assurance (1,420 lines)
|
||||
- Test strategy, automation, quality gates
|
||||
- TEA agent and test healing
|
||||
|
||||
|
|
@ -132,4 +132,4 @@ Comprehensive documentation for all BMM workflows organized by phase:
|
|||
- **[GitHub Issues](https://github.com/bmad-code-org/BMAD-METHOD/issues)** - Report bugs or request features
|
||||
- **[YouTube Channel](https://www.youtube.com/@BMadCode)** - Video tutorials and walkthroughs
|
||||
|
||||
**Ready to begin?** → [Start with the Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md)
|
||||
**Ready to begin?** → [Start with the Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md)
|
||||
|
|
|
|||
|
|
@ -199,6 +199,6 @@ Fast solo development without handoffs.
|
|||
|
||||
## Related
|
||||
|
||||
- [What Are Agents](./what-are-agents.md) - Foundational concepts
|
||||
- [Agent Reference](../../reference/agents/index.md) - Complete command reference
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md)
|
||||
- [What Are Agents](/docs/explanation/core-concepts/what-are-agents.md) - Foundational concepts
|
||||
- [Agent Reference](/docs/reference/agents/index.md) - Complete command reference
|
||||
- [Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md)
|
||||
|
|
|
|||
|
|
@ -1,40 +1,40 @@
|
|||
---
|
||||
title: "BMAD Core Concepts"
|
||||
title: "BMad Core Concepts"
|
||||
---
|
||||
|
||||
|
||||
Understanding the fundamental building blocks of the BMAD Method.
|
||||
Understanding the fundamental building blocks of the BMad Method.
|
||||
|
||||
## The Essentials
|
||||
|
||||
| Concept | Description | Guide |
|
||||
|---------|-------------|-------|
|
||||
| **Agents** | AI assistants with personas, capabilities, and menus | [Agents Guide](./what-are-agents.md) |
|
||||
| **Workflows** | Structured processes for achieving specific outcomes | [Workflows Guide](./what-are-workflows.md) |
|
||||
| **Modules** | Packaged collections of agents and workflows | [Modules Guide](./what-are-modules.md) |
|
||||
| **Agents** | AI assistants with personas, capabilities, and menus | [Agents Guide](/docs/explanation/core-concepts/what-are-agents.md) |
|
||||
| **Workflows** | Structured processes for achieving specific outcomes | [Workflows Guide](/docs/explanation/core-concepts/what-are-workflows.md) |
|
||||
| **Modules** | Packaged collections of agents and workflows | [Modules Guide](/docs/explanation/core-concepts/what-are-modules.md) |
|
||||
|
||||
## Getting Started
|
||||
|
||||
### New to BMAD?
|
||||
Start here to understand what BMAD is and how it works:
|
||||
### New to BMad?
|
||||
Start here to understand what BMad is and how it works:
|
||||
|
||||
1. **[Agents Guide](./what-are-agents.md)** - Learn about Simple and Expert agents
|
||||
2. **[Workflows Guide](./what-are-workflows.md)** - Understand how workflows orchestrate tasks
|
||||
3. **[Modules Guide](./what-are-modules.md)** - See how modules organize functionality
|
||||
1. **[Agents Guide](/docs/explanation/core-concepts/what-are-agents.md)** - Learn about Simple and Expert agents
|
||||
2. **[Workflows Guide](/docs/explanation/core-concepts/what-are-workflows.md)** - Understand how workflows orchestrate tasks
|
||||
3. **[Modules Guide](/docs/explanation/core-concepts/what-are-modules.md)** - See how modules organize functionality
|
||||
|
||||
### Installing BMAD
|
||||
### Installing BMad
|
||||
|
||||
- **[Installation Guide](../../how-to/installation/index.md)** - Set up BMAD in your project
|
||||
- **[Upgrading from v4](../../how-to/installation/upgrade-to-v6.md)** - Migrate from earlier versions
|
||||
- **[Installation Guide](/docs/how-to/installation/index.md)** - Set up BMad in your project
|
||||
- **[Upgrading from v4](/docs/how-to/installation/upgrade-to-v6.md)** - Migrate from earlier versions
|
||||
|
||||
### Configuration
|
||||
|
||||
- **[BMAD Customization](../../how-to/customization/index.md)** - Personalize agents and workflows
|
||||
- **[BMad Customization](/docs/how-to/customization/index.md)** - Personalize agents and workflows
|
||||
|
||||
### Advanced
|
||||
|
||||
- **[Web Bundles](../features/web-bundles.md)** - Use BMAD in Gemini Gems and Custom GPTs
|
||||
- **[Web Bundles](/docs/explanation/features/web-bundles.md)** - Use BMad in Gemini Gems and Custom GPTs
|
||||
|
||||
---
|
||||
|
||||
**Next:** Read the [Agents Guide](./what-are-agents.md) to understand the core building block of BMAD.
|
||||
**Next:** Read the [Agents Guide](/docs/explanation/core-concepts/what-are-agents.md) to understand the core building block of BMad.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Agents are AI assistants that help you accomplish tasks. Each agent has a unique
|
|||
|
||||
## Agent Types
|
||||
|
||||
BMAD has two primary agent types, designed for different use cases:
|
||||
BMad has two primary agent types, designed for different use cases:
|
||||
|
||||
### Simple Agents
|
||||
|
||||
|
|
@ -85,12 +85,12 @@ All agents share these building blocks:
|
|||
|
||||
## Creating Custom Agents
|
||||
|
||||
BMAD provides the **BMAD Builder (BMB)** module for creating your own agents. See the [Agent Creation Guide](../../tutorials/advanced/create-custom-agent.md) for step-by-step instructions.
|
||||
BMad provides the **BMad Builder (BMB)** module for creating your own agents. See the [Agent Creation Guide](/docs/tutorials/advanced/create-custom-agent.md) for step-by-step instructions.
|
||||
|
||||
## Customizing Existing Agents
|
||||
|
||||
You can modify any agent's behavior without editing core files. See [BMAD Customization](../../how-to/customization/index.md) for details. It is critical to never modify an installed agents .md file directly and follow the customization process, this way future updates to the agent or module its part of will continue to be updated and recompiled with the installer tool, and your customizations will still be retained.
|
||||
You can modify any agent's behavior without editing core files. See [BMad Customization](/docs/how-to/customization/index.md) for details. It is critical to never modify an installed agents .md file directly and follow the customization process, this way future updates to the agent or module its part of will continue to be updated and recompiled with the installer tool, and your customizations will still be retained.
|
||||
|
||||
---
|
||||
|
||||
**Next:** Learn about [Workflows](./what-are-workflows.md) to see how agents accomplish complex tasks.
|
||||
**Next:** Learn about [Workflows](/docs/explanation/core-concepts/what-are-workflows.md) to see how agents accomplish complex tasks.
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ Always installed, provides shared functionality:
|
|||
- Core workflows (Party Mode, Advanced Elicitation, Brainstorming)
|
||||
- Common tasks (document indexing, sharding, review)
|
||||
|
||||
### BMAD Method (BMM)
|
||||
### BMad Method (BMM)
|
||||
Software and game development:
|
||||
- Project planning workflows
|
||||
- Implementation agents (Dev, PM, QA, Scrum Master)
|
||||
- Testing and architecture guidance
|
||||
|
||||
### BMAD Builder (BMB)
|
||||
### BMad Builder (BMB)
|
||||
Create custom solutions:
|
||||
- Agent creation workflows
|
||||
- Workflow authoring tools
|
||||
|
|
@ -40,7 +40,7 @@ Innovation and creativity:
|
|||
- Innovation strategy workflows
|
||||
- Storytelling and ideation
|
||||
|
||||
### BMAD Game Dev (BMGD)
|
||||
### BMad Game Dev (BMGD)
|
||||
Game development specialization:
|
||||
- Game design workflows
|
||||
- Narrative development
|
||||
|
|
@ -53,8 +53,8 @@ Installed modules follow this structure:
|
|||
```
|
||||
_bmad/
|
||||
├── core/ # Always present
|
||||
├── bmm/ # BMAD Method (if installed)
|
||||
├── bmb/ # BMAD Builder (if installed)
|
||||
├── bmm/ # BMad Method (if installed)
|
||||
├── bmb/ # BMad Builder (if installed)
|
||||
├── cis/ # Creative Intelligence (if installed)
|
||||
└── bmgd/ # Game Dev (if installed)
|
||||
```
|
||||
|
|
@ -70,10 +70,10 @@ Custom modules are installed the same way as official modules.
|
|||
|
||||
## Installing Modules
|
||||
|
||||
During BMAD installation, you choose which modules to install. You can also add or remove modules later by re-running the installer.
|
||||
During BMad installation, you choose which modules to install. You can also add or remove modules later by re-running the installer.
|
||||
|
||||
See [Installation Guide](../../how-to/installation/index.md) for details.
|
||||
See [Installation Guide](/docs/how-to/installation/index.md) for details.
|
||||
|
||||
---
|
||||
|
||||
**Next:** Read the [Installation Guide](../../how-to/installation/index.md) to set up BMAD with the modules you need.
|
||||
**Next:** Read the [Installation Guide](/docs/how-to/installation/index.md) to set up BMad with the modules you need.
|
||||
|
|
|
|||
|
|
@ -138,15 +138,15 @@ Each workflow checks for required inputs from prior workflows, validates they're
|
|||
|
||||
### The Tri-Modal Pattern
|
||||
|
||||
For critical workflows that produce important artifacts, BMAD uses a tri-modal structure: Create, Validate, and Edit. Each mode is a separate workflow path that can run independently or flow into the others.
|
||||
For critical workflows that produce important artifacts, BMad uses a tri-modal structure: Create, Validate, and Edit. Each mode is a separate workflow path that can run independently or flow into the others.
|
||||
|
||||
**Create mode** builds new artifacts from scratch. But here's where it gets interesting: create mode can also function as a conversion tool. Feed it a non-compliant document—something that doesn't follow BMAD standards—and it will extract the essential content and rebuild it as a compliant artifact. This means you can bring in existing work and automatically upgrade it to follow proper patterns.
|
||||
**Create mode** builds new artifacts from scratch. But here's where it gets interesting: create mode can also function as a conversion tool. Feed it a non-compliant document—something that doesn't follow BMad standards—and it will extract the essential content and rebuild it as a compliant artifact. This means you can bring in existing work and automatically upgrade it to follow proper patterns.
|
||||
|
||||
**Validate mode** runs standalone and checks artifacts against standards. Because it's separate, you can run validation whenever you want—immediately after creation, weeks later when things have changed, or even using a different LLM entirely. It's like having a quality assurance checkpoint that's always available but never forced.
|
||||
|
||||
**Edit mode** modifies existing artifacts while enforcing standards. As you update documents to reflect changing requirements or new understanding, edit mode ensures you don't accidentally drift away from the patterns that make the artifacts useful. It checks compliance as you work and can route back to create mode if it detects something that needs full conversion.
|
||||
|
||||
All BMAD planning workflows and the BMB module (will) use this tri-modal pattern. The pristine example is the workflow workflow in BMB—it creates workflow specifications, validates them against standards, and lets you edit them while maintaining compliance. You can study that workflow to see the pattern in action.
|
||||
All BMad planning workflows and the BMB module (will) use this tri-modal pattern. The pristine example is the workflow workflow in BMB—it creates workflow specifications, validates them against standards, and lets you edit them while maintaining compliance. You can study that workflow to see the pattern in action.
|
||||
|
||||
This tri-modal approach gives you the best of both worlds: the creativity and flexibility to build what you need, the quality assurance of validation that can run anytime, and the ability to iterate while staying true to standards that make the artifacts valuable across sessions and team members.
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ Before building a workflow, answer these questions:
|
|||
|
||||
## Learning from Examples
|
||||
|
||||
The best way to understand workflows is to study real examples. Look at the official BMAD modules:
|
||||
The best way to understand workflows is to study real examples. Look at the official BMad modules:
|
||||
|
||||
- **BMB (Module Builder)**: Workflow and agent creation workflows
|
||||
- **BMM (Business Method Module)**: Complete software development pipeline from brainstorming through sprint planning
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@ title: "Core Module"
|
|||
---
|
||||
|
||||
|
||||
The Core Module is installed with all installations of BMAD modules and provides common functionality that any module, workflow, or agent can take advantage of.
|
||||
The Core Module is installed with all installations of BMad modules and provides common functionality that any module, workflow, or agent can take advantage of.
|
||||
|
||||
## Core Module Components
|
||||
|
||||
- **[Global Core Config](../../reference/configuration/global-config.md)** — Inheritable configuration that impacts all modules and custom content
|
||||
- **[Core Workflows](../../reference/workflows/core-workflows.md)** — Domain-agnostic workflows usable by any module
|
||||
- [Party Mode](../../explanation/features/party-mode.md) — Multi-agent conversation orchestration
|
||||
- [Brainstorming](../../explanation/features/brainstorming-techniques.md) — Structured creative sessions with 60+ techniques
|
||||
- [Advanced Elicitation](../../explanation/features/advanced-elicitation.md) — LLM rethinking with 50+ reasoning methods
|
||||
- **[Core Tasks](../../reference/configuration/core-tasks.md)** — Common tasks available across modules
|
||||
- [Index Docs](../../reference/configuration/core-tasks.md#index-docs) — Generate directory index files
|
||||
- [Adversarial Review](../../reference/configuration/core-tasks.md#adversarial-review-general) — Critical content review
|
||||
- [Shard Document](../../reference/configuration/core-tasks.md#shard-document) — Split large documents into sections
|
||||
- **[Global Core Config](/docs/reference/configuration/global-config.md)** — Inheritable configuration that impacts all modules and custom content
|
||||
- **[Core Workflows](/docs/reference/workflows/core-workflows.md)** — Domain-agnostic workflows usable by any module
|
||||
- [Party Mode](/docs/explanation/features/party-mode.md) — Multi-agent conversation orchestration
|
||||
- [Brainstorming](/docs/explanation/features/brainstorming-techniques.md) — Structured creative sessions with 60+ techniques
|
||||
- [Advanced Elicitation](/docs/explanation/features/advanced-elicitation.md) — LLM rethinking with 50+ reasoning methods
|
||||
- **[Core Tasks](/docs/reference/configuration/core-tasks.md)** — Common tasks available across modules
|
||||
- [Index Docs](/docs/reference/configuration/core-tasks.md#index-docs) — Generate directory index files
|
||||
- [Adversarial Review](/docs/reference/configuration/core-tasks.md#adversarial-review-general) — Critical content review
|
||||
- [Shard Document](/docs/reference/configuration/core-tasks.md#shard-document) — Split large documents into sections
|
||||
|
|
|
|||
|
|
@ -117,5 +117,5 @@ CIS workflows integrate with:
|
|||
|
||||
## Related
|
||||
|
||||
- [Facilitation Over Generation](../philosophy/facilitation-over-generation.md) - Core philosophy
|
||||
- [Brainstorming Techniques](../features/brainstorming-techniques.md) - Technique reference
|
||||
- [Facilitation Over Generation](/docs/explanation/philosophy/facilitation-over-generation.md) - Core philosophy
|
||||
- [Brainstorming Techniques](/docs/explanation/features/brainstorming-techniques.md) - Technique reference
|
||||
|
|
|
|||
|
|
@ -2,22 +2,25 @@
|
|||
title: "Brownfield Development FAQ"
|
||||
description: Common questions about brownfield development in the BMad Method
|
||||
---
|
||||
Quick answers to common questions about brownfield (existing codebase) development in the BMad Method (BMM).
|
||||
|
||||
## Questions
|
||||
|
||||
Quick answers to common questions about brownfield (existing codebase) development in the BMad Method.
|
||||
- [What is brownfield vs greenfield?](#what-is-brownfield-vs-greenfield)
|
||||
- [Do I have to run document-project for brownfield?](#do-i-have-to-run-document-project-for-brownfield)
|
||||
- [What if I forget to run document-project?](#what-if-i-forget-to-run-document-project)
|
||||
- [Can I use Quick Spec Flow for brownfield projects?](#can-i-use-quick-spec-flow-for-brownfield-projects)
|
||||
- [How does workflow-init handle old planning docs?](#how-does-workflow-init-handle-old-planning-docs)
|
||||
- [What if my existing code doesn't follow best practices?](#what-if-my-existing-code-doesnt-follow-best-practices)
|
||||
|
||||
---
|
||||
### What is brownfield vs greenfield?
|
||||
|
||||
## Q: What is brownfield vs greenfield?
|
||||
- **Greenfield** — New project, starting from scratch, clean slate
|
||||
- **Brownfield** — Existing project, working with established codebase and patterns
|
||||
|
||||
**A:**
|
||||
### Do I have to run document-project for brownfield?
|
||||
|
||||
- **Greenfield:** New project, starting from scratch, clean slate
|
||||
- **Brownfield:** Existing project, working with established codebase and patterns
|
||||
|
||||
## Q: Do I have to run document-project for brownfield?
|
||||
|
||||
**A:** Highly recommended, especially if:
|
||||
Highly recommended, especially if:
|
||||
|
||||
- No existing documentation
|
||||
- Documentation is outdated
|
||||
|
|
@ -26,9 +29,9 @@ Quick answers to common questions about brownfield (existing codebase) developme
|
|||
|
||||
You can skip it if you have comprehensive, up-to-date documentation including `docs/index.md`.
|
||||
|
||||
## Q: What if I forget to run document-project on brownfield?
|
||||
### What if I forget to run document-project?
|
||||
|
||||
**A:** Workflows will lack context about existing code. You may get:
|
||||
Workflows will lack context about existing code. You may get:
|
||||
|
||||
- Suggestions that don't match existing patterns
|
||||
- Integration approaches that miss existing APIs
|
||||
|
|
@ -36,9 +39,9 @@ You can skip it if you have comprehensive, up-to-date documentation including `d
|
|||
|
||||
Run document-project and restart planning with proper context.
|
||||
|
||||
## Q: Can I use Quick Spec Flow for brownfield projects?
|
||||
### Can I use Quick Spec Flow for brownfield projects?
|
||||
|
||||
**A:** Yes! Quick Spec Flow works great for brownfield. It will:
|
||||
Yes! Quick Spec Flow works great for brownfield. It will:
|
||||
|
||||
- Auto-detect your existing stack
|
||||
- Analyze brownfield code patterns
|
||||
|
|
@ -47,34 +50,24 @@ Run document-project and restart planning with proper context.
|
|||
|
||||
Perfect for bug fixes and small features in existing codebases.
|
||||
|
||||
## Q: How does workflow-init handle brownfield with old planning docs?
|
||||
### How does workflow-init handle old planning docs?
|
||||
|
||||
**A:** workflow-init asks about YOUR current work first, then uses old artifacts as context:
|
||||
workflow-init asks about YOUR current work first, then uses old artifacts as context:
|
||||
|
||||
1. Shows what it found (old PRD, epics, etc.)
|
||||
2. Asks: "Is this work in progress, previous effort, or proposed work?"
|
||||
3. If previous effort: Asks you to describe your NEW work
|
||||
4. Determines level based on YOUR work, not old artifacts
|
||||
|
||||
This prevents old Level 3 PRDs from forcing Level 3 workflow for new Level 0 bug fix.
|
||||
This prevents old Level 3 PRDs from forcing Level 3 workflow for a new Level 0 bug fix.
|
||||
|
||||
## Q: What if my existing code doesn't follow best practices?
|
||||
### What if my existing code doesn't follow best practices?
|
||||
|
||||
**A:** Quick Spec Flow detects your conventions and asks: "Should I follow these existing conventions?" You decide:
|
||||
Quick Spec Flow detects your conventions and asks: "Should I follow these existing conventions?" You decide:
|
||||
|
||||
- **Yes** → Maintain consistency with current codebase
|
||||
- **No** → Establish new standards (document why in tech-spec)
|
||||
|
||||
BMM respects your choice - it won't force modernization, but it will offer it.
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Get started with BMM
|
||||
- [Brownfield Guide](../../how-to/brownfield/index.md) - Existing codebase workflows
|
||||
- [Glossary](../../reference/glossary/index.md) - Terminology reference
|
||||
|
||||
---
|
||||
BMM respects your choice — it won't force modernization, but it will offer it.
|
||||
|
||||
**Have a question not answered here?** Please [open an issue](https://github.com/bmad-code-org/BMAD-METHOD/issues) or ask in [Discord](https://discord.gg/gk8jAdXWmj) so we can add it!
|
||||
|
|
|
|||
|
|
@ -3,24 +3,29 @@ title: "Getting Started FAQ"
|
|||
description: Common questions about getting started with the BMad Method
|
||||
---
|
||||
|
||||
|
||||
Quick answers to common questions about getting started with the BMad Method.
|
||||
|
||||
---
|
||||
## Questions
|
||||
|
||||
## Q: Do I always need to run workflow-init?
|
||||
- [Do I always need to run workflow-init?](#do-i-always-need-to-run-workflow-init)
|
||||
- [Why do I need fresh chats for each workflow?](#why-do-i-need-fresh-chats-for-each-workflow)
|
||||
- [Can I skip workflow-status and just start working?](#can-i-skip-workflow-status-and-just-start-working)
|
||||
- [What's the minimum I need to get started?](#whats-the-minimum-i-need-to-get-started)
|
||||
- [How do I know if I'm in Phase 1, 2, 3, or 4?](#how-do-i-know-if-im-in-phase-1-2-3-or-4)
|
||||
|
||||
**A:** No, once you learn the flow you can go directly to workflows. However, workflow-init is helpful because it:
|
||||
### Do I always need to run workflow-init?
|
||||
|
||||
No, once you learn the flow you can go directly to workflows. However, workflow-init is helpful because it:
|
||||
|
||||
- Determines your project's appropriate level automatically
|
||||
- Creates the tracking status file
|
||||
- Routes you to the correct starting workflow
|
||||
|
||||
For experienced users: use the [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) to go directly to the right agent/workflow.
|
||||
For experienced users: use the [Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md) to go directly to the right agent/workflow.
|
||||
|
||||
## Q: Why do I need fresh chats for each workflow?
|
||||
### Why do I need fresh chats for each workflow?
|
||||
|
||||
**A:** Context-intensive workflows (like brainstorming, PRD creation, architecture design) can cause AI hallucinations if run in sequence within the same chat. Starting fresh ensures the agent has maximum context capacity for each workflow. This is particularly important for:
|
||||
Context-intensive workflows (like brainstorming, PRD creation, architecture design) can cause AI hallucinations if run in sequence within the same chat. Starting fresh ensures the agent has maximum context capacity for each workflow. This is particularly important for:
|
||||
|
||||
- Planning workflows (PRD, architecture)
|
||||
- Analysis workflows (brainstorming, research)
|
||||
|
|
@ -28,39 +33,30 @@ For experienced users: use the [Quick Start Guide](../../tutorials/getting-start
|
|||
|
||||
Quick workflows like status checks can reuse chats safely.
|
||||
|
||||
## Q: Can I skip workflow-status and just start working?
|
||||
### Can I skip workflow-status and just start working?
|
||||
|
||||
**A:** Yes, if you already know your project level and which workflow comes next. workflow-status is mainly useful for:
|
||||
Yes, if you already know your project level and which workflow comes next. workflow-status is mainly useful for:
|
||||
|
||||
- New projects (guides initial setup)
|
||||
- When you're unsure what to do next
|
||||
- After breaks in work (reminds you where you left off)
|
||||
- Checking overall progress
|
||||
|
||||
## Q: What's the minimum I need to get started?
|
||||
### What's the minimum I need to get started?
|
||||
|
||||
**A:** For the fastest path:
|
||||
For the fastest path:
|
||||
|
||||
1. Install BMad Method: `npx bmad-method@alpha install`
|
||||
2. For small changes: Load PM agent → run tech-spec → implement
|
||||
3. For larger projects: Load PM agent → run prd → architect → implement
|
||||
|
||||
## Q: How do I know if I'm in Phase 1, 2, 3, or 4?
|
||||
### How do I know if I'm in Phase 1, 2, 3, or 4?
|
||||
|
||||
**A:** Check your `bmm-workflow-status.md` file (created by workflow-init). It shows your current phase and progress. If you don't have this file, you can also tell by what you're working on:
|
||||
Check your `bmm-workflow-status.md` file (created by workflow-init). It shows your current phase and progress. If you don't have this file, you can also tell by what you're working on:
|
||||
|
||||
- **Phase 1** - Brainstorming, research, product brief (optional)
|
||||
- **Phase 2** - Creating either a PRD or tech-spec (always required)
|
||||
- **Phase 3** - Architecture design (Level 2-4 only)
|
||||
- **Phase 4** - Actually writing code, implementing stories
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Get started with BMM
|
||||
- [Glossary](../../reference/glossary/index.md) - Terminology reference
|
||||
|
||||
---
|
||||
- **Phase 1** — Brainstorming, research, product brief (optional)
|
||||
- **Phase 2** — Creating either a PRD or tech-spec (always required)
|
||||
- **Phase 3** — Architecture design (Level 2-4 only)
|
||||
- **Phase 4** — Actually writing code, implementing stories
|
||||
|
||||
**Have a question not answered here?** Please [open an issue](https://github.com/bmad-code-org/BMAD-METHOD/issues) or ask in [Discord](https://discord.gg/gk8jAdXWmj) so we can add it!
|
||||
|
|
|
|||
|
|
@ -3,54 +3,50 @@ title: "Implementation FAQ"
|
|||
description: Common questions about implementation in the BMad Method
|
||||
---
|
||||
|
||||
|
||||
Quick answers to common questions about implementation in the BMad Method.
|
||||
|
||||
---
|
||||
## Questions
|
||||
|
||||
## Q: Does create-story include implementation context?
|
||||
- [Does create-story include implementation context?](#does-create-story-include-implementation-context)
|
||||
- [How do I mark a story as done?](#how-do-i-mark-a-story-as-done)
|
||||
- [Can I work on multiple stories at once?](#can-i-work-on-multiple-stories-at-once)
|
||||
- [What if my story takes longer than estimated?](#what-if-my-story-takes-longer-than-estimated)
|
||||
- [When should I run retrospective?](#when-should-i-run-retrospective)
|
||||
|
||||
**A:** Yes! The create-story workflow generates story files that include implementation-specific guidance, references existing patterns from your documentation, and provides technical context. The workflow loads your architecture, PRD, and existing project documentation to create comprehensive stories. For Quick Flow projects using tech-spec, the tech-spec itself is already comprehensive, so stories can be simpler.
|
||||
### Does create-story include implementation context?
|
||||
|
||||
## Q: How do I mark a story as done?
|
||||
Yes! The create-story workflow generates story files that include implementation-specific guidance, references existing patterns from your documentation, and provides technical context. The workflow loads your architecture, PRD, and existing project documentation to create comprehensive stories. For Quick Flow projects using tech-spec, the tech-spec itself is already comprehensive, so stories can be simpler.
|
||||
|
||||
**A:** After dev-story completes and code-review passes:
|
||||
### How do I mark a story as done?
|
||||
|
||||
After dev-story completes and code-review passes:
|
||||
|
||||
1. Open `sprint-status.yaml` (created by sprint-planning)
|
||||
2. Change the story status from `review` to `done`
|
||||
3. Save the file
|
||||
|
||||
## Q: Can I work on multiple stories at once?
|
||||
### Can I work on multiple stories at once?
|
||||
|
||||
**A:** Yes, if you have capacity! Stories within different epics can be worked in parallel. However, stories within the same epic are usually sequential because they build on each other.
|
||||
Yes, if you have capacity! Stories within different epics can be worked in parallel. However, stories within the same epic are usually sequential because they build on each other.
|
||||
|
||||
## Q: What if my story takes longer than estimated?
|
||||
### What if my story takes longer than estimated?
|
||||
|
||||
**A:** That's normal! Stories are estimates. If implementation reveals more complexity:
|
||||
That's normal! Stories are estimates. If implementation reveals more complexity:
|
||||
|
||||
1. Continue working until DoD is met
|
||||
2. Consider if story should be split
|
||||
3. Document learnings in retrospective
|
||||
4. Adjust future estimates based on this learning
|
||||
|
||||
## Q: When should I run retrospective?
|
||||
### When should I run retrospective?
|
||||
|
||||
**A:** After completing all stories in an epic (when epic is done). Retrospectives capture:
|
||||
After completing all stories in an epic (when epic is done). Retrospectives capture:
|
||||
|
||||
- What went well
|
||||
- What could improve
|
||||
- Technical insights
|
||||
- Learnings for future epics
|
||||
|
||||
Don't wait until project end - run after each epic for continuous improvement.
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Get started with BMM
|
||||
- [Glossary](../../reference/glossary/index.md) - Terminology reference
|
||||
|
||||
---
|
||||
Don't wait until project end — run after each epic for continuous improvement.
|
||||
|
||||
**Have a question not answered here?** Please [open an issue](https://github.com/bmad-code-org/BMAD-METHOD/issues) or ask in [Discord](https://discord.gg/gk8jAdXWmj) so we can add it!
|
||||
|
|
|
|||
|
|
@ -3,15 +3,14 @@ title: "Frequently Asked Questions"
|
|||
description: Frequently asked questions about the BMad Method
|
||||
---
|
||||
|
||||
|
||||
Quick answers to common questions about the BMad Method, organized by topic.
|
||||
|
||||
## Topics
|
||||
|
||||
- [Getting Started](./getting-started-faq.md) - Questions about starting with BMM
|
||||
- [Levels & Tracks](./levels-and-tracks-faq.md) - Choosing the right level
|
||||
- [Workflows](./workflows-faq.md) - Workflow and phase questions
|
||||
- [Planning](./planning-faq.md) - Planning document questions
|
||||
- [Implementation](./implementation-faq.md) - Implementation questions
|
||||
- [Brownfield](./brownfield-faq.md) - Existing codebase questions
|
||||
- [Tools & Advanced](./tools-faq.md) - Tools, IDEs, and advanced topics
|
||||
- [Getting Started](/docs/explanation/faq/getting-started-faq.md) - Questions about starting with BMad
|
||||
- [Levels & Tracks](/docs/explanation/faq/levels-and-tracks-faq.md) - Choosing the right level
|
||||
- [Workflows](/docs/explanation/faq/workflows-faq.md) - Workflow and phase questions
|
||||
- [Planning](/docs/explanation/faq/planning-faq.md) - Planning document questions
|
||||
- [Implementation](/docs/explanation/faq/implementation-faq.md) - Implementation questions
|
||||
- [Brownfield](/docs/explanation/faq/brownfield-faq.md) - Existing codebase questions
|
||||
- [Tools & Advanced](/docs/explanation/faq/tools-faq.md) - Tools, IDEs, and advanced topics
|
||||
|
|
|
|||
|
|
@ -3,41 +3,44 @@ title: "Levels and Tracks FAQ"
|
|||
description: Common questions about choosing the right level for your project
|
||||
---
|
||||
|
||||
|
||||
Quick answers to common questions about choosing the right level for your BMad Method project.
|
||||
|
||||
---
|
||||
## Questions
|
||||
|
||||
## Q: How do I know which level my project is?
|
||||
- [How do I know which level my project is?](#how-do-i-know-which-level-my-project-is)
|
||||
- [Can I change levels mid-project?](#can-i-change-levels-mid-project)
|
||||
- [What if workflow-init suggests the wrong level?](#what-if-workflow-init-suggests-the-wrong-level)
|
||||
- [Do I always need architecture for Level 2?](#do-i-always-need-architecture-for-level-2)
|
||||
- [What's the difference between Level 1 and Level 2?](#whats-the-difference-between-level-1-and-level-2)
|
||||
|
||||
**A:** Use workflow-init for automatic detection, or self-assess using these keywords:
|
||||
### How do I know which level my project is?
|
||||
|
||||
- **Level 0:** "fix", "bug", "typo", "small change", "patch" → 1 story
|
||||
- **Level 1:** "simple", "basic", "small feature", "add" → 1-10 stories
|
||||
- **Level 2:** "dashboard", "several features", "admin panel" → 5-15 stories
|
||||
- **Level 3:** "platform", "integration", "complex", "system" → 12-40 stories
|
||||
- **Level 4:** "enterprise", "multi-tenant", "multiple products" → 40+ stories
|
||||
Use workflow-init for automatic detection, or self-assess using these keywords:
|
||||
|
||||
- **Level 0** — "fix", "bug", "typo", "small change", "patch" → 1 story
|
||||
- **Level 1** — "simple", "basic", "small feature", "add" → 1-10 stories
|
||||
- **Level 2** — "dashboard", "several features", "admin panel" → 5-15 stories
|
||||
- **Level 3** — "platform", "integration", "complex", "system" → 12-40 stories
|
||||
- **Level 4** — "enterprise", "multi-tenant", "multiple products" → 40+ stories
|
||||
|
||||
When in doubt, start smaller. You can always run create-prd later if needed.
|
||||
|
||||
## Q: Can I change levels mid-project?
|
||||
### Can I change levels mid-project?
|
||||
|
||||
**A:** Yes! If you started at Level 1 but realize it's Level 2, you can run create-prd to add proper planning docs. The system is flexible - your initial level choice isn't permanent.
|
||||
Yes! If you started at Level 1 but realize it's Level 2, you can run create-prd to add proper planning docs. The system is flexible — your initial level choice isn't permanent.
|
||||
|
||||
## Q: What if workflow-init suggests the wrong level?
|
||||
### What if workflow-init suggests the wrong level?
|
||||
|
||||
**A:** You can override it! workflow-init suggests a level but always asks for confirmation. If you disagree, just say so and choose the level you think is appropriate. Trust your judgment.
|
||||
You can override it! workflow-init suggests a level but always asks for confirmation. If you disagree, just say so and choose the level you think is appropriate. Trust your judgment.
|
||||
|
||||
## Q: Do I always need architecture for Level 2?
|
||||
### Do I always need architecture for Level 2?
|
||||
|
||||
**A:** No, architecture is **optional** for Level 2. Only create architecture if you need system-level design. Many Level 2 projects work fine with just PRD created during planning.
|
||||
No, architecture is **optional** for Level 2. Only create architecture if you need system-level design. Many Level 2 projects work fine with just PRD created during planning.
|
||||
|
||||
## Q: What's the difference between Level 1 and Level 2?
|
||||
### What's the difference between Level 1 and Level 2?
|
||||
|
||||
**A:**
|
||||
|
||||
- **Level 1:** 1-10 stories, uses tech-spec (simpler, faster), no architecture
|
||||
- **Level 2:** 5-15 stories, uses PRD (product-focused), optional architecture
|
||||
- **Level 1** — 1-10 stories, uses tech-spec (simpler, faster), no architecture
|
||||
- **Level 2** — 5-15 stories, uses PRD (product-focused), optional architecture
|
||||
|
||||
The overlap (5-10 stories) is intentional. Choose based on:
|
||||
|
||||
|
|
@ -46,13 +49,4 @@ The overlap (5-10 stories) is intentional. Choose based on:
|
|||
- Multiple epics? → Level 2
|
||||
- Single epic? → Level 1
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Get started with BMM
|
||||
- [Glossary](../../reference/glossary/index.md) - Terminology reference
|
||||
|
||||
---
|
||||
|
||||
**Have a question not answered here?** Please [open an issue](https://github.com/bmad-code-org/BMAD-METHOD/issues) or ask in [Discord](https://discord.gg/gk8jAdXWmj) so we can add it!
|
||||
|
|
|
|||
|
|
@ -3,22 +3,25 @@ title: "Planning Documents FAQ"
|
|||
description: Common questions about planning documents in the BMad Method
|
||||
---
|
||||
|
||||
|
||||
Quick answers to common questions about planning documents in the BMad Method.
|
||||
|
||||
---
|
||||
## Questions
|
||||
|
||||
## Q: Why no tech-spec at Level 2+?
|
||||
- [Why no tech-spec at Level 2+?](#why-no-tech-spec-at-level-2)
|
||||
- [Do I need a PRD for a bug fix?](#do-i-need-a-prd-for-a-bug-fix)
|
||||
- [Can I skip the product brief?](#can-i-skip-the-product-brief)
|
||||
|
||||
**A:** Level 2+ projects need product-level planning (PRD) and system-level design (Architecture), which tech-spec doesn't provide. Tech-spec is too narrow for coordinating multiple features. Instead, Level 2-4 uses:
|
||||
### Why no tech-spec at Level 2+?
|
||||
|
||||
Level 2+ projects need product-level planning (PRD) and system-level design (Architecture), which tech-spec doesn't provide. Tech-spec is too narrow for coordinating multiple features. Instead, Level 2-4 uses:
|
||||
|
||||
- PRD (product vision, functional requirements, non-functional requirements)
|
||||
- Architecture (system design)
|
||||
- Epics+Stories (created AFTER architecture is complete)
|
||||
|
||||
## Q: Do I need a PRD for a bug fix?
|
||||
### Do I need a PRD for a bug fix?
|
||||
|
||||
**A:** No! Bug fixes are typically Level 0 (single atomic change). Use Quick Spec Flow:
|
||||
No! Bug fixes are typically Level 0 (single atomic change). Use Quick Spec Flow:
|
||||
|
||||
- Load PM agent
|
||||
- Run tech-spec workflow
|
||||
|
|
@ -26,22 +29,13 @@ Quick answers to common questions about planning documents in the BMad Method.
|
|||
|
||||
PRDs are for Level 2-4 projects with multiple features requiring product-level coordination.
|
||||
|
||||
## Q: Can I skip the product brief?
|
||||
### Can I skip the product brief?
|
||||
|
||||
**A:** Yes, product brief is always optional. It's most valuable for:
|
||||
Yes, product brief is always optional. It's most valuable for:
|
||||
|
||||
- Level 3-4 projects needing strategic direction
|
||||
- Projects with stakeholders requiring alignment
|
||||
- Novel products needing market research
|
||||
- When you want to explore solution space before committing
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Get started with BMM
|
||||
- [Glossary](../../reference/glossary/index.md) - Terminology reference
|
||||
|
||||
---
|
||||
|
||||
**Have a question not answered here?** Please [open an issue](https://github.com/bmad-code-org/BMAD-METHOD/issues) or ask in [Discord](https://discord.gg/gk8jAdXWmj) so we can add it!
|
||||
|
|
|
|||
|
|
@ -3,16 +3,38 @@ title: "Tools and Advanced FAQ"
|
|||
description: Common questions about tools, IDEs, and advanced topics in the BMad Method
|
||||
---
|
||||
|
||||
|
||||
Quick answers to common questions about tools, IDEs, and advanced topics in the BMad Method.
|
||||
|
||||
---
|
||||
## Questions
|
||||
|
||||
**Tools and Technical**
|
||||
|
||||
- [Why are my Mermaid diagrams not rendering?](#why-are-my-mermaid-diagrams-not-rendering)
|
||||
- [Can I use BMM with GitHub Copilot / Cursor / other AI tools?](#can-i-use-bmm-with-github-copilot--cursor--other-ai-tools)
|
||||
- [What IDEs/tools support BMM?](#what-idestools-support-bmm)
|
||||
- [Can I customize agents?](#can-i-customize-agents)
|
||||
- [What happens to my planning docs after implementation?](#what-happens-to-my-planning-docs-after-implementation)
|
||||
- [Can I use BMM for non-software projects?](#can-i-use-bmm-for-non-software-projects)
|
||||
|
||||
**Advanced**
|
||||
|
||||
- [What if my project grows from Level 1 to Level 3?](#what-if-my-project-grows-from-level-1-to-level-3)
|
||||
- [Can I mix greenfield and brownfield approaches?](#can-i-mix-greenfield-and-brownfield-approaches)
|
||||
- [How do I handle urgent hotfixes during a sprint?](#how-do-i-handle-urgent-hotfixes-during-a-sprint)
|
||||
- [What if I disagree with the workflow's recommendations?](#what-if-i-disagree-with-the-workflows-recommendations)
|
||||
- [Can multiple developers work on the same BMM project?](#can-multiple-developers-work-on-the-same-bmm-project)
|
||||
- [What is party mode and when should I use it?](#what-is-party-mode-and-when-should-i-use-it)
|
||||
|
||||
**Getting Help**
|
||||
|
||||
- [Where do I get help if my question isn't answered here?](#where-do-i-get-help-if-my-question-isnt-answered-here)
|
||||
- [How do I report a bug or request a feature?](#how-do-i-report-a-bug-or-request-a-feature)
|
||||
|
||||
## Tools and Technical
|
||||
|
||||
### Q: Why are my Mermaid diagrams not rendering?
|
||||
### Why are my Mermaid diagrams not rendering?
|
||||
|
||||
**A:** Common issues:
|
||||
Common issues:
|
||||
|
||||
1. Missing language tag: Use ` ```mermaid` not just ` ``` `
|
||||
2. Syntax errors in diagram (validate at mermaid.live)
|
||||
|
|
@ -20,9 +42,9 @@ Quick answers to common questions about tools, IDEs, and advanced topics in the
|
|||
|
||||
All BMM docs use valid Mermaid syntax that should render in GitHub, VS Code, and most IDEs.
|
||||
|
||||
### Q: Can I use BMM with GitHub Copilot / Cursor / other AI tools?
|
||||
### Can I use BMM with GitHub Copilot / Cursor / other AI tools?
|
||||
|
||||
**A:** Yes! BMM is complementary. BMM handles:
|
||||
Yes! BMM is complementary. BMM handles:
|
||||
|
||||
- Project planning and structure
|
||||
- Workflow orchestration
|
||||
|
|
@ -38,13 +60,13 @@ Your AI coding assistant handles:
|
|||
|
||||
Use them together for best results.
|
||||
|
||||
### Q: What IDEs/tools support BMM?
|
||||
### What IDEs/tools support BMM?
|
||||
|
||||
**A:** BMM requires tools with **agent mode** and access to **high-quality LLM models** that can load and follow complex workflows, then properly implement code changes.
|
||||
BMM requires tools with **agent mode** and access to **high-quality LLM models** that can load and follow complex workflows, then properly implement code changes.
|
||||
|
||||
**Recommended Tools:**
|
||||
|
||||
- **Claude Code** - Best choice
|
||||
- **Claude Code** — Best choice
|
||||
- Sonnet 4.5 (excellent workflow following, coding, reasoning)
|
||||
- Opus (maximum context, complex planning)
|
||||
- Native agent mode designed for BMM workflows
|
||||
|
|
@ -61,22 +83,22 @@ Use them together for best results.
|
|||
|
||||
**What Matters:**
|
||||
|
||||
1. **Agent mode** - Can load long workflow instructions and maintain context
|
||||
2. **High-quality LLM** - Models ranked high on SWE-bench (coding benchmarks)
|
||||
3. **Model selection** - Access to Claude Sonnet 4.5, Opus, or GPT-4o class models
|
||||
4. **Context capacity** - Can handle large planning documents and codebases
|
||||
1. **Agent mode** — Can load long workflow instructions and maintain context
|
||||
2. **High-quality LLM** — Models ranked high on SWE-bench (coding benchmarks)
|
||||
3. **Model selection** — Access to Claude Sonnet 4.5, Opus, or GPT-4o class models
|
||||
4. **Context capacity** — Can handle large planning documents and codebases
|
||||
|
||||
**Why model quality matters:** BMM workflows require LLMs that can follow multi-step processes, maintain context across phases, and implement code that adheres to specifications. Tools with weaker models will struggle with workflow adherence and code quality.
|
||||
|
||||
### Q: Can I customize agents?
|
||||
### Can I customize agents?
|
||||
|
||||
**A:** Yes! Agents are installed as markdown files with XML-style content (optimized for LLMs, readable by any model). Create customization files in `_bmad/_config/agents/[agent-name].customize.yaml` to override default behaviors while keeping core functionality intact. See agent documentation for customization options.
|
||||
Yes! Agents are installed as markdown files with XML-style content (optimized for LLMs, readable by any model). Create customization files in `_bmad/_config/agents/[agent-name].customize.yaml` to override default behaviors while keeping core functionality intact. See agent documentation for customization options.
|
||||
|
||||
**Note:** While source agents in this repo are YAML, they install as `.md` files with XML-style tags - a format any LLM can read and follow.
|
||||
**Note:** While source agents in this repo are YAML, they install as `.md` files with XML-style tags — a format any LLM can read and follow.
|
||||
|
||||
### Q: What happens to my planning docs after implementation?
|
||||
### What happens to my planning docs after implementation?
|
||||
|
||||
**A:** Keep them! They serve as:
|
||||
Keep them! They serve as:
|
||||
|
||||
- Historical record of decisions
|
||||
- Onboarding material for new team members
|
||||
|
|
@ -85,37 +107,35 @@ Use them together for best results.
|
|||
|
||||
For enterprise projects (Level 4), consider archiving completed planning artifacts to keep workspace clean.
|
||||
|
||||
### Q: Can I use BMM for non-software projects?
|
||||
### Can I use BMM for non-software projects?
|
||||
|
||||
**A:** BMM is optimized for software development, but the methodology principles (scale-adaptive planning, just-in-time design, context injection) can apply to other complex project types. You'd need to adapt workflows and agents for your domain.
|
||||
BMM is optimized for software development, but the methodology principles (scale-adaptive planning, just-in-time design, context injection) can apply to other complex project types. You'd need to adapt workflows and agents for your domain.
|
||||
|
||||
---
|
||||
## Advanced
|
||||
|
||||
## Advanced Questions
|
||||
### What if my project grows from Level 1 to Level 3?
|
||||
|
||||
### Q: What if my project grows from Level 1 to Level 3?
|
||||
|
||||
**A:** Totally fine! When you realize scope has grown:
|
||||
Totally fine! When you realize scope has grown:
|
||||
|
||||
1. Run create-prd to add product-level planning
|
||||
2. Run create-architecture for system design
|
||||
3. Use existing tech-spec as input for PRD
|
||||
4. Continue with updated level
|
||||
|
||||
The system is flexible - growth is expected.
|
||||
The system is flexible — growth is expected.
|
||||
|
||||
### Q: Can I mix greenfield and brownfield approaches?
|
||||
### Can I mix greenfield and brownfield approaches?
|
||||
|
||||
**A:** Yes! Common scenario: adding new greenfield feature to brownfield codebase. Approach:
|
||||
Yes! Common scenario: adding new greenfield feature to brownfield codebase. Approach:
|
||||
|
||||
1. Run document-project for brownfield context
|
||||
2. Use greenfield workflows for new feature planning
|
||||
3. Explicitly document integration points between new and existing
|
||||
4. Test integration thoroughly
|
||||
|
||||
### Q: How do I handle urgent hotfixes during a sprint?
|
||||
### How do I handle urgent hotfixes during a sprint?
|
||||
|
||||
**A:** Use correct-course workflow or just:
|
||||
Use correct-course workflow or just:
|
||||
|
||||
1. Save your current work state
|
||||
2. Load PM agent → quick tech-spec for hotfix
|
||||
|
|
@ -125,25 +145,25 @@ The system is flexible - growth is expected.
|
|||
|
||||
Level 0 Quick Spec Flow is perfect for urgent fixes.
|
||||
|
||||
### Q: What if I disagree with the workflow's recommendations?
|
||||
### What if I disagree with the workflow's recommendations?
|
||||
|
||||
**A:** Workflows are guidance, not enforcement. If a workflow recommends something that doesn't make sense for your context:
|
||||
Workflows are guidance, not enforcement. If a workflow recommends something that doesn't make sense for your context:
|
||||
|
||||
- Explain your reasoning to the agent
|
||||
- Ask for alternative approaches
|
||||
- Skip the recommendation if you're confident
|
||||
- Document why you deviated (for future reference)
|
||||
|
||||
Trust your expertise - BMM supports your decisions.
|
||||
Trust your expertise — BMM supports your decisions.
|
||||
|
||||
### Q: Can multiple developers work on the same BMM project?
|
||||
### Can multiple developers work on the same BMM project?
|
||||
|
||||
**A:** Yes! But the paradigm is fundamentally different from traditional agile teams.
|
||||
Yes! But the paradigm is fundamentally different from traditional agile teams.
|
||||
|
||||
**Key Difference:**
|
||||
|
||||
- **Traditional:** Multiple devs work on stories within one epic (months)
|
||||
- **Agentic:** Each dev owns complete epics (days)
|
||||
- **Traditional** — Multiple devs work on stories within one epic (months)
|
||||
- **Agentic** — Each dev owns complete epics (days)
|
||||
|
||||
**In traditional agile:** A team of 5 devs might spend 2-3 months on a single epic, with each dev owning different stories.
|
||||
|
||||
|
|
@ -177,9 +197,9 @@ Trust your expertise - BMM supports your decisions.
|
|||
- Coordinate at epic boundaries, not story level
|
||||
- Use git submodules for BMM in enterprise settings
|
||||
|
||||
### Q: What is party mode and when should I use it?
|
||||
### What is party mode and when should I use it?
|
||||
|
||||
**A:** Party mode is a unique multi-agent collaboration feature where ALL your installed agents (19+ from BMM, CIS, BMB, custom modules) discuss your challenges together in real-time.
|
||||
Party mode is a unique multi-agent collaboration feature where ALL your installed agents (19+ from BMM, CIS, BMB, custom modules) discuss your challenges together in real-time.
|
||||
|
||||
**How it works:**
|
||||
|
||||
|
|
@ -197,9 +217,9 @@ Trust your expertise - BMM supports your decisions.
|
|||
|
||||
**Example parties:**
|
||||
|
||||
- **Product Strategy:** PM + Innovation Strategist (CIS) + Analyst
|
||||
- **Technical Design:** Architect + Creative Problem Solver (CIS) + Game Architect
|
||||
- **User Experience:** UX Designer + Design Thinking Coach (CIS) + Storyteller (CIS)
|
||||
- **Product Strategy** — PM + Innovation Strategist (CIS) + Analyst
|
||||
- **Technical Design** — Architect + Creative Problem Solver (CIS) + Game Architect
|
||||
- **User Experience** — UX Designer + Design Thinking Coach (CIS) + Storyteller (CIS)
|
||||
|
||||
**Why it's powerful:**
|
||||
|
||||
|
|
@ -208,26 +228,20 @@ Trust your expertise - BMM supports your decisions.
|
|||
- Emergent insights from agent interaction
|
||||
- Natural collaboration across modules
|
||||
|
||||
**For complete documentation:**
|
||||
|
||||
👉 **[Party Mode Guide](../../explanation/features/party-mode.md)** - How it works, when to use it, example compositions, best practices
|
||||
|
||||
---
|
||||
**For complete documentation:** See the [Party Mode Guide](/docs/explanation/features/party-mode.md)
|
||||
|
||||
## Getting Help
|
||||
|
||||
### Q: Where do I get help if my question isn't answered here?
|
||||
|
||||
**A:**
|
||||
### Where do I get help if my question isn't answered here?
|
||||
|
||||
1. Search [Complete Documentation](https://github.com/bmad-code-org/BMAD-METHOD/blob/main/README.md) for related topics
|
||||
2. Ask in [Discord Community](https://discord.gg/gk8jAdXWmj) (#bmad-method-help)
|
||||
3. Open a [GitHub Issue](https://github.com/bmad-code-org/BMAD-METHOD/issues)
|
||||
4. Watch [YouTube Tutorials](https://www.youtube.com/@BMadCode)
|
||||
|
||||
### Q: How do I report a bug or request a feature?
|
||||
### How do I report a bug or request a feature?
|
||||
|
||||
**A:** Open a GitHub issue at: <https://github.com/bmad-code-org/BMAD-METHOD/issues>
|
||||
Open a GitHub issue at: <https://github.com/bmad-code-org/BMAD-METHOD/issues>
|
||||
|
||||
Please include:
|
||||
|
||||
|
|
@ -236,13 +250,4 @@ Please include:
|
|||
- Expected vs actual behavior
|
||||
- Relevant workflow or agent involved
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Get started with BMM
|
||||
- [Glossary](../../reference/glossary/index.md) - Terminology reference
|
||||
|
||||
---
|
||||
|
||||
**Have a question not answered here?** Please [open an issue](https://github.com/bmad-code-org/BMAD-METHOD/issues) or ask in [Discord](https://discord.gg/gk8jAdXWmj) so we can add it!
|
||||
|
|
|
|||
|
|
@ -3,66 +3,59 @@ title: "Workflows FAQ"
|
|||
description: Common questions about BMad Method workflows and phases
|
||||
---
|
||||
|
||||
|
||||
Quick answers to common questions about BMad Method workflows and phases.
|
||||
|
||||
---
|
||||
## Questions
|
||||
|
||||
## Q: What's the difference between workflow-status and workflow-init?
|
||||
- [What's the difference between workflow-status and workflow-init?](#whats-the-difference-between-workflow-status-and-workflow-init)
|
||||
- [Can I skip Phase 1 (Analysis)?](#can-i-skip-phase-1-analysis)
|
||||
- [When is Phase 3 (Architecture) required?](#when-is-phase-3-architecture-required)
|
||||
- [What happens if I skip a recommended workflow?](#what-happens-if-i-skip-a-recommended-workflow)
|
||||
- [How do I know when Phase 3 is complete?](#how-do-i-know-when-phase-3-is-complete)
|
||||
- [Can I run workflows in parallel?](#can-i-run-workflows-in-parallel)
|
||||
|
||||
**A:**
|
||||
### What's the difference between workflow-status and workflow-init?
|
||||
|
||||
- **workflow-status:** Checks existing status and tells you what's next (use when continuing work)
|
||||
- **workflow-init:** Creates new status file and sets up project (use when starting new project)
|
||||
- **workflow-status** — Checks existing status and tells you what's next (use when continuing work)
|
||||
- **workflow-init** — Creates new status file and sets up project (use when starting new project)
|
||||
|
||||
If status file exists, use workflow-status. If not, use workflow-init.
|
||||
|
||||
## Q: Can I skip Phase 1 (Analysis)?
|
||||
### Can I skip Phase 1 (Analysis)?
|
||||
|
||||
**A:** Yes! Phase 1 is optional for all levels, though recommended for complex projects. Skip if:
|
||||
Yes! Phase 1 is optional for all levels, though recommended for complex projects. Skip if:
|
||||
|
||||
- Requirements are clear
|
||||
- No research needed
|
||||
- Time-sensitive work
|
||||
- Small changes (Level 0-1)
|
||||
|
||||
## Q: When is Phase 3 (Architecture) required?
|
||||
### When is Phase 3 (Architecture) required?
|
||||
|
||||
**A:**
|
||||
- **Level 0-1** — Never (skip entirely)
|
||||
- **Level 2** — Optional (only if system design needed)
|
||||
- **Level 3-4** — Required (comprehensive architecture mandatory)
|
||||
|
||||
- **Level 0-1:** Never (skip entirely)
|
||||
- **Level 2:** Optional (only if system design needed)
|
||||
- **Level 3-4:** Required (comprehensive architecture mandatory)
|
||||
### What happens if I skip a recommended workflow?
|
||||
|
||||
## Q: What happens if I skip a recommended workflow?
|
||||
|
||||
**A:** Nothing breaks! Workflows are guidance, not enforcement. However, skipping recommended workflows (like architecture for Level 3) may cause:
|
||||
Nothing breaks! Workflows are guidance, not enforcement. However, skipping recommended workflows (like architecture for Level 3) may cause:
|
||||
|
||||
- Integration issues during implementation
|
||||
- Rework due to poor planning
|
||||
- Conflicting design decisions
|
||||
- Longer development time overall
|
||||
|
||||
## Q: How do I know when Phase 3 is complete and I can start Phase 4?
|
||||
### How do I know when Phase 3 is complete?
|
||||
|
||||
**A:** For Level 3-4, run the implementation-readiness workflow. It validates PRD + Architecture + Epics + UX (optional) are aligned before implementation. Pass the gate check = ready for Phase 4.
|
||||
For Level 3-4, run the implementation-readiness workflow. It validates PRD + Architecture + Epics + UX (optional) are aligned before implementation. Pass the gate check = ready for Phase 4.
|
||||
|
||||
## Q: Can I run workflows in parallel or do they have to be sequential?
|
||||
### Can I run workflows in parallel?
|
||||
|
||||
**A:** Most workflows must be sequential within a phase:
|
||||
Most workflows must be sequential within a phase:
|
||||
|
||||
- Phase 1: brainstorm → research → product-brief (optional order)
|
||||
- Phase 2: PRD must complete before moving forward
|
||||
- Phase 3: architecture → epics+stories → implementation-readiness (sequential)
|
||||
- Phase 4: Stories within an epic should generally be sequential, but stories in different epics can be parallel if you have capacity
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Get started with BMM
|
||||
- [Glossary](../../reference/glossary/index.md) - Terminology reference
|
||||
|
||||
---
|
||||
- **Phase 1** — brainstorm → research → product-brief (optional order)
|
||||
- **Phase 2** — PRD must complete before moving forward
|
||||
- **Phase 3** — architecture → epics+stories → implementation-readiness (sequential)
|
||||
- **Phase 4** — Stories within an epic should generally be sequential, but stories in different epics can be parallel if you have capacity
|
||||
|
||||
**Have a question not answered here?** Please [open an issue](https://github.com/bmad-code-org/BMAD-METHOD/issues) or ask in [Discord](https://discord.gg/gk8jAdXWmj) so we can add it!
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ Based on context, 5 methods are intelligently selected from a library of 50+ tec
|
|||
- Each method builds on previous enhancements
|
||||
|
||||
### 4. Party Mode Integration (Optional)
|
||||
If Party Mode is active, BMAD agents participate randomly in the elicitation process, adding their unique perspectives to the methods.
|
||||
If Party Mode is active, BMad agents participate randomly in the elicitation process, adding their unique perspectives to the methods.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -103,9 +103,9 @@ _(Multiple perspectives reveal the right answer)_
|
|||
|
||||
## Related Documentation
|
||||
|
||||
- [Agents Reference](../../reference/agents/index.md) - Complete agent reference
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Getting started with BMM
|
||||
- [Setup Party Mode](../../how-to/workflows/setup-party-mode.md) - How to use it
|
||||
- [Agents Reference](/docs/reference/agents/index.md) - Complete agent reference
|
||||
- [Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md) - Getting started with BMM
|
||||
- [Setup Party Mode](/docs/how-to/workflows/setup-party-mode.md) - How to use it
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -164,6 +164,6 @@ Start with Quick Flow, but switch to BMad Method when:
|
|||
|
||||
## Related
|
||||
|
||||
- [Create Tech Spec](../../how-to/workflows/create-tech-spec.md) - How to use Quick Flow
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Getting started
|
||||
- [Four Phases](../architecture/four-phases.md) - Understanding the full methodology
|
||||
- [Create Tech Spec](/docs/how-to/workflows/create-tech-spec.md) - How to use Quick Flow
|
||||
- [Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md) - Getting started
|
||||
- [Four Phases](/docs/explanation/architecture/four-phases.md) - Understanding the full methodology
|
||||
|
|
|
|||
|
|
@ -195,24 +195,299 @@ Epic/Release Gate → TEA: *nfr-assess, *trace Phase 2 (release decision)
|
|||
|
||||
**Note**: `*trace` is a two-phase workflow: Phase 1 (traceability) + Phase 2 (gate decision). This reduces cognitive load while maintaining natural workflow.
|
||||
|
||||
### Why TEA Requires Its Own Knowledge Base
|
||||
|
||||
TEA uniquely requires:
|
||||
|
||||
- **Extensive domain knowledge**: 30+ fragments covering test patterns, CI/CD, fixtures, quality practices, and optional playwright-utils integration
|
||||
- **Cross-cutting concerns**: Domain-specific testing patterns that apply across all BMad projects (vs project-specific artifacts like PRDs/stories)
|
||||
- **Optional integrations**: MCP capabilities (exploratory, verification) and playwright-utils support
|
||||
|
||||
This architecture enables TEA to maintain consistent, production-ready testing patterns across all BMad projects while operating across multiple development phases.
|
||||
|
||||
---
|
||||
|
||||
|
||||
## High-Level Cheat Sheets
|
||||
|
||||
These cheat sheets map TEA workflows to the **BMad Method and Enterprise tracks** across the **4-Phase Methodology** (Phase 1: Analysis, Phase 2: Planning, Phase 3: Solutioning, Phase 4: Implementation).
|
||||
|
||||
**Note:** Quick Flow projects typically don't require TEA (covered in Overview). These cheat sheets focus on BMad Method and Enterprise tracks where TEA adds value.
|
||||
|
||||
**Legend for Track Deltas:**
|
||||
|
||||
- ➕ = New workflow or phase added (doesn't exist in baseline)
|
||||
- 🔄 = Modified focus (same workflow, different emphasis or purpose)
|
||||
- 📦 = Additional output or archival requirement
|
||||
|
||||
### Greenfield - BMad Method (Simple/Standard Work)
|
||||
|
||||
**Planning Track:** BMad Method (PRD + Architecture)
|
||||
**Use Case:** New projects with standard complexity
|
||||
|
||||
| Workflow Stage | Test Architect | Dev / Team | Outputs |
|
||||
| -------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------- |
|
||||
| **Phase 1**: Discovery | - | Analyst `*product-brief` (optional) | `product-brief.md` |
|
||||
| **Phase 2**: Planning | - | PM `*prd` (creates PRD with FRs/NFRs) | PRD with functional/non-functional requirements |
|
||||
| **Phase 3**: Solutioning | Run `*framework`, `*ci` AFTER architecture and epic creation | Architect `*architecture`, `*create-epics-and-stories`, `*implementation-readiness` | Architecture, epics/stories, test scaffold, CI pipeline |
|
||||
| **Phase 4**: Sprint Start | - | SM `*sprint-planning` | Sprint status file with all epics and stories |
|
||||
| **Phase 4**: Epic Planning | Run `*test-design` for THIS epic (per-epic test plan) | Review epic scope | `test-design-epic-N.md` with risk assessment and test plan |
|
||||
| **Phase 4**: Story Dev | (Optional) `*atdd` before dev, then `*automate` after | SM `*create-story`, DEV implements | Tests, story implementation |
|
||||
| **Phase 4**: Story Review | Execute `*test-review` (optional), re-run `*trace` | Address recommendations, update code/tests | Quality report, refreshed coverage matrix |
|
||||
| **Phase 4**: Release Gate | (Optional) `*test-review` for final audit, Run `*trace` (Phase 2) | Confirm Definition of Done, share release notes | Quality audit, Gate YAML + release summary |
|
||||
|
||||
<details>
|
||||
<summary>Execution Notes</summary>
|
||||
|
||||
- Run `*framework` only once per repo or when modern harness support is missing.
|
||||
- **Phase 3 (Solutioning)**: After architecture is complete, run `*framework` and `*ci` to setup test infrastructure based on architectural decisions.
|
||||
- **Phase 4 starts**: After solutioning is complete, sprint planning loads all epics.
|
||||
- **`*test-design` runs per-epic**: At the beginning of working on each epic, run `*test-design` to create a test plan for THAT specific epic/feature. Output: `test-design-epic-N.md`.
|
||||
- Use `*atdd` before coding when the team can adopt ATDD; share its checklist with the dev agent.
|
||||
- Post-implementation, keep `*trace` current, expand coverage with `*automate`, optionally review test quality with `*test-review`. For release gate, run `*trace` with Phase 2 enabled to get deployment decision.
|
||||
- Use `*test-review` after `*atdd` to validate generated tests, after `*automate` to ensure regression quality, or before gate for final audit.
|
||||
- Clarification: `*test-review` is optional and only audits existing tests; run it after `*atdd` or `*automate` when you want a quality review, not as a required step.
|
||||
- Clarification: `*atdd` outputs are not auto-consumed; share the ATDD doc/tests with the dev workflow. `*trace` does not run `*atdd`—it evaluates existing artifacts for coverage and gate readiness.
|
||||
- Clarification: `*ci` is a one-time setup; recommended early (Phase 3 or before feature work), but it can be done later if it was skipped.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Worked Example – “Nova CRM” Greenfield Feature</summary>
|
||||
|
||||
1. **Planning (Phase 2):** Analyst runs `*product-brief`; PM executes `*prd` to produce PRD with FRs/NFRs.
|
||||
2. **Solutioning (Phase 3):** Architect completes `*architecture` for the new module; `*create-epics-and-stories` generates epics/stories based on architecture; TEA sets up test infrastructure via `*framework` and `*ci` based on architectural decisions; gate check validates planning completeness.
|
||||
3. **Sprint Start (Phase 4):** Scrum Master runs `*sprint-planning` to load all epics into sprint status.
|
||||
4. **Epic 1 Planning (Phase 4):** TEA runs `*test-design` to create test plan for Epic 1, producing `test-design-epic-1.md` with risk assessment.
|
||||
5. **Story Implementation (Phase 4):** For each story in Epic 1, SM generates story via `*create-story`; TEA optionally runs `*atdd`; Dev implements with guidance from failing tests.
|
||||
6. **Post-Dev (Phase 4):** TEA runs `*automate`, optionally `*test-review` to audit test quality, re-runs `*trace` to refresh coverage.
|
||||
7. **Release Gate:** TEA runs `*trace` with Phase 2 enabled to generate gate decision.
|
||||
|
||||
</details>
|
||||
|
||||
### Brownfield - BMad Method or Enterprise (Simple or Complex)
|
||||
|
||||
**Planning Tracks:** BMad Method or Enterprise Method
|
||||
**Use Case:** Existing codebases - simple additions (BMad Method) or complex enterprise requirements (Enterprise Method)
|
||||
|
||||
**🔄 Brownfield Deltas from Greenfield:**
|
||||
|
||||
- ➕ Documentation (Prerequisite) - Document existing codebase if undocumented
|
||||
- ➕ Phase 2: `*trace` - Baseline existing test coverage before planning
|
||||
- 🔄 Phase 4: `*test-design` - Focus on regression hotspots and brownfield risks
|
||||
- 🔄 Phase 4: Story Review - May include `*nfr-assess` if not done earlier
|
||||
|
||||
| Workflow Stage | Test Architect | Dev / Team | Outputs |
|
||||
| --------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
||||
| **Documentation**: Prerequisite ➕ | - | Analyst `*document-project` (if undocumented) | Comprehensive project documentation |
|
||||
| **Phase 1**: Discovery | - | Analyst/PM/Architect rerun planning workflows | Updated planning artifacts in `{output_folder}` |
|
||||
| **Phase 2**: Planning | Run ➕ `*trace` (baseline coverage) | PM `*prd` (creates PRD with FRs/NFRs) | PRD with FRs/NFRs, ➕ coverage baseline |
|
||||
| **Phase 3**: Solutioning | Run `*framework`, `*ci` AFTER architecture and epic creation | Architect `*architecture`, `*create-epics-and-stories`, `*implementation-readiness` | Architecture, epics/stories, test framework, CI pipeline |
|
||||
| **Phase 4**: Sprint Start | - | SM `*sprint-planning` | Sprint status file with all epics and stories |
|
||||
| **Phase 4**: Epic Planning | Run `*test-design` for THIS epic 🔄 (regression hotspots) | Review epic scope and brownfield risks | `test-design-epic-N.md` with brownfield risk assessment and mitigation |
|
||||
| **Phase 4**: Story Dev | (Optional) `*atdd` before dev, then `*automate` after | SM `*create-story`, DEV implements | Tests, story implementation |
|
||||
| **Phase 4**: Story Review | Apply `*test-review` (optional), re-run `*trace`, ➕ `*nfr-assess` if needed | Resolve gaps, update docs/tests | Quality report, refreshed coverage matrix, NFR report |
|
||||
| **Phase 4**: Release Gate | (Optional) `*test-review` for final audit, Run `*trace` (Phase 2) | Capture sign-offs, share release notes | Quality audit, Gate YAML + release summary |
|
||||
|
||||
<details>
|
||||
<summary>Execution Notes</summary>
|
||||
|
||||
- Lead with `*trace` during Planning (Phase 2) to baseline existing test coverage before architecture work begins.
|
||||
- **Phase 3 (Solutioning)**: After architecture is complete, run `*framework` and `*ci` to modernize test infrastructure. For brownfield, framework may need to integrate with or replace existing test setup.
|
||||
- **Phase 4 starts**: After solutioning is complete and sprint planning loads all epics.
|
||||
- **`*test-design` runs per-epic**: At the beginning of working on each epic, run `*test-design` to identify regression hotspots, integration risks, and mitigation strategies for THAT specific epic/feature. Output: `test-design-epic-N.md`.
|
||||
- Use `*atdd` when stories benefit from ATDD; otherwise proceed to implementation and rely on post-dev automation.
|
||||
- After development, expand coverage with `*automate`, optionally review test quality with `*test-review`, re-run `*trace` (Phase 2 for gate decision). Run `*nfr-assess` now if non-functional risks weren't addressed earlier.
|
||||
- Use `*test-review` to validate existing brownfield tests or audit new tests before gate.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Worked Example – “Atlas Payments” Brownfield Story</summary>
|
||||
|
||||
1. **Planning (Phase 2):** PM executes `*prd` to create PRD with FRs/NFRs; TEA runs `*trace` to baseline existing coverage.
|
||||
2. **Solutioning (Phase 3):** Architect triggers `*architecture` capturing legacy payment flows and integration architecture; `*create-epics-and-stories` generates Epic 1 (Payment Processing) based on architecture; TEA sets up `*framework` and `*ci` based on architectural decisions; gate check validates planning.
|
||||
3. **Sprint Start (Phase 4):** Scrum Master runs `*sprint-planning` to load Epic 1 into sprint status.
|
||||
4. **Epic 1 Planning (Phase 4):** TEA runs `*test-design` for Epic 1 (Payment Processing), producing `test-design-epic-1.md` that flags settlement edge cases, regression hotspots, and mitigation plans.
|
||||
5. **Story Implementation (Phase 4):** For each story in Epic 1, SM generates story via `*create-story`; TEA runs `*atdd` producing failing Playwright specs; Dev implements with guidance from tests and checklist.
|
||||
6. **Post-Dev (Phase 4):** TEA applies `*automate`, optionally `*test-review` to audit test quality, re-runs `*trace` to refresh coverage.
|
||||
7. **Release Gate:** TEA performs `*nfr-assess` to validate SLAs, runs `*trace` with Phase 2 enabled to generate gate decision (PASS/CONCERNS/FAIL).
|
||||
|
||||
</details>
|
||||
|
||||
### Greenfield - Enterprise Method (Enterprise/Compliance Work)
|
||||
|
||||
**Planning Track:** Enterprise Method (BMad Method + extended security/devops/test strategies)
|
||||
**Use Case:** New enterprise projects with compliance, security, or complex regulatory requirements
|
||||
|
||||
**🏢 Enterprise Deltas from BMad Method:**
|
||||
|
||||
- ➕ Phase 1: `*research` - Domain and compliance research (recommended)
|
||||
- ➕ Phase 2: `*nfr-assess` - Capture NFR requirements early (security/performance/reliability)
|
||||
- 🔄 Phase 4: `*test-design` - Enterprise focus (compliance, security architecture alignment)
|
||||
- 📦 Release Gate - Archive artifacts and compliance evidence for audits
|
||||
|
||||
| Workflow Stage | Test Architect | Dev / Team | Outputs |
|
||||
| -------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
||||
| **Phase 1**: Discovery | - | Analyst ➕ `*research`, `*product-brief` | Domain research, compliance analysis, product brief |
|
||||
| **Phase 2**: Planning | Run ➕ `*nfr-assess` | PM `*prd` (creates PRD with FRs/NFRs), UX `*create-ux-design` | Enterprise PRD with FRs/NFRs, UX design, ➕ NFR documentation |
|
||||
| **Phase 3**: Solutioning | Run `*framework`, `*ci` AFTER architecture and epic creation | Architect `*architecture`, `*create-epics-and-stories`, `*implementation-readiness` | Architecture, epics/stories, test framework, CI pipeline |
|
||||
| **Phase 4**: Sprint Start | - | SM `*sprint-planning` | Sprint plan with all epics |
|
||||
| **Phase 4**: Epic Planning | Run `*test-design` for THIS epic 🔄 (compliance focus) | Review epic scope and compliance requirements | `test-design-epic-N.md` with security/performance/compliance focus |
|
||||
| **Phase 4**: Story Dev | (Optional) `*atdd`, `*automate`, `*test-review`, `*trace` per story | SM `*create-story`, DEV implements | Tests, fixtures, quality reports, coverage matrices |
|
||||
| **Phase 4**: Release Gate | Final `*test-review` audit, Run `*trace` (Phase 2), 📦 archive artifacts | Capture sign-offs, 📦 compliance evidence | Quality audit, updated assessments, gate YAML, 📦 audit trail |
|
||||
|
||||
<details>
|
||||
<summary>Execution Notes</summary>
|
||||
|
||||
- `*nfr-assess` runs early in Planning (Phase 2) to capture compliance, security, and performance requirements upfront.
|
||||
- **Phase 3 (Solutioning)**: After architecture is complete, run `*framework` and `*ci` with enterprise-grade configurations (selective testing, burn-in jobs, caching, notifications).
|
||||
- **Phase 4 starts**: After solutioning is complete and sprint planning loads all epics.
|
||||
- **`*test-design` runs per-epic**: At the beginning of working on each epic, run `*test-design` to create an enterprise-focused test plan for THAT specific epic, ensuring alignment with security architecture, performance targets, and compliance requirements. Output: `test-design-epic-N.md`.
|
||||
- Use `*atdd` for stories when feasible so acceptance tests can lead implementation.
|
||||
- Use `*test-review` per story or sprint to maintain quality standards and ensure compliance with testing best practices.
|
||||
- Prior to release, rerun coverage (`*trace`, `*automate`), perform final quality audit with `*test-review`, and formalize the decision with `*trace` Phase 2 (gate decision); archive artifacts for compliance audits.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Worked Example – “Helios Ledger” Enterprise Release</summary>
|
||||
|
||||
1. **Planning (Phase 2):** Analyst runs `*research` and `*product-brief`; PM completes `*prd` creating PRD with FRs/NFRs; TEA runs `*nfr-assess` to establish NFR targets.
|
||||
2. **Solutioning (Phase 3):** Architect completes `*architecture` with enterprise considerations; `*create-epics-and-stories` generates epics/stories based on architecture; TEA sets up `*framework` and `*ci` with enterprise-grade configurations based on architectural decisions; gate check validates planning completeness.
|
||||
3. **Sprint Start (Phase 4):** Scrum Master runs `*sprint-planning` to load all epics into sprint status.
|
||||
4. **Per-Epic (Phase 4):** For each epic, TEA runs `*test-design` to create epic-specific test plan (e.g., `test-design-epic-1.md`, `test-design-epic-2.md`) with compliance-focused risk assessment.
|
||||
5. **Per-Story (Phase 4):** For each story, TEA uses `*atdd`, `*automate`, `*test-review`, and `*trace`; Dev teams iterate on the findings.
|
||||
6. **Release Gate:** TEA re-checks coverage, performs final quality audit with `*test-review`, and logs the final gate decision via `*trace` Phase 2, archiving artifacts for compliance.
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## TEA Command Catalog
|
||||
|
||||
| Command | Primary Outputs | Notes |
|
||||
| -------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
|
||||
| `*framework` | Playwright/Cypress scaffold, `.env.example`, `.nvmrc`, sample specs | Use when no production-ready harness exists |
|
||||
| `*ci` | CI workflow, selective test scripts, secrets checklist | Platform-aware (GitHub Actions default) |
|
||||
| `*test-design` | Combined risk assessment, mitigation plan, and coverage strategy | Risk scoring + optional exploratory mode |
|
||||
| `*atdd` | Failing acceptance tests + implementation checklist | TDD red phase + optional recording mode |
|
||||
| `*automate` | Prioritized specs, fixtures, README/script updates, DoD summary | Optional healing/recording, avoid duplicate coverage |
|
||||
| `*test-review` | Test quality review report with 0-100 score, violations, fixes | Reviews tests against knowledge base patterns |
|
||||
| `*nfr-assess` | NFR assessment report with actions | Focus on security/performance/reliability |
|
||||
| `*trace` | Phase 1: Coverage matrix, recommendations. Phase 2: Gate decision (PASS/CONCERNS/FAIL/WAIVED) | Two-phase workflow: traceability + gate decision |
|
||||
| Command | Primary Outputs | Notes | With Playwright MCP Enhancements |
|
||||
| -------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `*framework` | Playwright/Cypress scaffold, `.env.example`, `.nvmrc`, sample specs | Use when no production-ready harness exists | - |
|
||||
| `*ci` | CI workflow, selective test scripts, secrets checklist | Platform-aware (GitHub Actions default) | - |
|
||||
| `*test-design` | Combined risk assessment, mitigation plan, and coverage strategy | Risk scoring + optional exploratory mode | **+ Exploratory**: Interactive UI discovery with browser automation (uncover actual functionality) |
|
||||
| `*atdd` | Failing acceptance tests + implementation checklist | TDD red phase + optional recording mode | **+ Recording**: AI generation verified with live browser (accurate selectors from real DOM) |
|
||||
| `*automate` | Prioritized specs, fixtures, README/script updates, DoD summary | Optional healing/recording, avoid duplicate coverage | **+ Healing**: Pattern fixes enhanced with visual debugging + **+ Recording**: AI verified with live browser |
|
||||
| `*test-review` | Test quality review report with 0-100 score, violations, fixes | Reviews tests against knowledge base patterns | - |
|
||||
| `*nfr-assess` | NFR assessment report with actions | Focus on security/performance/reliability | - |
|
||||
| `*trace` | Phase 1: Coverage matrix, recommendations. Phase 2: Gate decision (PASS/CONCERNS/FAIL/WAIVED) | Two-phase workflow: traceability + gate decision | - |
|
||||
|
||||
---
|
||||
|
||||
## Playwright Utils Integration
|
||||
|
||||
TEA optionally integrates with `@seontechnologies/playwright-utils`, an open-source library providing fixture-based utilities for Playwright tests. This integration enhances TEA's test generation and review workflows with production-ready patterns.
|
||||
|
||||
<details>
|
||||
<summary><strong>Installation & Configuration</strong></summary>
|
||||
|
||||
**Package**: `@seontechnologies/playwright-utils` ([npm](https://www.npmjs.com/package/@seontechnologies/playwright-utils) | [GitHub](https://github.com/seontechnologies/playwright-utils))
|
||||
|
||||
**Install**: `npm install -D @seontechnologies/playwright-utils`
|
||||
|
||||
**Enable during BMAD installation** by answering "Yes" when prompted, or manually set `tea_use_playwright_utils: true` in `_bmad/bmm/config.yaml`.
|
||||
|
||||
**To disable**: Set `tea_use_playwright_utils: false` in `_bmad/bmm/config.yaml`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>How Playwright Utils Enhances TEA Workflows</strong></summary>
|
||||
|
||||
1. `*framework`:
|
||||
- Default: Basic Playwright scaffold
|
||||
- **+ playwright-utils**: Scaffold with api-request, network-recorder, auth-session, burn-in, network-error-monitor fixtures pre-configured
|
||||
|
||||
Benefit: Production-ready patterns from day one
|
||||
|
||||
2. `*automate`, `*atdd`:
|
||||
- Default: Standard test patterns
|
||||
- **+ playwright-utils**: Tests using api-request (schema validation), intercept-network-call (mocking), recurse (polling), log (structured logging), file-utils (CSV/PDF)
|
||||
|
||||
Benefit: Advanced patterns without boilerplate
|
||||
|
||||
3. `*test-review`:
|
||||
- Default: Reviews against core knowledge base (22 fragments)
|
||||
- **+ playwright-utils**: Reviews against expanded knowledge base (33 fragments: 22 core + 11 playwright-utils)
|
||||
|
||||
Benefit: Reviews include fixture composition, auth patterns, network recording best practices
|
||||
|
||||
4. `*ci`:
|
||||
- Default: Standard CI workflow
|
||||
- **+ playwright-utils**: CI workflow with burn-in script (smart test selection) and network-error-monitor integration
|
||||
|
||||
Benefit: Faster CI feedback, HTTP error detection
|
||||
|
||||
**Utilities available** (10 total): api-request, network-recorder, auth-session, intercept-network-call, recurse, log, file-utils, burn-in, network-error-monitor, fixtures-composition
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## Playwright MCP Enhancements
|
||||
|
||||
TEA can leverage Playwright MCP servers to enhance test generation with live browser verification. MCP provides interactive capabilities on top of TEA's default AI-based approach.
|
||||
|
||||
<details>
|
||||
<summary><strong>MCP Server Configuration</strong></summary>
|
||||
|
||||
**Two Playwright MCP servers** (actively maintained, continuously updated):
|
||||
|
||||
- `playwright` - Browser automation (`npx @playwright/mcp@latest`)
|
||||
- `playwright-test` - Test runner with failure analysis (`npx playwright run-test-mcp-server`)
|
||||
|
||||
**Config example**:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"playwright": {
|
||||
"command": "npx",
|
||||
"args": ["@playwright/mcp@latest"]
|
||||
},
|
||||
"playwright-test": {
|
||||
"command": "npx",
|
||||
"args": ["playwright", "run-test-mcp-server"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**To disable**: Set `tea_use_mcp_enhancements: false` in `_bmad/bmm/config.yaml` OR remove MCPs from IDE config.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>How MCP Enhances TEA Workflows</strong></summary>
|
||||
|
||||
1. `*test-design`:
|
||||
- Default: Analysis + documentation
|
||||
- **+ MCP**: Interactive UI discovery with `browser_navigate`, `browser_click`, `browser_snapshot`, behavior observation
|
||||
|
||||
Benefit: Discover actual functionality, edge cases, undocumented features
|
||||
|
||||
2. `*atdd`, `*automate`:
|
||||
- Default: Infers selectors and interactions from requirements and knowledge fragments
|
||||
- **+ MCP**: Generates tests **then** verifies with `generator_setup_page`, `browser_*` tools, validates against live app
|
||||
|
||||
Benefit: Accurate selectors from real DOM, verified behavior, refined test code
|
||||
|
||||
3. `*automate` (healing mode):
|
||||
- Default: Pattern-based fixes from error messages + knowledge fragments
|
||||
- **+ MCP**: Pattern fixes **enhanced with** `browser_snapshot`, `browser_console_messages`, `browser_network_requests`, `browser_generate_locator`
|
||||
|
||||
Benefit: Visual failure context, live DOM inspection, root cause discovery
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Setup Test Framework](../../how-to/workflows/setup-test-framework.md) - How to set up testing infrastructure
|
||||
- [Run Test Design](../../how-to/workflows/run-test-design.md) - Creating test plans
|
||||
- [Setup Test Framework](/docs/how-to/workflows/setup-test-framework.md) - How to set up testing infrastructure
|
||||
- [Run Test Design](/docs/how-to/workflows/run-test-design.md) - Creating test plans
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ title: "Web Bundles"
|
|||
---
|
||||
|
||||
|
||||
Use BMAD agents in Gemini Gems and Custom GPTs.
|
||||
Use BMad agents in Gemini Gems and Custom GPTs.
|
||||
|
||||
## Status
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ Web bundles package BMad agents as self-contained files that work in Gemini Gems
|
|||
|
||||
**Perfect for:**
|
||||
- Uploading a single file to a Gemini GEM or Custom GPT
|
||||
- Using BMAD Method from the Web
|
||||
- Using BMad Method from the Web
|
||||
- Cost savings (generally lower cost than local usage)
|
||||
- Quick sharing of agent configurations
|
||||
|
||||
|
|
@ -33,5 +33,3 @@ Web bundles package BMad agents as self-contained files that work in Gemini Gems
|
|||
- Some quality reduction vs local usage
|
||||
- Less convenient than full local installation
|
||||
- Limited to agent capabilities (no workflow file access)
|
||||
|
||||
[← Back to Core Concepts](../index.md)
|
||||
|
|
|
|||
|
|
@ -405,6 +405,6 @@ The `project-context.md` file (if present) serves as the authoritative source fo
|
|||
|
||||
## Next Steps
|
||||
|
||||
- **[Quick Start Guide](../../tutorials/getting-started/quick-start-bmgd.md)** - Get started with BMGD
|
||||
- **[Workflows Guide](../../reference/workflows/index.md)** - Detailed workflow reference
|
||||
- **[Game Types Guide](../../explanation/game-dev/game-types.md)** - Game type templates
|
||||
- **[Quick Start Guide](/docs/tutorials/getting-started/quick-start-bmgd.md)** - Get started with BMGD
|
||||
- **[Workflows Guide](/docs/reference/workflows/index.md)** - Detailed workflow reference
|
||||
- **[Game Types Guide](/docs/explanation/game-dev/game-types.md)** - Game type templates
|
||||
|
|
|
|||
|
|
@ -145,6 +145,6 @@ This means you get all of BMM's implementation structure plus game-specific enha
|
|||
|
||||
## Related
|
||||
|
||||
- [BMGD Overview](./index.md) - Getting started with BMGD
|
||||
- [Game Types Guide](./game-types.md) - Understanding game templates
|
||||
- [Quick Start BMGD](../../tutorials/getting-started/quick-start-bmgd.md) - Tutorial
|
||||
- [BMGD Overview](/docs/explanation/game-dev/index.md) - Getting started with BMGD
|
||||
- [Game Types Guide](/docs/explanation/game-dev/game-types.md) - Understanding game templates
|
||||
- [Quick Start BMGD](/docs/tutorials/getting-started/quick-start-bmgd.md) - Tutorial
|
||||
|
|
|
|||
|
|
@ -501,6 +501,6 @@ When you select a game type, BMGD adds these GDD sections:
|
|||
|
||||
## Next Steps
|
||||
|
||||
- **[Quick Start Guide](../../tutorials/getting-started/quick-start-bmgd.md)** - Get started with BMGD
|
||||
- **[Workflows Guide](../../reference/workflows/bmgd-workflows.md)** - GDD workflow details
|
||||
- **[Glossary](../../reference/glossary/index.md)** - Game development terminology
|
||||
- **[Quick Start Guide](/docs/tutorials/getting-started/quick-start-bmgd.md)** - Get started with BMGD
|
||||
- **[Workflows Guide](/docs/reference/workflows/bmgd-workflows.md)** - GDD workflow details
|
||||
- **[Glossary](/docs/reference/glossary/index.md)** - Game development terminology
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Complete guides for the BMad Game Development Module (BMGD) - AI-powered workflo
|
|||
|
||||
**New to BMGD?** Start here:
|
||||
|
||||
- **[Quick Start Guide](../../tutorials/getting-started/quick-start-bmgd.md)** - Get started building your first game
|
||||
- **[Quick Start Guide](/docs/tutorials/getting-started/quick-start-bmgd.md)** - Get started building your first game
|
||||
- Installation and setup
|
||||
- Understanding the game development phases
|
||||
- Running your first workflows
|
||||
|
|
@ -24,8 +24,8 @@ Complete guides for the BMad Game Development Module (BMGD) - AI-powered workflo
|
|||
|
||||
## Core Documentation
|
||||
|
||||
- **[Game Types Guide](./game-types.md)** - Selecting and using game type templates (24 supported types)
|
||||
- **[BMGD vs BMM](./bmgd-vs-bmm.md)** - Understanding the differences
|
||||
- **[Game Types Guide](/docs/explanation/game-dev/game-types.md)** - Selecting and using game type templates (24 supported types)
|
||||
- **[BMGD vs BMM](/docs/explanation/game-dev/bmgd-vs-bmm.md)** - Understanding the differences
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ BMGD follows four phases aligned with game development:
|
|||
### I need to...
|
||||
|
||||
**Start a new game project**
|
||||
→ Start with [Quick Start Guide](../../tutorials/getting-started/quick-start-bmgd.md)
|
||||
→ Start with [Quick Start Guide](/docs/tutorials/getting-started/quick-start-bmgd.md)
|
||||
→ Run `brainstorm-game` for ideation
|
||||
→ Create a Game Brief with `create-brief`
|
||||
|
||||
|
|
@ -74,12 +74,12 @@ BMGD follows four phases aligned with game development:
|
|||
→ Follow the sprint-based development cycle
|
||||
|
||||
**Quickly test an idea**
|
||||
→ Use [Quick-Flow](../../how-to/workflows/bmgd-quick-flow.md) for rapid prototyping
|
||||
→ Use [Quick-Flow](/docs/how-to/workflows/bmgd-quick-flow.md) for rapid prototyping
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [Game Types Guide](./game-types.md) - Understanding game type templates
|
||||
- [BMGD vs BMM](./bmgd-vs-bmm.md) - Comparison with core method
|
||||
- [Glossary](../../reference/glossary/index.md) - Terminology reference
|
||||
- [Game Types Guide](/docs/explanation/game-dev/game-types.md) - Understanding game type templates
|
||||
- [BMGD vs BMM](/docs/explanation/game-dev/bmgd-vs-bmm.md) - Comparison with core method
|
||||
- [Glossary](/docs/reference/glossary/index.md) - Terminology reference
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
title: "Explanation"
|
||||
---
|
||||
|
||||
|
||||
Understanding-oriented content that explains concepts, architecture, and the reasoning behind BMAD's design.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
Foundational concepts you need to understand BMAD.
|
||||
|
||||
- [What are Agents?](./core-concepts/what-are-agents.md)
|
||||
- [What are Workflows?](./core-concepts/what-are-workflows.md)
|
||||
- [What are Modules?](./core-concepts/what-are-modules.md)
|
||||
|
||||
## Architecture
|
||||
|
||||
How BMAD is designed and why.
|
||||
|
||||
## Philosophy
|
||||
|
||||
The thinking behind BMAD's approach.
|
||||
|
||||
## Features
|
||||
|
||||
Deep dives into specific BMAD features.
|
||||
|
||||
- [Party Mode](./features/party-mode.md)
|
||||
- [Brainstorming Techniques](./features/brainstorming-techniques.md)
|
||||
- [Advanced Elicitation](./features/advanced-elicitation.md)
|
||||
- [Web Bundles](./features/web-bundles.md)
|
||||
|
||||
## Modules
|
||||
|
||||
Explanations of BMAD's module ecosystem.
|
||||
|
|
@ -117,5 +117,5 @@ But the core creative work happens through facilitated discovery.
|
|||
|
||||
## Related
|
||||
|
||||
- [Creative Intelligence Suite](../creative-intelligence/index.md) - CIS overview
|
||||
- [Brainstorming Techniques](../features/brainstorming-techniques.md) - Available techniques
|
||||
- [Creative Intelligence Suite](/docs/explanation/creative-intelligence/index.md) - CIS overview
|
||||
- [Brainstorming Techniques](/docs/explanation/features/brainstorming-techniques.md) - Available techniques
|
||||
|
|
|
|||
|
|
@ -86,6 +86,6 @@ Follow the standard Phase 4 implementation workflows:
|
|||
|
||||
## Related
|
||||
|
||||
- [Brownfield Development Guide](./index.md)
|
||||
- [Document Existing Project](./document-existing-project.md)
|
||||
- [Quick Fix in Brownfield](./quick-fix-in-brownfield.md)
|
||||
- [Brownfield Development Guide](/docs/how-to/brownfield/index.md)
|
||||
- [Document Existing Project](/docs/how-to/brownfield/document-existing-project.md)
|
||||
- [Quick Fix in Brownfield](/docs/how-to/brownfield/quick-fix-in-brownfield.md)
|
||||
|
|
|
|||
|
|
@ -80,5 +80,5 @@ Review the documentation for:
|
|||
|
||||
## Related
|
||||
|
||||
- [Brownfield Development Guide](./index.md)
|
||||
- [Add Feature to Existing Project](./add-feature-to-existing.md)
|
||||
- [Brownfield Development Guide](/docs/how-to/brownfield/index.md)
|
||||
- [Add Feature to Existing Project](/docs/how-to/brownfield/add-feature-to-existing.md)
|
||||
|
|
|
|||
|
|
@ -89,14 +89,14 @@ Pay close attention here to prevent reinventing the wheel or making decisions th
|
|||
|
||||
## Next Steps
|
||||
|
||||
- **[Document Existing Project](../../how-to/brownfield/document-existing-project.md)** - How to document your brownfield codebase
|
||||
- **[Add Feature to Existing Project](../../how-to/brownfield/add-feature-to-existing.md)** - Adding new functionality
|
||||
- **[Quick Fix in Brownfield](../../how-to/brownfield/quick-fix-in-brownfield.md)** - Bug fixes and ad-hoc changes
|
||||
- **[Brownfield FAQ](../../explanation/faq/brownfield-faq.md)** - Common questions about brownfield development
|
||||
- **[Document Existing Project](/docs/how-to/brownfield/document-existing-project.md)** - How to document your brownfield codebase
|
||||
- **[Add Feature to Existing Project](/docs/how-to/brownfield/add-feature-to-existing.md)** - Adding new functionality
|
||||
- **[Quick Fix in Brownfield](/docs/how-to/brownfield/quick-fix-in-brownfield.md)** - Bug fixes and ad-hoc changes
|
||||
- **[Brownfield FAQ](/docs/explanation/faq/brownfield-faq.md)** - Common questions about brownfield development
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Getting started with BMM
|
||||
- [Quick Spec Flow](../../explanation/features/quick-flow.md) - Fast path for small changes
|
||||
- [Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md) - Getting started with BMM
|
||||
- [Quick Spec Flow](/docs/explanation/features/quick-flow.md) - Fast path for small changes
|
||||
|
|
|
|||
|
|
@ -89,6 +89,6 @@ Consider using Quick Flow or full BMad Method when:
|
|||
|
||||
## Related
|
||||
|
||||
- [Brownfield Development Guide](./index.md)
|
||||
- [Add Feature to Existing Project](./add-feature-to-existing.md)
|
||||
- [Quick Spec Flow](../../explanation/features/quick-flow.md)
|
||||
- [Brownfield Development Guide](/docs/how-to/brownfield/index.md)
|
||||
- [Add Feature to Existing Project](/docs/how-to/brownfield/add-feature-to-existing.md)
|
||||
- [Quick Spec Flow](/docs/explanation/features/quick-flow.md)
|
||||
|
|
|
|||
|
|
@ -201,8 +201,8 @@ memories:
|
|||
|
||||
## Next Steps
|
||||
|
||||
- **[Learn about Agents](../../explanation/core-concepts/what-are-agents.md)** - Understand Simple vs Expert agents
|
||||
- **[Agent Creation Guide](../../tutorials/advanced/create-custom-agent.md)** - Build completely custom agents
|
||||
- **[BMM Complete Documentation](../../explanation/bmm/index.md)** - Full BMad Method reference
|
||||
- **[Learn about Agents](/docs/explanation/core-concepts/what-are-agents.md)** - Understand Simple vs Expert agents
|
||||
- **[Agent Creation Guide](/docs/tutorials/advanced/create-custom-agent.md)** - Build completely custom agents
|
||||
- **[BMM Complete Documentation](/docs/explanation/bmm/index.md)** - Full BMad Method reference
|
||||
|
||||
[← Back to Customization](./index.md)
|
||||
[← Back to Customization](/docs/how-to/customization/index.md)
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ Workflow customization will allow you to:
|
|||
|
||||
While workflow customization is in development, you can:
|
||||
|
||||
- **Create Custom Workflows** - Use the BMAD Builder to create entirely new workflows
|
||||
- **Customize Agents** - Modify agent behavior using [Agent Customization](./customize-agents.md)
|
||||
- **Create Custom Workflows** - Use the BMad Builder to create entirely new workflows
|
||||
- **Customize Agents** - Modify agent behavior using [Agent Customization](/docs/how-to/customization/customize-agents.md)
|
||||
- **Provide Feedback** - Share your workflow customization needs with the community
|
||||
|
||||
---
|
||||
|
||||
**In the meantime:** Learn how to [create custom workflows](../../explanation/bmad-builder/index.md) from scratch.
|
||||
**In the meantime:** Learn how to [create custom workflows](/docs/explanation/bmad-builder/index.md) from scratch.
|
||||
|
||||
[← Back to Customization](./index.md)
|
||||
[← Back to Customization](/docs/how-to/customization/index.md)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "BMAD Customization"
|
||||
title: "BMad Customization"
|
||||
---
|
||||
|
||||
|
||||
|
|
@ -9,12 +9,12 @@ Personalize agents and workflows to match your needs.
|
|||
|
||||
| Guide | Description |
|
||||
|-------|-------------|
|
||||
| **[Agent Customization](./customize-agents.md)** | Modify agent behavior without editing core files |
|
||||
| **[Workflow Customization](./customize-workflows.md)** | Customize and optimize workflows |
|
||||
| **[Agent Customization](/docs/how-to/customization/customize-agents.md)** | Modify agent behavior without editing core files |
|
||||
| **[Workflow Customization](/docs/how-to/customization/customize-workflows.md)** | Customize and optimize workflows |
|
||||
|
||||
## Overview
|
||||
|
||||
BMAD provides two main customization approaches:
|
||||
BMad provides two main customization approaches:
|
||||
|
||||
### Agent Customization
|
||||
Modify any agent's persona, name, capabilities, or menu items using `.customize.yaml` files in `_bmad/_config/agents/`. Your customizations persist through updates.
|
||||
|
|
@ -24,6 +24,4 @@ Replace or extend workflow steps to create tailored processes. (Coming soon)
|
|||
|
||||
---
|
||||
|
||||
**Next:** Read the [Agent Customization Guide](./customize-agents.md) to start personalizing your agents.
|
||||
|
||||
[← Back to Core Concepts](../index.md)
|
||||
**Next:** Read the [Agent Customization Guide](/docs/how-to/customization/customize-agents.md) to start personalizing your agents.
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
---
|
||||
title: "How to Get Answers About BMAD"
|
||||
description: Use an LLM to quickly answer your own BMAD questions
|
||||
title: "How to Get Answers About BMad"
|
||||
description: Use an LLM to quickly answer your own BMad questions
|
||||
---
|
||||
|
||||
Point an LLM at BMAD's source files and ask your question. That's the technique—the rest of this guide shows you how.
|
||||
Point an LLM at BMad's source files and ask your question. That's the technique—the rest of this guide shows you how.
|
||||
|
||||
## See It Work
|
||||
|
||||
:::note[Example]
|
||||
**Q:** "Tell me the fastest way to build something with BMAD"
|
||||
**Q:** "Tell me the fastest way to build something with BMad"
|
||||
|
||||
**A:** Use Quick Flow: Run `create-tech-spec` to write a technical specification, then `quick-dev` to implement it—skipping the full planning phases. This gets small features shipped in a single focused session instead of going through the full 4-phase BMM workflow.
|
||||
:::
|
||||
|
||||
## Why This Works
|
||||
|
||||
BMAD's prompts are written in plain English, not code. The `_bmad` folder contains readable instructions, workflows, and agent definitions—exactly what LLMs are good at processing. You're not asking the LLM to guess; you're giving it the actual source material.
|
||||
BMad's prompts are written in plain English, not code. The `_bmad` folder contains readable instructions, workflows, and agent definitions—exactly what LLMs are good at processing. You're not asking the LLM to guess; you're giving it the actual source material.
|
||||
|
||||
## How to Do It
|
||||
|
||||
|
|
@ -23,17 +23,17 @@ BMAD's prompts are written in plain English, not code. The `_bmad` folder contai
|
|||
|
||||
| Source | Best For | Examples |
|
||||
|--------|----------|----------|
|
||||
| **`_bmad` folder** (installed) | How BMAD works in detail—agents, workflows, prompts | "What does the PM agent do?" "How does the PRD workflow work?" |
|
||||
| **`_bmad` folder** (installed) | How BMad works in detail—agents, workflows, prompts | "What does the PM agent do?" "How does the PRD workflow work?" |
|
||||
| **Full GitHub repo** (cloned) | Why things are the way they are—history, installer, architecture | "Why is the installer structured this way?" "What changed in v6?" |
|
||||
| **`llms-full.txt`** | Quick overview from documentation perspective | "Explain BMAD's four phases" "What's the difference between levels?" |
|
||||
| **`llms-full.txt`** | Quick overview from documentation perspective | "Explain BMad's four phases" "What's the difference between levels?" |
|
||||
|
||||
:::note[What's `_bmad`?]
|
||||
The `_bmad` folder is created when you install BMAD. It contains all the agent definitions, workflows, and prompts. If you don't have this folder yet, you haven't installed BMAD—see the "clone the repo" option below.
|
||||
The `_bmad` folder is created when you install BMad. It contains all the agent definitions, workflows, and prompts. If you don't have this folder yet, you haven't installed BMad—see the "clone the repo" option below.
|
||||
:::
|
||||
|
||||
### If Your AI Can Read Files (Claude Code, Cursor, etc.)
|
||||
|
||||
**BMAD installed:** Point your LLM at the `_bmad` folder and ask directly.
|
||||
**BMad installed:** Point your LLM at the `_bmad` folder and ask directly.
|
||||
|
||||
**Want deeper context:** Clone the [full repo](https://github.com/bmad-code-org/BMAD-METHOD) for git history and installer details.
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ Fetch `llms-full.txt` into your session:
|
|||
https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt
|
||||
```
|
||||
|
||||
You can also find this and other downloadable resources on the [Downloads page](/downloads).
|
||||
You can also find this and other downloadable resources on the [Downloads page](/docs/downloads.md).
|
||||
|
||||
:::tip[Verify Surprising Answers]
|
||||
LLMs occasionally get things wrong. If an answer seems off, check the source file it referenced or ask on Discord.
|
||||
|
|
@ -66,7 +66,7 @@ Tried the LLM approach and still need help? You now have a much better question
|
|||
|
||||
## Found a Bug?
|
||||
|
||||
If it's clearly a bug in BMAD itself, skip Discord and go straight to GitHub Issues:
|
||||
If it's clearly a bug in BMad itself, skip Discord and go straight to GitHub Issues:
|
||||
|
||||
**GitHub Issues:** [github.com/bmad-code-org/BMAD-METHOD/issues](https://github.com/bmad-code-org/BMAD-METHOD/issues)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
---
|
||||
title: "How-To Guides"
|
||||
---
|
||||
|
||||
|
||||
Task-oriented guides that show you how to accomplish specific goals. Each guide assumes you already understand the basics.
|
||||
|
||||
## Installation
|
||||
|
||||
- [Upgrade to V6](./installation/upgrade-to-v6.md)
|
||||
- [Install Custom Modules](./installation/install-custom-modules.md)
|
||||
|
||||
## IDE Setup
|
||||
|
||||
*Coming soon*
|
||||
|
||||
## Customization
|
||||
|
||||
- [Customize Agents](./customization/customize-agents.md)
|
||||
- [Customize Workflows](./customization/customize-workflows.md)
|
||||
- [Vendor Workflows](./customization/vendor-workflows.md)
|
||||
- [Shard Large Documents](./customization/shard-large-documents.md)
|
||||
|
||||
## Workflows
|
||||
|
||||
Guides for running specific BMAD workflows.
|
||||
|
||||
## Brownfield Projects
|
||||
|
||||
Working with existing codebases.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Solutions to common problems.
|
||||
|
||||
- [Get Answers About BMAD](./get-answers-about-bmad.md)
|
||||
|
|
@ -10,6 +10,6 @@ How-to guides for installing and configuring the BMad Method.
|
|||
|
||||
| Guide | Description |
|
||||
|-------|-------------|
|
||||
| **[Install BMad](./install-bmad.md)** | Step-by-step installation instructions |
|
||||
| **[Install Custom Modules](./install-custom-modules.md)** | Add custom agents, workflows, and modules |
|
||||
| **[Upgrade to v6](./upgrade-to-v6.md)** | Migrate from BMad v4 to v6 |
|
||||
| **[Install BMad](/docs/how-to/installation/install-bmad.md)** | Step-by-step installation instructions |
|
||||
| **[Install Custom Modules](/docs/how-to/installation/install-custom-modules.md)** | Add custom agents, workflows, and modules |
|
||||
| **[Upgrade to v6](/docs/how-to/installation/upgrade-to-v6.md)** | Migrate from BMad v4 to v6 |
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
title: "How to Install BMAD"
|
||||
description: Step-by-step guide to installing BMAD in your project
|
||||
title: "How to Install BMad"
|
||||
description: Step-by-step guide to installing BMad in your project
|
||||
---
|
||||
|
||||
|
||||
Complete guide to installing BMAD in your project.
|
||||
Complete guide to installing BMad in your project.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ npx bmad-method install
|
|||
|
||||
### 2. Choose Installation Location
|
||||
|
||||
The installer will ask where to install BMAD files. Options:
|
||||
The installer will ask where to install BMad files. Options:
|
||||
- Current directory (recommended for new projects)
|
||||
- Subdirectory
|
||||
- Custom path
|
||||
|
|
@ -39,7 +39,7 @@ Choose which AI tools you'll be using:
|
|||
- Windsurf
|
||||
- Other
|
||||
|
||||
The installer configures BMAD for your selected tools.
|
||||
The installer configures BMad for your selected tools.
|
||||
|
||||
### 4. Choose Modules
|
||||
|
||||
|
|
@ -133,6 +133,6 @@ npx bmad-method install --verbose
|
|||
|
||||
## Related
|
||||
|
||||
- [Quick Start Guide](../../tutorials/getting-started/getting-started-bmadv6.md) - Getting started with BMM
|
||||
- [Upgrade to V6](./upgrade-to-v6.md) - Upgrading from previous versions
|
||||
- [Install Custom Modules](./install-custom-modules.md) - Adding custom content
|
||||
- [Quick Start Guide](/docs/tutorials/getting-started/getting-started-bmadv6.md) - Getting started with BMM
|
||||
- [Upgrade to V6](/docs/how-to/installation/upgrade-to-v6.md) - Upgrading from previous versions
|
||||
- [Install Custom Modules](/docs/how-to/installation/install-custom-modules.md) - Adding custom content
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ title: "Custom Content Installation"
|
|||
---
|
||||
|
||||
|
||||
This guide explains how to create and install custom BMAD content including agents, workflows, and modules. Custom content extends BMAD's functionality with specialized tools and workflows that can be shared across projects or teams.
|
||||
This guide explains how to create and install custom BMad content including agents, workflows, and modules. Custom content extends BMad's functionality with specialized tools and workflows that can be shared across projects or teams.
|
||||
|
||||
For detailed information about the different types of custom content available, see [Custom Content Types](../../explanation/bmad-builder/custom-content-types.md).
|
||||
For detailed information about the different types of custom content available, see [Custom Content Types](/docs/explanation/bmad-builder/custom-content-types.md).
|
||||
|
||||
You can find example custom modules in the `samples/sample-custom-modules/` folder of the repository. Download either of the sample folders to try them out.
|
||||
|
||||
## Content Types Overview
|
||||
|
||||
BMAD Core supports several categories of custom content:
|
||||
BMad Core supports several categories of custom content:
|
||||
|
||||
- Custom Stand Alone Modules
|
||||
- Custom Add On Modules
|
||||
|
|
@ -100,17 +100,17 @@ Ensure your content follows the proper conventions and includes a `module.yaml`
|
|||
|
||||
### New Project Installation
|
||||
|
||||
When setting up a new BMAD project:
|
||||
When setting up a new BMad project:
|
||||
|
||||
1. The installer will prompt: `Would you like to install a local custom module (this includes custom agents and workflows also)? (y/N)`
|
||||
2. Select 'y' to specify the path to your module folder containing `module.yaml`
|
||||
|
||||
### Existing Project Modification
|
||||
|
||||
To add custom content to an existing BMAD project:
|
||||
To add custom content to an existing BMad project:
|
||||
|
||||
1. Run the installer against your project location
|
||||
2. Select `Modify BMAD Installation`
|
||||
2. Select `Modify BMad Installation`
|
||||
3. Choose the option to add, modify, or update custom modules
|
||||
|
||||
### Upcoming Features
|
||||
|
|
@ -120,7 +120,7 @@ To add custom content to an existing BMAD project:
|
|||
|
||||
## Quick Updates
|
||||
|
||||
When updates to BMAD Core or core modules (BMM, CIS, etc.) become available, the quick update process will:
|
||||
When updates to BMad Core or core modules (BMM, CIS, etc.) become available, the quick update process will:
|
||||
|
||||
1. Apply available updates to core modules
|
||||
2. Recompile all agents with customizations from the `_config/agents` folder
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
---
|
||||
title: "BMad v4 to v6 Upgrade Guide"
|
||||
title: "Upgrading from Previous Versions"
|
||||
---
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
BMad v6 represents a complete ground-up rewrite with significant architectural changes. This guide will help you migrate your v4 project to v6.
|
||||
The latest version of BMad represents a complete ground-up rewrite with significant architectural changes. This guide will help you migrate from version 4.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ persona:
|
|||
- Always upbeat and adventurous
|
||||
```
|
||||
|
||||
There is a lot more that is possible with agent customization, which is covered in detail in the [Agent Customization Guide](../customization/customize-agents.md)
|
||||
There is a lot more that is possible with agent customization, which is covered in detail in the [Agent Customization Guide](/docs/how-to/customization/customize-agents.md)
|
||||
|
||||
CRITICAL NOTE: After you modify the customization file, you need to run the npx installer against your installed location, and choose the option to rebuild all agents, or just do a quick update again. This always builds agents fresh and applies customizations.
|
||||
|
||||
|
|
|
|||
|
|
@ -256,6 +256,6 @@ When reporting issues, include:
|
|||
|
||||
## Next Steps
|
||||
|
||||
- **[Quick Start Guide](../../tutorials/getting-started/quick-start-bmgd.md)** - Getting started
|
||||
- **[Workflows Guide](../../reference/workflows/index.md)** - Workflow reference
|
||||
- **[Glossary](../../reference/glossary/index.md)** - Terminology
|
||||
- **[Quick Start Guide](/docs/tutorials/getting-started/quick-start-bmgd.md)** - Getting started
|
||||
- **[Workflows Guide](/docs/reference/workflows/index.md)** - Workflow reference
|
||||
- **[Glossary](/docs/reference/glossary/index.md)** - Terminology
|
||||
|
|
|
|||
|
|
@ -286,6 +286,6 @@ If quick-dev keeps expanding scope, stop and create proper stories.
|
|||
|
||||
## Next Steps
|
||||
|
||||
- **[Workflows Guide](../../reference/workflows/bmgd-workflows.md)** - Full workflow reference
|
||||
- **[Agents Guide](../../explanation/game-dev/agents.md)** - Agent capabilities
|
||||
- **[Quick Start Guide](../../tutorials/getting-started/quick-start-bmgd.md)** - Getting started with BMGD
|
||||
- **[Workflows Guide](/docs/reference/workflows/bmgd-workflows.md)** - Full workflow reference
|
||||
- **[Agents Guide](/docs/explanation/game-dev/agents.md)** - Agent capabilities
|
||||
- **[Quick Start Guide](/docs/tutorials/getting-started/quick-start-bmgd.md)** - Getting started with BMGD
|
||||
|
|
|
|||
|
|
@ -125,6 +125,6 @@ After research:
|
|||
|
||||
## Related
|
||||
|
||||
- [Run Brainstorming Session](./run-brainstorming-session.md) - Explore ideas before research
|
||||
- [Create Product Brief](./create-product-brief.md) - Capture strategic vision
|
||||
- [Create PRD](./create-prd.md) - Move to formal planning
|
||||
- [Run Brainstorming Session](/docs/how-to/workflows/run-brainstorming-session.md) - Explore ideas before research
|
||||
- [Create Product Brief](/docs/how-to/workflows/create-product-brief.md) - Capture strategic vision
|
||||
- [Create PRD](/docs/how-to/workflows/create-prd.md) - Move to formal planning
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ After architecture:
|
|||
|
||||
## Related
|
||||
|
||||
- [Create PRD](./create-prd.md) - Requirements before architecture
|
||||
- [Create Epics and Stories](./create-epics-and-stories.md) - Next step
|
||||
- [Run Implementation Readiness](./run-implementation-readiness.md) - Gate check
|
||||
- [Why Solutioning Matters](../../explanation/architecture/why-solutioning-matters.md)
|
||||
- [Create PRD](/docs/how-to/workflows/create-prd.md) - Requirements before architecture
|
||||
- [Create Epics and Stories](/docs/how-to/workflows/create-epics-and-stories.md) - Next step
|
||||
- [Run Implementation Readiness](/docs/how-to/workflows/run-implementation-readiness.md) - Gate check
|
||||
- [Why Solutioning Matters](/docs/explanation/architecture/why-solutioning-matters.md)
|
||||
|
|
|
|||
|
|
@ -131,6 +131,6 @@ After creating epics and stories:
|
|||
|
||||
## Related
|
||||
|
||||
- [Create Architecture](./create-architecture.md) - Do this first
|
||||
- [Run Implementation Readiness](./run-implementation-readiness.md) - Gate check
|
||||
- [Run Sprint Planning](./run-sprint-planning.md) - Start implementation
|
||||
- [Create Architecture](/docs/how-to/workflows/create-architecture.md) - Do this first
|
||||
- [Run Implementation Readiness](/docs/how-to/workflows/run-implementation-readiness.md) - Gate check
|
||||
- [Run Sprint Planning](/docs/how-to/workflows/run-sprint-planning.md) - Start implementation
|
||||
|
|
|
|||
|
|
@ -125,6 +125,6 @@ After PRD:
|
|||
|
||||
## Related
|
||||
|
||||
- [Create Product Brief](./create-product-brief.md) - Input for PRD
|
||||
- [Create UX Design](./create-ux-design.md) - Optional UX workflow
|
||||
- [Create Architecture](./create-architecture.md) - Next step after PRD
|
||||
- [Create Product Brief](/docs/how-to/workflows/create-product-brief.md) - Input for PRD
|
||||
- [Create UX Design](/docs/how-to/workflows/create-ux-design.md) - Optional UX workflow
|
||||
- [Create Architecture](/docs/how-to/workflows/create-architecture.md) - Next step after PRD
|
||||
|
|
|
|||
|
|
@ -112,6 +112,6 @@ Planning workflows automatically load the product brief if it exists.
|
|||
|
||||
## Related
|
||||
|
||||
- [Run Brainstorming Session](./run-brainstorming-session.md) - Explore ideas first
|
||||
- [Conduct Research](./conduct-research.md) - Validate ideas
|
||||
- [Create PRD](./create-prd.md) - Next step after product brief
|
||||
- [Run Brainstorming Session](/docs/how-to/workflows/run-brainstorming-session.md) - Explore ideas first
|
||||
- [Conduct Research](/docs/how-to/workflows/conduct-research.md) - Validate ideas
|
||||
- [Create PRD](/docs/how-to/workflows/create-prd.md) - Next step after product brief
|
||||
|
|
|
|||
|
|
@ -114,6 +114,6 @@ Implement email verification flow for new user registrations.
|
|||
|
||||
## Related
|
||||
|
||||
- [Run Sprint Planning](./run-sprint-planning.md) - Initialize tracking
|
||||
- [Implement Story](./implement-story.md) - Next step
|
||||
- [Run Code Review](./run-code-review.md) - After implementation
|
||||
- [Run Sprint Planning](/docs/how-to/workflows/run-sprint-planning.md) - Initialize tracking
|
||||
- [Implement Story](/docs/how-to/workflows/implement-story.md) - Next step
|
||||
- [Run Code Review](/docs/how-to/workflows/run-code-review.md) - After implementation
|
||||
|
|
|
|||
|
|
@ -154,6 +154,6 @@ If your "single change" needs 3+ files, it might be a multi-story feature. Let t
|
|||
|
||||
## Related
|
||||
|
||||
- [Quick Flow](../../explanation/features/quick-flow.md) - Understanding Quick Spec Flow
|
||||
- [Implement Story](./implement-story.md) - After tech spec
|
||||
- [Create PRD](./create-prd.md) - For larger projects needing full BMad Method
|
||||
- [Quick Flow](/docs/explanation/features/quick-flow.md) - Understanding Quick Spec Flow
|
||||
- [Implement Story](/docs/how-to/workflows/implement-story.md) - After tech spec
|
||||
- [Create PRD](/docs/how-to/workflows/create-prd.md) - For larger projects needing full BMad Method
|
||||
|
|
|
|||
|
|
@ -112,6 +112,6 @@ The UX spec feeds into:
|
|||
|
||||
## Related
|
||||
|
||||
- [Create PRD](./create-prd.md) - Create requirements first
|
||||
- [Create Architecture](./create-architecture.md) - Technical design
|
||||
- [Create Epics and Stories](./create-epics-and-stories.md) - Work breakdown
|
||||
- [Create PRD](/docs/how-to/workflows/create-prd.md) - Create requirements first
|
||||
- [Create Architecture](/docs/how-to/workflows/create-architecture.md) - Technical design
|
||||
- [Create Epics and Stories](/docs/how-to/workflows/create-epics-and-stories.md) - Work breakdown
|
||||
|
|
|
|||
|
|
@ -122,6 +122,6 @@ A: Split the story and document the change.
|
|||
|
||||
## Related
|
||||
|
||||
- [Create Story](./create-story.md) - Prepare the story first
|
||||
- [Run Code Review](./run-code-review.md) - After implementation
|
||||
- [Run Sprint Planning](./run-sprint-planning.md) - Sprint organization
|
||||
- [Create Story](/docs/how-to/workflows/create-story.md) - Prepare the story first
|
||||
- [Run Code Review](/docs/how-to/workflows/run-code-review.md) - After implementation
|
||||
- [Run Sprint Planning](/docs/how-to/workflows/run-sprint-planning.md) - Sprint organization
|
||||
|
|
|
|||
|
|
@ -89,6 +89,6 @@ After brainstorming:
|
|||
|
||||
## Related
|
||||
|
||||
- [Conduct Research](./conduct-research.md) - Validate your ideas
|
||||
- [Create Product Brief](./create-product-brief.md) - Capture strategic vision
|
||||
- [Create PRD](./create-prd.md) - Move to formal planning
|
||||
- [Conduct Research](/docs/how-to/workflows/conduct-research.md) - Validate your ideas
|
||||
- [Create Product Brief](/docs/how-to/workflows/create-product-brief.md) - Capture strategic vision
|
||||
- [Create PRD](/docs/how-to/workflows/create-prd.md) - Move to formal planning
|
||||
|
|
|
|||
|
|
@ -136,6 +136,6 @@ Every story goes through code-review before being marked done. This ensures:
|
|||
|
||||
## Related
|
||||
|
||||
- [Implement Story](./implement-story.md) - Before code review
|
||||
- [Create Story](./create-story.md) - Move to next story
|
||||
- [Run Sprint Planning](./run-sprint-planning.md) - Sprint organization
|
||||
- [Implement Story](/docs/how-to/workflows/implement-story.md) - Before code review
|
||||
- [Create Story](/docs/how-to/workflows/create-story.md) - Move to next story
|
||||
- [Run Sprint Planning](/docs/how-to/workflows/run-sprint-planning.md) - Sprint organization
|
||||
|
|
|
|||
|
|
@ -157,6 +157,6 @@ E-commerce platform → CONCERNS ⚠️
|
|||
|
||||
## Related
|
||||
|
||||
- [Create Architecture](./create-architecture.md) - Architecture workflow
|
||||
- [Create Epics and Stories](./create-epics-and-stories.md) - Work breakdown
|
||||
- [Run Sprint Planning](./run-sprint-planning.md) - Start implementation
|
||||
- [Create Architecture](/docs/how-to/workflows/create-architecture.md) - Architecture workflow
|
||||
- [Create Epics and Stories](/docs/how-to/workflows/create-epics-and-stories.md) - Work breakdown
|
||||
- [Run Sprint Planning](/docs/how-to/workflows/run-sprint-planning.md) - Start implementation
|
||||
|
|
|
|||
|
|
@ -106,6 +106,6 @@ Stories move through these states in the sprint status file:
|
|||
|
||||
## Related
|
||||
|
||||
- [Create Story](./create-story.md) - Prepare stories for implementation
|
||||
- [Implement Story](./implement-story.md) - Dev workflow
|
||||
- [Run Code Review](./run-code-review.md) - Quality assurance
|
||||
- [Create Story](/docs/how-to/workflows/create-story.md) - Prepare stories for implementation
|
||||
- [Implement Story](/docs/how-to/workflows/implement-story.md) - Dev workflow
|
||||
- [Run Code Review](/docs/how-to/workflows/run-code-review.md) - Quality assurance
|
||||
|
|
|
|||
|
|
@ -123,6 +123,6 @@ TEA generates a comprehensive test design document.
|
|||
|
||||
## Related
|
||||
|
||||
- [TEA Overview](../../explanation/features/tea-overview.md) - Understanding the Test Architect
|
||||
- [Setup Test Framework](./setup-test-framework.md) - Setting up testing infrastructure
|
||||
- [Create Architecture](./create-architecture.md) - Architecture workflow
|
||||
- [TEA Overview](/docs/explanation/features/tea-overview.md) - Understanding the Test Architect
|
||||
- [Setup Test Framework](/docs/how-to/workflows/setup-test-framework.md) - Setting up testing infrastructure
|
||||
- [Create Architecture](/docs/how-to/workflows/create-architecture.md) - Architecture workflow
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ description: How to set up and use Party Mode for multi-agent collaboration
|
|||
---
|
||||
|
||||
|
||||
Use Party Mode to orchestrate dynamic multi-agent conversations with your entire BMAD team.
|
||||
Use Party Mode to orchestrate dynamic multi-agent conversations with your entire BMad team.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -113,5 +113,5 @@ Type "exit" or "done" to conclude the session. Participating agents will say per
|
|||
|
||||
## Related
|
||||
|
||||
- [Party Mode](../../explanation/features/party-mode.md) - Understanding Party Mode
|
||||
- [Agent Roles](../../explanation/core-concepts/agent-roles.md) - Available agents
|
||||
- [Party Mode](/docs/explanation/features/party-mode.md) - Understanding Party Mode
|
||||
- [Agent Roles](/docs/explanation/core-concepts/agent-roles.md) - Available agents
|
||||
|
|
|
|||
|
|
@ -108,6 +108,6 @@ Configure in your IDE's MCP settings.
|
|||
|
||||
## Related
|
||||
|
||||
- [TEA Overview](../../explanation/features/tea-overview.md) - Understanding the Test Architect
|
||||
- [Run Test Design](./run-test-design.md) - Creating test plans
|
||||
- [Create Architecture](./create-architecture.md) - Architecture workflow
|
||||
- [TEA Overview](/docs/explanation/features/tea-overview.md) - Understanding the Test Architect
|
||||
- [Run Test Design](/docs/how-to/workflows/run-test-design.md) - Creating test plans
|
||||
- [Create Architecture](/docs/how-to/workflows/create-architecture.md) - Architecture workflow
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
title: Welcome to BMad
|
||||
title: Welcome to the BMad Method
|
||||
---
|
||||
|
||||
BMad (**B**uild **M**ore, **A**rchitect **D**reams) is an AI-driven development framework that helps you build software faster and smarter. It provides specialized AI agents, guided workflows, and intelligent planning that adapts to your project's complexity—whether you're fixing a bug or building an enterprise platform.
|
||||
The BMad Method (**B**reakthrough **M**ethod of **A**gile AI **D**riven Development) is an AI-driven development framework that helps you build software faster and smarter. It provides specialized AI agents, guided workflows, and intelligent planning that adapts to your project's complexity—whether you're fixing a bug or building an enterprise platform.
|
||||
|
||||
If you're comfortable working with AI coding assistants like Claude, Cursor, or GitHub Copilot, you're ready to get started.
|
||||
|
||||
|
|
@ -12,11 +12,10 @@ If you're comfortable working with AI coding assistants like Claude, Cursor, or
|
|||
|
||||
The fastest way to understand BMad is to try it. Choose a tutorial to walk through your first project in about 10 minutes.
|
||||
|
||||
- **[Get Started with v4 (Stable)](./tutorials/getting-started/getting-started-bmadv4.md)** — Production-ready version with battle-tested workflows
|
||||
- **[Try v6 (Alpha)](./tutorials/getting-started/getting-started-bmadv6.md)** — Latest features, still in active development
|
||||
- **[Get Started with BMad](/docs/tutorials/getting-started/getting-started-bmadv6.md)** — Latest features, still in active development
|
||||
|
||||
:::tip[Already familiar with AI-assisted development?]
|
||||
Feel free to skip around. Use the sidebar to jump to any topic, or check out [What Are Agents?](./explanation/core-concepts/what-are-agents.md) to understand how BMad organizes its AI personas.
|
||||
Feel free to skip around. Use the sidebar to jump to any topic, or check out [What Are Agents?](/docs/explanation/core-concepts/what-are-agents.md) to understand how BMad organizes its AI personas.
|
||||
:::
|
||||
|
||||
---
|
||||
|
|
@ -26,11 +25,11 @@ Feel free to skip around. Use the sidebar to jump to any topic, or check out [Wh
|
|||
These docs are organized into four sections based on what you're trying to do:
|
||||
|
||||
| Section | Purpose |
|
||||
|---------|---------|
|
||||
| **[Tutorials](./tutorials/index.md)** | Learning-oriented. Step-by-step guides that walk you through building something. Start here if you're new. |
|
||||
| **[How-To Guides](./how-to/index.md)** | Task-oriented. Practical guides for solving specific problems. "How do I customize an agent?" lives here. |
|
||||
| **[Explanation](./explanation/index.md)** | Understanding-oriented. Deep dives into concepts and architecture. Read when you want to know *why*. |
|
||||
| **[Reference](./reference/index.md)** | Information-oriented. Technical specifications for agents, workflows, and configuration. |
|
||||
| ----------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| **Tutorials** | Learning-oriented. Step-by-step guides that walk you through building something. Start here if you're new. |
|
||||
| **How-To Guides** | Task-oriented. Practical guides for solving specific problems. "How do I customize an agent?" lives here. |
|
||||
| **Explanation** | Understanding-oriented. Deep dives into concepts and architecture. Read when you want to know *why*. |
|
||||
| **Reference** | Information-oriented. Technical specifications for agents, workflows, and configuration. |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -61,5 +60,4 @@ Get help, share what you're building, or contribute to BMad:
|
|||
|
||||
Ready to dive in? Pick a tutorial and start building.
|
||||
|
||||
- **[Get Started with v4 (Stable)](./tutorials/getting-started/getting-started-bmadv4.md)** — Recommended for production projects
|
||||
- **[Try v6 (Alpha)](./tutorials/getting-started/getting-started-bmadv6.md)** — Explore the latest features
|
||||
- **[Get Started with BMad](/docs/tutorials/getting-started/getting-started-bmadv6.md)** — Explore the latest features
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ Technical documentation and diagrams.
|
|||
- `*validate-doc` - Review documentation against standards
|
||||
- `*improve-readme` - Review and improve README files
|
||||
- `*explain-concept` - Create clear technical explanations
|
||||
- `*standards-guide` - Show BMAD documentation standards
|
||||
- `*standards-guide` - Show BMad documentation standards
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -137,5 +137,5 @@ Available to all agents:
|
|||
|
||||
## Related
|
||||
|
||||
- [Agent Roles](../../explanation/core-concepts/agent-roles.md) - Understanding agent responsibilities
|
||||
- [What Are Agents](../../explanation/core-concepts/what-are-agents.md) - Foundational concepts
|
||||
- [Agent Roles](/docs/explanation/core-concepts/agent-roles.md) - Understanding agent responsibilities
|
||||
- [What Are Agents](/docs/explanation/core-concepts/what-are-agents.md) - Foundational concepts
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ title: "Core Tasks"
|
|||
---
|
||||
|
||||
|
||||
Core Tasks are reusable task definitions that can be invoked by any BMAD module, workflow, or agent. These tasks provide standardized functionality for common operations.
|
||||
Core Tasks are reusable task definitions that can be invoked by any BMad module, workflow, or agent. These tasks provide standardized functionality for common operations.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
title: "BMAD Glossary"
|
||||
title: "BMad Glossary"
|
||||
---
|
||||
|
||||
|
||||
Comprehensive terminology reference for the BMAD Method.
|
||||
Comprehensive terminology reference for the BMad Method.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ Comprehensive terminology reference for the BMAD Method.
|
|||
|
||||
## Core Concepts
|
||||
|
||||
### BMAD (Build More, Architect Dreams)
|
||||
### BMad (Breakthrough Method of Agile AI Driven Development)
|
||||
|
||||
AI-driven agile development framework with specialized agents, guided workflows, and scale-adaptive intelligence.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
title: "Reference"
|
||||
---
|
||||
|
||||
|
||||
Information-oriented documentation for looking up facts, specifications, and details.
|
||||
|
||||
## Agents
|
||||
|
||||
Technical reference for all BMAD agents.
|
||||
|
||||
## Workflows
|
||||
|
||||
Technical reference for all BMAD workflows.
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration options and settings.
|
||||
|
||||
## Glossary
|
||||
|
||||
Definitions of BMAD terminology.
|
||||
|
||||
## FAQ
|
||||
|
||||
Frequently asked questions organized by topic.
|
||||
|
|
@ -262,7 +262,7 @@ Checks current project status across all phases. Shows completed documents, curr
|
|||
|
||||
## Quick-Flow Workflows
|
||||
|
||||
Fast-track workflows that skip full planning phases. See **[Quick-Flow Guide](../../how-to/workflows/bmgd-quick-flow.md)** for detailed usage.
|
||||
Fast-track workflows that skip full planning phases. See **[Quick-Flow Guide](/docs/how-to/workflows/bmgd-quick-flow.md)** for detailed usage.
|
||||
|
||||
### Quick-Prototype
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ This means:
|
|||
|
||||
## Next Steps
|
||||
|
||||
- **[Quick Start Guide](../../tutorials/getting-started/quick-start-bmgd.md)** - Get started with BMGD
|
||||
- **[Quick-Flow Guide](../../how-to/workflows/bmgd-quick-flow.md)** - Rapid prototyping and development
|
||||
- **[Agents Guide](../../explanation/game-dev/agents.md)** - Agent reference
|
||||
- **[Game Types Guide](../../explanation/game-dev/game-types.md)** - Game type templates
|
||||
- **[Quick Start Guide](/docs/tutorials/getting-started/quick-start-bmgd.md)** - Get started with BMGD
|
||||
- **[Quick-Flow Guide](/docs/how-to/workflows/bmgd-quick-flow.md)** - Rapid prototyping and development
|
||||
- **[Agents Guide](/docs/explanation/game-dev/agents.md)** - Agent reference
|
||||
- **[Game Types Guide](/docs/explanation/game-dev/game-types.md)** - Game type templates
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@ title: "Core Workflows"
|
|||
---
|
||||
|
||||
|
||||
Core Workflows are domain-agnostic workflows that can be utilized by any BMAD-compliant module, workflow, or agent. These workflows are installed by default and available at any time.
|
||||
Core Workflows are domain-agnostic workflows that can be utilized by any BMad-compliant module, workflow, or agent. These workflows are installed by default and available at any time.
|
||||
|
||||
## Available Core Workflows
|
||||
|
||||
### [Party Mode](../../explanation/features/party-mode.md)
|
||||
### [Party Mode](/docs/explanation/features/party-mode.md)
|
||||
|
||||
Orchestrate dynamic multi-agent conversations with your entire BMAD team. Engage with multiple specialized perspectives simultaneously—each agent maintaining their unique personality, expertise, and communication style.
|
||||
Orchestrate dynamic multi-agent conversations with your entire BMad team. Engage with multiple specialized perspectives simultaneously—each agent maintaining their unique personality, expertise, and communication style.
|
||||
|
||||
### [Brainstorming](../../explanation/features/brainstorming-techniques.md)
|
||||
### [Brainstorming](/docs/explanation/features/brainstorming-techniques.md)
|
||||
|
||||
Facilitate structured creative sessions using 60+ proven ideation techniques. The AI acts as coach and guide, using proven creativity methods to draw out ideas and insights that are already within you.
|
||||
|
||||
### [Advanced Elicitation](../../explanation/features/advanced-elicitation.md)
|
||||
### [Advanced Elicitation](/docs/explanation/features/advanced-elicitation.md)
|
||||
|
||||
Push the LLM to rethink its work through 50+ reasoning methods—the inverse of brainstorming. The LLM applies sophisticated techniques to re-examine and enhance content it has just generated, essentially "LLM brainstorming" to find better approaches and uncover improvements.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ title: "Document Project Workflow - Technical Reference"
|
|||
---
|
||||
|
||||
|
||||
**Module:** BMM (BMAD Method Module)
|
||||
**Module:** BMM (BMad Method Module)
|
||||
|
||||
## Purpose
|
||||
|
||||
|
|
@ -70,5 +70,5 @@ The workflow can be interrupted and resumed without losing progress:
|
|||
|
||||
**Related Documentation:**
|
||||
|
||||
- [Brownfield Development Guide](../../how-to/brownfield/index.md)
|
||||
- [Implementation Workflows](../../how-to/workflows/run-sprint-planning.md)
|
||||
- [Brownfield Development Guide](/docs/how-to/brownfield/index.md)
|
||||
- [Implementation Workflows](/docs/how-to/workflows/run-sprint-planning.md)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ Complete reference documentation for all BMad Method workflows.
|
|||
|
||||
## Core Workflows
|
||||
|
||||
- [Core Workflows](./core-workflows.md) - Domain-agnostic workflows available to all modules
|
||||
- [Document Project](./document-project.md) - Brownfield project documentation workflow
|
||||
- [Core Workflows](/docs/reference/workflows/core-workflows.md) - Domain-agnostic workflows available to all modules
|
||||
- [Document Project](/docs/reference/workflows/document-project.md) - Brownfield project documentation workflow
|
||||
|
||||
## Module-Specific Workflows
|
||||
|
||||
- [BMGD Workflows](./bmgd-workflows.md) - Game development workflows
|
||||
- [BMGD Workflows](/docs/reference/workflows/bmgd-workflows.md) - Game development workflows
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ title: "Create a Custom Agent"
|
|||
Build your own AI agent with a unique personality, specialized commands, and optional persistent memory using the BMad Builder workflow.
|
||||
|
||||
:::note[BMB Module]
|
||||
This tutorial uses the **BMad Builder (BMB)** module. Make sure you have BMAD installed with the BMB module enabled.
|
||||
This tutorial uses the **BMad Builder (BMB)** module. Make sure you have BMad installed with the BMB module enabled.
|
||||
:::
|
||||
|
||||
## What You'll Learn
|
||||
|
|
@ -18,7 +18,7 @@ This tutorial uses the **BMad Builder (BMB)** module. Make sure you have BMAD in
|
|||
- Test and iterate on your agent's behavior
|
||||
|
||||
:::note[Prerequisites]
|
||||
- BMAD installed with the BMB module
|
||||
- BMad installed with the BMB module
|
||||
- An idea for what you want your agent to do
|
||||
- About 15-30 minutes for your first agent
|
||||
:::
|
||||
|
|
@ -102,7 +102,7 @@ my-custom-stuff/
|
|||
└── workflows/ # Optional: custom workflows
|
||||
```
|
||||
|
||||
Install using the BMAD installer, then invoke your new agent in your IDE.
|
||||
Install using the BMad installer, then invoke your new agent in your IDE.
|
||||
|
||||
## What You've Accomplished
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ _bmad/
|
|||
|
||||
| Action | How |
|
||||
| ------------------- | ---------------------------------------------- |
|
||||
| Start workflow | `"Run the BMAD Builder create-agent workflow"` |
|
||||
| Start workflow | `"Run the BMad Builder create-agent workflow"` |
|
||||
| Edit agent directly | Modify `{agent-name}.agent.yaml` |
|
||||
| Edit customization | Modify `_bmad/_config/agents/{agent-name}` |
|
||||
| Rebuild agent | `npx bmad-method build <agent-name>` |
|
||||
|
|
@ -159,9 +159,9 @@ Study the reference agents in `src/modules/bmb/reference/agents/`:
|
|||
|
||||
## Further Reading
|
||||
|
||||
- **[What Are Agents](../../explanation/core-concepts/what-are-agents.md)** - Deep technical details on agent types
|
||||
- **[Agent Customization](../../how-to/customization/customize-agents.md)** - Modify agents without editing core files
|
||||
- **[Custom Content Installation](../../how-to/installation/install-custom-modules.md)** - Package and distribute your agents
|
||||
- **[What Are Agents](/docs/explanation/core-concepts/what-are-agents.md)** - Deep technical details on agent types
|
||||
- **[Agent Customization](/docs/how-to/customization/customize-agents.md)** - Modify agents without editing core files
|
||||
- **[Custom Content Installation](/docs/how-to/installation/install-custom-modules.md)** - Package and distribute your agents
|
||||
|
||||
:::tip[Key Takeaways]
|
||||
- **Start small** - Your first agent should solve one problem well
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
---
|
||||
title: "Getting Started with BMad v6 Alpha"
|
||||
description: Install BMad v6 Alpha and build your first project
|
||||
title: "Getting Started with the BMad Method"
|
||||
description: Install BMad and build your first project
|
||||
---
|
||||
|
||||
**Upgrading from previous versions?** See the [Upgrade Guide](/docs/how-to/installation/upgrade-to-v6.md) instead.
|
||||
|
||||
---
|
||||
|
||||
Build software faster using AI-powered workflows with specialized agents that guide you through planning, architecture, and implementation.
|
||||
|
||||
:::caution[Alpha Software]
|
||||
BMad v6 is currently in **alpha**. Expect breaking changes, incomplete features, and evolving documentation. For a stable experience, use the [BMad v4 tutorial](./getting-started-bmadv4.md) instead.
|
||||
:::
|
||||
|
||||
## What You'll Learn
|
||||
|
||||
- Install and initialize BMad Method for a new project
|
||||
|
|
@ -37,7 +36,7 @@ BMad v6 is currently in **alpha**. Expect breaking changes, incomplete features,
|
|||
BMad helps you build software through guided workflows with specialized AI agents. The process follows four phases:
|
||||
|
||||
| Phase | Name | What Happens |
|
||||
|-------|------|--------------|
|
||||
| ----- | -------------- | --------------------------------------------------- |
|
||||
| 1 | Analysis | Brainstorming, research, product brief *(optional)* |
|
||||
| 2 | Planning | Create requirements (PRD or tech-spec) |
|
||||
| 3 | Solutioning | Design architecture *(BMad Method/Enterprise only)* |
|
||||
|
|
@ -50,7 +49,7 @@ BMad helps you build software through guided workflows with specialized AI agent
|
|||
Based on your project's complexity, BMad offers three planning tracks:
|
||||
|
||||
| Track | Best For | Documents Created |
|
||||
|-------|----------|-------------------|
|
||||
| --------------- | ------------------------------------------------------ | -------------------------------------- |
|
||||
| **Quick Flow** | Bug fixes, simple features, clear scope (1-15 stories) | Tech-spec only |
|
||||
| **BMad Method** | Products, platforms, complex features (10-50+ stories) | PRD + Architecture + UX |
|
||||
| **Enterprise** | Compliance, multi-tenant systems (30+ stories) | PRD + Architecture + Security + DevOps |
|
||||
|
|
@ -84,7 +83,7 @@ your-project/
|
|||
```
|
||||
|
||||
:::tip[Troubleshooting]
|
||||
Having issues? See [Install BMad](../../how-to/installation/install-bmad.md) for common solutions.
|
||||
Having issues? See [Install BMad](/docs/how-to/installation/install-bmad.md) for common solutions.
|
||||
:::
|
||||
|
||||
## Step 1: Initialize Your Project
|
||||
|
|
@ -167,7 +166,7 @@ Load the **SM agent** and run `sprint-planning`. This creates `sprint-status.yam
|
|||
For each story, repeat this cycle with fresh chats:
|
||||
|
||||
| Step | Agent | Workflow | Purpose |
|
||||
|------|-------|----------|---------|
|
||||
| ---- | ----- | -------------- | ------------------------------------- |
|
||||
| 1 | SM | `create-story` | Create story file from epic |
|
||||
| 2 | DEV | `dev-story` | Implement the story |
|
||||
| 3 | TEA | `automate` | Generate guardrail tests *(optional)* |
|
||||
|
|
@ -201,7 +200,7 @@ your-project/
|
|||
## Quick Reference
|
||||
|
||||
| Command | Agent | Purpose |
|
||||
|---------|-------|---------|
|
||||
| --------------------------- | --------- | ------------------------------------ |
|
||||
| `*workflow-init` | Analyst | Initialize a new project |
|
||||
| `*workflow-status` | Any | Check progress and next steps |
|
||||
| `*prd` | PM | Create Product Requirements Document |
|
||||
|
|
@ -231,7 +230,7 @@ Yes, once you learn the flow. Use the Quick Reference to go directly to needed w
|
|||
|
||||
- **During workflows** — Agents guide you with questions and explanations
|
||||
- **Community** — [Discord](https://discord.gg/gk8jAdXWmj) (#bmad-method-help, #report-bugs-and-issues)
|
||||
- **Documentation** — [BMM Workflow Reference](../../reference/workflows/index.md)
|
||||
- **Documentation** — [BMM Workflow Reference](/docs/reference/workflows/index.md)
|
||||
- **Video tutorials** — [BMad Code YouTube](https://www.youtube.com/@BMadCode)
|
||||
|
||||
## Key Takeaways
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ description: Build games with BMad's Game Development Module
|
|||
Build games faster using AI-powered workflows with specialized game development agents that guide you through preproduction, design, architecture, and implementation.
|
||||
|
||||
:::note[Module Extension]
|
||||
BMGD (BMad Game Development) is a module that extends BMad Method. You'll need BMad installed first—see the [BMad v4 tutorial](./getting-started-bmadv4.md) or [BMad v6 tutorial](./getting-started-bmadv6.md) if you haven't installed it yet.
|
||||
BMGD (BMad Game Development) is a module that extends BMad Method. You'll need BMad installed first—see the [BMad v6 tutorial](/docs/tutorials/getting-started/getting-started-bmadv6.md) if you haven't installed it yet.
|
||||
:::
|
||||
|
||||
## What You'll Learn
|
||||
|
|
@ -37,7 +37,7 @@ BMGD (BMad Game Development) is a module that extends BMad Method. You'll need B
|
|||
BMGD follows four game development phases with specialized agents for each:
|
||||
|
||||
| Phase | Name | What Happens |
|
||||
|-------|------|--------------|
|
||||
| ----- | ------------- | ----------------------------------------------------------------- |
|
||||
| 1 | Preproduction | Capture game vision, create Game Brief *(optional brainstorming)* |
|
||||
| 2 | Design | Detail mechanics, systems, narrative in GDD |
|
||||
| 3 | Technical | Plan engine, architecture, technical decisions |
|
||||
|
|
@ -50,7 +50,7 @@ BMGD follows four game development phases with specialized agents for each:
|
|||
### Game Development Agents
|
||||
|
||||
| Agent | When to Use |
|
||||
|-------|-------------|
|
||||
| --------------------- | ----------------------------------------- |
|
||||
| **Game Designer** | Brainstorming, Game Brief, GDD, Narrative |
|
||||
| **Game Architect** | Architecture, technical decisions |
|
||||
| **Game Developer** | Implementation, code reviews |
|
||||
|
|
@ -172,7 +172,7 @@ Load the **Game Scrum Master** agent and run `sprint-planning`. This creates `sp
|
|||
For each story, repeat this cycle with fresh chats:
|
||||
|
||||
| Step | Agent | Workflow | Purpose |
|
||||
|------|-------|----------|---------|
|
||||
| ---- | -------- | -------------- | ---------------------------------- |
|
||||
| 1 | Game SM | `create-story` | Create story file from epic |
|
||||
| 2 | Game Dev | `dev-story` | Implement the story |
|
||||
| 3 | Game QA | `automate` | Generate tests *(optional)* |
|
||||
|
|
@ -214,7 +214,7 @@ your-project/
|
|||
## Quick Reference
|
||||
|
||||
| Command | Agent | Purpose |
|
||||
|---------|-------|---------|
|
||||
| ---------------------- | -------------- | ----------------------------- |
|
||||
| `*brainstorm-game` | Game Designer | Guided game ideation |
|
||||
| `*create-game-brief` | Game Designer | Create Game Brief |
|
||||
| `*create-gdd` | Game Designer | Create Game Design Document |
|
||||
|
|
@ -244,7 +244,7 @@ Yes. Documents are living artifacts—return to update them as your vision evolv
|
|||
|
||||
- **During workflows** — Agents guide you with questions and explanations
|
||||
- **Community** — [Discord](https://discord.gg/gk8jAdXWmj) (#bmad-method-help, #report-bugs-and-issues)
|
||||
- **Documentation** — [BMGD Workflow Reference](../../reference/workflows/bmgd-workflows.md)
|
||||
- **Documentation** — [BMGD Workflow Reference](/docs/reference/workflows/bmgd-workflows.md)
|
||||
- **Video tutorials** — [BMad Code YouTube](https://www.youtube.com/@BMadCode)
|
||||
|
||||
## Key Takeaways
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
---
|
||||
title: "Tutorials"
|
||||
---
|
||||
|
||||
|
||||
Learning-oriented guides that walk you through building something real with BMad. Perfect for getting hands-on experience.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Start your journey with BMad by choosing a version that fits your needs:
|
||||
|
||||
- [Get Started with v4 (Stable)](./getting-started/getting-started-bmadv4.md) — Production-ready version with battle-tested workflows
|
||||
- [Try v6 (Alpha)](./getting-started/getting-started-bmadv6.md) — Latest features, still in active development
|
||||
|
||||
## First Project
|
||||
|
||||
Your first end-to-end project with BMad.
|
||||
|
||||
## Advanced
|
||||
|
||||
More complex scenarios and advanced patterns.
|
||||
|
|
@ -27,9 +27,10 @@
|
|||
"bmad:install": "node tools/cli/bmad-cli.js install",
|
||||
"bundle": "node tools/cli/bundlers/bundle-web.js all",
|
||||
"docs:build": "node tools/build-docs.js",
|
||||
"docs:check-links": "node tools/check-doc-links.js",
|
||||
"docs:dev": "astro dev --root website",
|
||||
"docs:fix-links": "node tools/fix-doc-links.js",
|
||||
"docs:preview": "astro preview --root website",
|
||||
"docs:validate-links": "node tools/validate-doc-links.js",
|
||||
"flatten": "node tools/flattener/main.js",
|
||||
"format:check": "prettier --check \"**/*.{js,cjs,mjs,json,yaml}\"",
|
||||
"format:fix": "prettier --write \"**/*.{js,cjs,mjs,json,yaml}\"",
|
||||
|
|
|
|||
|
|
@ -12,15 +12,17 @@ agent:
|
|||
|
||||
persona:
|
||||
role: Master Test Architect
|
||||
identity: Test architect specializing in CI/CD, automated frameworks, and scalable quality gates.
|
||||
identity: Test architect specializing in API testing, backend services, UI automation, CI/CD pipelines, and scalable quality gates. Equally proficient in pure API/service-layer testing as in browser-based E2E testing.
|
||||
communication_style: "Blends data with gut instinct. 'Strong opinions, weakly held' is their mantra. Speaks in risk calculations and impact assessments."
|
||||
principles: |
|
||||
- Risk-based testing - depth scales with impact
|
||||
- Quality gates backed by data
|
||||
- Tests mirror usage patterns
|
||||
- Tests mirror usage patterns (API, UI, or both)
|
||||
- Flakiness is critical technical debt
|
||||
- Tests first AI implements suite validates
|
||||
- Calculate risk vs value for every testing decision
|
||||
- Prefer lower test levels (unit > integration > E2E) when possible
|
||||
- API tests are first-class citizens, not just UI support
|
||||
|
||||
critical_actions:
|
||||
- "Consult {project-root}/_bmad/bmm/testarch/tea-index.csv to select knowledge fragments under knowledge/ and load only the files needed for the current task"
|
||||
|
|
@ -39,7 +41,7 @@ agent:
|
|||
|
||||
- trigger: AT or fuzzy match on atdd
|
||||
workflow: "{project-root}/_bmad/bmm/workflows/testarch/atdd/workflow.yaml"
|
||||
description: "[AT] Generate E2E tests first, before starting implementation"
|
||||
description: "[AT] Generate API and/or E2E tests first, before starting implementation"
|
||||
|
||||
- trigger: TA or fuzzy match on test-automate
|
||||
workflow: "{project-root}/_bmad/bmm/workflows/testarch/automate/workflow.yaml"
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ project_knowledge: # Artifacts from research, document-project output, other lon
|
|||
result: "{project-root}/{value}"
|
||||
|
||||
tea_use_mcp_enhancements:
|
||||
prompt: "Test Architect Playwright MCP capabilities (healing, exploratory, verification) are optionally available.\nYou will have to setup your MCPs yourself; refer to test-architecture.md for hints.\nWould you like to enable MCP enhancements in Test Architect?"
|
||||
prompt: "Test Architect Playwright MCP capabilities (healing, exploratory, verification) are optionally available.\nYou will have to setup your MCPs yourself; refer to https://docs.bmad-method.org/explanation/features/tea-overview for configuration examples.\nWould you like to enable MCP enhancements in Test Architect?"
|
||||
default: false
|
||||
result: "{value}"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Principle
|
||||
|
||||
Use typed HTTP client with built-in schema validation and automatic retry for server errors. The utility handles URL resolution, header management, response parsing, and single-line response validation with proper TypeScript support.
|
||||
Use typed HTTP client with built-in schema validation and automatic retry for server errors. The utility handles URL resolution, header management, response parsing, and single-line response validation with proper TypeScript support. **Works without a browser** - ideal for pure API/service testing.
|
||||
|
||||
## Rationale
|
||||
|
||||
|
|
@ -21,6 +21,7 @@ The `apiRequest` utility provides:
|
|||
- **Schema validation**: Single-line validation (JSON Schema, Zod, OpenAPI)
|
||||
- **URL resolution**: Four-tier strategy (explicit > config > Playwright > direct)
|
||||
- **TypeScript generics**: Type-safe response bodies
|
||||
- **No browser required**: Pure API testing without browser overhead
|
||||
|
||||
## Pattern Examples
|
||||
|
||||
|
|
@ -60,10 +61,11 @@ test('should fetch user data', async ({ apiRequest }) => {
|
|||
|
||||
```typescript
|
||||
import { test } from '@seontechnologies/playwright-utils/api-request/fixtures';
|
||||
import { z } from 'zod';
|
||||
|
||||
test('should validate response schema', async ({ apiRequest }) => {
|
||||
// JSON Schema validation
|
||||
const response = await apiRequest({
|
||||
test('should validate response schema (JSON Schema)', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/users/123',
|
||||
validateSchema: {
|
||||
|
|
@ -77,22 +79,25 @@ test('should validate response schema', async ({ apiRequest }) => {
|
|||
},
|
||||
});
|
||||
// Throws if schema validation fails
|
||||
expect(status).toBe(200);
|
||||
});
|
||||
|
||||
// Zod schema validation
|
||||
import { z } from 'zod';
|
||||
|
||||
const UserSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
email: z.string().email(),
|
||||
});
|
||||
|
||||
const response = await apiRequest({
|
||||
test('should validate response schema (Zod)', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/users/123',
|
||||
validateSchema: UserSchema,
|
||||
});
|
||||
// Response body is type-safe AND validated
|
||||
expect(status).toBe(200);
|
||||
expect(body.email).toContain('@');
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -236,6 +241,136 @@ test('should poll until job completes', async ({ apiRequest, recurse }) => {
|
|||
- `recurse` polls until predicate returns true
|
||||
- Composable utilities work together seamlessly
|
||||
|
||||
### Example 6: Microservice Testing (Multiple Services)
|
||||
|
||||
**Context**: Test interactions between microservices without a browser.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@seontechnologies/playwright-utils/fixtures';
|
||||
|
||||
const USER_SERVICE = process.env.USER_SERVICE_URL || 'http://localhost:3001';
|
||||
const ORDER_SERVICE = process.env.ORDER_SERVICE_URL || 'http://localhost:3002';
|
||||
|
||||
test.describe('Microservice Integration', () => {
|
||||
test('should validate cross-service user lookup', async ({ apiRequest }) => {
|
||||
// Create user in user-service
|
||||
const { body: user } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/users',
|
||||
baseUrl: USER_SERVICE,
|
||||
body: { name: 'Test User', email: 'test@example.com' },
|
||||
});
|
||||
|
||||
// Create order in order-service (validates user via user-service)
|
||||
const { status, body: order } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
baseUrl: ORDER_SERVICE,
|
||||
body: {
|
||||
userId: user.id,
|
||||
items: [{ productId: 'prod-1', quantity: 2 }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(order.userId).toBe(user.id);
|
||||
});
|
||||
|
||||
test('should reject order for invalid user', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
baseUrl: ORDER_SERVICE,
|
||||
body: {
|
||||
userId: 'non-existent-user',
|
||||
items: [{ productId: 'prod-1', quantity: 1 }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body.code).toBe('INVALID_USER');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Test multiple services without browser
|
||||
- Use `baseUrl` to target different services
|
||||
- Validate cross-service communication
|
||||
- Pure API testing - fast and reliable
|
||||
|
||||
### Example 7: GraphQL API Testing
|
||||
|
||||
**Context**: Test GraphQL endpoints with queries and mutations.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
test.describe('GraphQL API', () => {
|
||||
const GRAPHQL_ENDPOINT = '/graphql';
|
||||
|
||||
test('should query users via GraphQL', async ({ apiRequest }) => {
|
||||
const query = `
|
||||
query GetUsers($limit: Int) {
|
||||
users(limit: $limit) {
|
||||
id
|
||||
name
|
||||
email
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: GRAPHQL_ENDPOINT,
|
||||
body: {
|
||||
query,
|
||||
variables: { limit: 10 },
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.errors).toBeUndefined();
|
||||
expect(body.data.users).toHaveLength(10);
|
||||
});
|
||||
|
||||
test('should create user via mutation', async ({ apiRequest }) => {
|
||||
const mutation = `
|
||||
mutation CreateUser($input: CreateUserInput!) {
|
||||
createUser(input: $input) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: GRAPHQL_ENDPOINT,
|
||||
body: {
|
||||
query: mutation,
|
||||
variables: {
|
||||
input: { name: 'GraphQL User', email: 'gql@example.com' },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.data.createUser.id).toBeDefined();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- GraphQL via POST request
|
||||
- Variables in request body
|
||||
- Check `body.errors` for GraphQL errors (not status code)
|
||||
- Works for queries and mutations
|
||||
|
||||
## Comparison with Vanilla Playwright
|
||||
|
||||
| Vanilla Playwright | playwright-utils apiRequest |
|
||||
|
|
@ -251,11 +386,13 @@ test('should poll until job completes', async ({ apiRequest, recurse }) => {
|
|||
|
||||
**Use apiRequest for:**
|
||||
|
||||
- ✅ API endpoint testing
|
||||
- ✅ Background API calls in UI tests
|
||||
- ✅ Pure API/service testing (no browser needed)
|
||||
- ✅ Microservice integration testing
|
||||
- ✅ GraphQL API testing
|
||||
- ✅ Schema validation needs
|
||||
- ✅ Tests requiring retry logic
|
||||
- ✅ Typed API responses
|
||||
- ✅ Background API calls in UI tests
|
||||
- ✅ Contract testing support
|
||||
|
||||
**Stick with vanilla Playwright for:**
|
||||
|
||||
|
|
@ -265,11 +402,13 @@ test('should poll until job completes', async ({ apiRequest, recurse }) => {
|
|||
|
||||
## Related Fragments
|
||||
|
||||
- `api-testing-patterns.md` - Comprehensive pure API testing patterns
|
||||
- `overview.md` - Installation and design principles
|
||||
- `auth-session.md` - Authentication token management
|
||||
- `recurse.md` - Polling for async operations
|
||||
- `fixtures-composition.md` - Combining utilities with mergeTests
|
||||
- `log.md` - Logging API requests
|
||||
- `contract-testing.md` - Pact contract testing
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,843 @@
|
|||
# API Testing Patterns
|
||||
|
||||
## Principle
|
||||
|
||||
Test APIs and backend services directly without browser overhead. Use Playwright's `request` context for HTTP operations, `apiRequest` utility for enhanced features, and `recurse` for async operations. Pure API tests run faster, are more stable, and provide better coverage for service-layer logic.
|
||||
|
||||
## Rationale
|
||||
|
||||
Many teams over-rely on E2E/browser tests when API tests would be more appropriate:
|
||||
|
||||
- **Slower feedback**: Browser tests take seconds, API tests take milliseconds
|
||||
- **More brittle**: UI changes break tests even when API works correctly
|
||||
- **Wrong abstraction**: Testing business logic through UI layers adds noise
|
||||
- **Resource heavy**: Browsers consume memory and CPU
|
||||
|
||||
API-first testing provides:
|
||||
|
||||
- **Fast execution**: No browser startup, no rendering, no JavaScript execution
|
||||
- **Direct validation**: Test exactly what the service returns
|
||||
- **Better isolation**: Test service logic independent of UI
|
||||
- **Easier debugging**: Clear request/response without DOM noise
|
||||
- **Contract validation**: Verify API contracts explicitly
|
||||
|
||||
## When to Use API Tests vs E2E Tests
|
||||
|
||||
| Scenario | API Test | E2E Test |
|
||||
|----------|----------|----------|
|
||||
| CRUD operations | ✅ Primary | ❌ Overkill |
|
||||
| Business logic validation | ✅ Primary | ❌ Overkill |
|
||||
| Error handling (4xx, 5xx) | ✅ Primary | ⚠️ Supplement |
|
||||
| Authentication flows | ✅ Primary | ⚠️ Supplement |
|
||||
| Data transformation | ✅ Primary | ❌ Overkill |
|
||||
| User journeys | ❌ Can't test | ✅ Primary |
|
||||
| Visual regression | ❌ Can't test | ✅ Primary |
|
||||
| Cross-browser issues | ❌ Can't test | ✅ Primary |
|
||||
|
||||
**Rule of thumb**: If you're testing what the server returns (not how it looks), use API tests.
|
||||
|
||||
## Pattern Examples
|
||||
|
||||
### Example 1: Pure API Test (No Browser)
|
||||
|
||||
**Context**: Test REST API endpoints directly without any browser context.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// tests/api/users.spec.ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
// No page, no browser - just API
|
||||
test.describe('Users API', () => {
|
||||
test('should create user', async ({ request }) => {
|
||||
const response = await request.post('/api/users', {
|
||||
data: {
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
role: 'user',
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.status()).toBe(201);
|
||||
|
||||
const user = await response.json();
|
||||
expect(user.id).toBeDefined();
|
||||
expect(user.name).toBe('John Doe');
|
||||
expect(user.email).toBe('john@example.com');
|
||||
});
|
||||
|
||||
test('should get user by ID', async ({ request }) => {
|
||||
// Create user first
|
||||
const createResponse = await request.post('/api/users', {
|
||||
data: { name: 'Jane Doe', email: 'jane@example.com' },
|
||||
});
|
||||
const { id } = await createResponse.json();
|
||||
|
||||
// Get user
|
||||
const getResponse = await request.get(`/api/users/${id}`);
|
||||
expect(getResponse.status()).toBe(200);
|
||||
|
||||
const user = await getResponse.json();
|
||||
expect(user.id).toBe(id);
|
||||
expect(user.name).toBe('Jane Doe');
|
||||
});
|
||||
|
||||
test('should return 404 for non-existent user', async ({ request }) => {
|
||||
const response = await request.get('/api/users/non-existent-id');
|
||||
expect(response.status()).toBe(404);
|
||||
|
||||
const error = await response.json();
|
||||
expect(error.code).toBe('USER_NOT_FOUND');
|
||||
});
|
||||
|
||||
test('should validate required fields', async ({ request }) => {
|
||||
const response = await request.post('/api/users', {
|
||||
data: { name: 'Missing Email' }, // email is required
|
||||
});
|
||||
|
||||
expect(response.status()).toBe(400);
|
||||
|
||||
const error = await response.json();
|
||||
expect(error.code).toBe('VALIDATION_ERROR');
|
||||
expect(error.details).toContainEqual(
|
||||
expect.objectContaining({ field: 'email', message: expect.any(String) })
|
||||
);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- No `page` fixture needed - only `request`
|
||||
- Tests run without browser overhead
|
||||
- Direct HTTP assertions
|
||||
- Clear error handling tests
|
||||
|
||||
### Example 2: API Test with apiRequest Utility
|
||||
|
||||
**Context**: Use enhanced apiRequest for schema validation, retry, and type safety.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// tests/api/orders.spec.ts
|
||||
import { test, expect } from '@seontechnologies/playwright-utils/api-request/fixtures';
|
||||
import { z } from 'zod';
|
||||
|
||||
// Define schema for type safety and validation
|
||||
const OrderSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
userId: z.string(),
|
||||
items: z.array(
|
||||
z.object({
|
||||
productId: z.string(),
|
||||
quantity: z.number().positive(),
|
||||
price: z.number().positive(),
|
||||
})
|
||||
),
|
||||
total: z.number().positive(),
|
||||
status: z.enum(['pending', 'processing', 'shipped', 'delivered']),
|
||||
createdAt: z.string().datetime(),
|
||||
});
|
||||
|
||||
type Order = z.infer<typeof OrderSchema>;
|
||||
|
||||
test.describe('Orders API', () => {
|
||||
test('should create order with schema validation', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest<Order>({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
body: {
|
||||
userId: 'user-123',
|
||||
items: [
|
||||
{ productId: 'prod-1', quantity: 2, price: 29.99 },
|
||||
{ productId: 'prod-2', quantity: 1, price: 49.99 },
|
||||
],
|
||||
},
|
||||
validateSchema: OrderSchema, // Validates response matches schema
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(body.id).toBeDefined();
|
||||
expect(body.status).toBe('pending');
|
||||
expect(body.total).toBe(109.97); // 2*29.99 + 49.99
|
||||
});
|
||||
|
||||
test('should handle server errors with retry', async ({ apiRequest }) => {
|
||||
// apiRequest retries 5xx errors by default
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/orders/order-123',
|
||||
retryConfig: {
|
||||
maxRetries: 3,
|
||||
retryDelay: 1000,
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
});
|
||||
|
||||
test('should list orders with pagination', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest<{ orders: Order[]; total: number; page: number }>({
|
||||
method: 'GET',
|
||||
path: '/api/orders',
|
||||
params: { page: 1, limit: 10, status: 'pending' },
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.orders).toHaveLength(10);
|
||||
expect(body.total).toBeGreaterThan(10);
|
||||
expect(body.page).toBe(1);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Zod schema for runtime validation AND TypeScript types
|
||||
- `validateSchema` throws if response doesn't match
|
||||
- Built-in retry for transient failures
|
||||
- Type-safe `body` access
|
||||
|
||||
### Example 3: Microservice-to-Microservice Testing
|
||||
|
||||
**Context**: Test service interactions without browser - validate API contracts between services.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// tests/api/service-integration.spec.ts
|
||||
import { test, expect } from '@seontechnologies/playwright-utils/fixtures';
|
||||
|
||||
test.describe('Service Integration', () => {
|
||||
const USER_SERVICE_URL = process.env.USER_SERVICE_URL || 'http://localhost:3001';
|
||||
const ORDER_SERVICE_URL = process.env.ORDER_SERVICE_URL || 'http://localhost:3002';
|
||||
const INVENTORY_SERVICE_URL = process.env.INVENTORY_SERVICE_URL || 'http://localhost:3003';
|
||||
|
||||
test('order service should validate user exists', async ({ apiRequest }) => {
|
||||
// Create user in user-service
|
||||
const { body: user } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/users',
|
||||
baseUrl: USER_SERVICE_URL,
|
||||
body: { name: 'Test User', email: 'test@example.com' },
|
||||
});
|
||||
|
||||
// Create order in order-service (should validate user via user-service)
|
||||
const { status, body: order } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
baseUrl: ORDER_SERVICE_URL,
|
||||
body: {
|
||||
userId: user.id,
|
||||
items: [{ productId: 'prod-1', quantity: 1 }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(order.userId).toBe(user.id);
|
||||
});
|
||||
|
||||
test('order service should reject invalid user', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
baseUrl: ORDER_SERVICE_URL,
|
||||
body: {
|
||||
userId: 'non-existent-user',
|
||||
items: [{ productId: 'prod-1', quantity: 1 }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body.code).toBe('INVALID_USER');
|
||||
});
|
||||
|
||||
test('order should decrease inventory', async ({ apiRequest, recurse }) => {
|
||||
// Get initial inventory
|
||||
const { body: initialInventory } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/inventory/prod-1',
|
||||
baseUrl: INVENTORY_SERVICE_URL,
|
||||
});
|
||||
|
||||
// Create order
|
||||
await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
baseUrl: ORDER_SERVICE_URL,
|
||||
body: {
|
||||
userId: 'user-123',
|
||||
items: [{ productId: 'prod-1', quantity: 2 }],
|
||||
},
|
||||
});
|
||||
|
||||
// Poll for inventory update (eventual consistency)
|
||||
const { body: updatedInventory } = await recurse(
|
||||
() =>
|
||||
apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/inventory/prod-1',
|
||||
baseUrl: INVENTORY_SERVICE_URL,
|
||||
}),
|
||||
(response) => response.body.quantity === initialInventory.quantity - 2,
|
||||
{ timeout: 10000, interval: 500 }
|
||||
);
|
||||
|
||||
expect(updatedInventory.quantity).toBe(initialInventory.quantity - 2);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Multiple service URLs for microservice testing
|
||||
- Tests service-to-service communication
|
||||
- Uses `recurse` for eventual consistency
|
||||
- No browser needed for full integration testing
|
||||
|
||||
### Example 4: GraphQL API Testing
|
||||
|
||||
**Context**: Test GraphQL endpoints with queries and mutations.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// tests/api/graphql.spec.ts
|
||||
import { test, expect } from '@seontechnologies/playwright-utils/api-request/fixtures';
|
||||
|
||||
const GRAPHQL_ENDPOINT = '/graphql';
|
||||
|
||||
test.describe('GraphQL API', () => {
|
||||
test('should query users', async ({ apiRequest }) => {
|
||||
const query = `
|
||||
query GetUsers($limit: Int) {
|
||||
users(limit: $limit) {
|
||||
id
|
||||
name
|
||||
email
|
||||
role
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: GRAPHQL_ENDPOINT,
|
||||
body: {
|
||||
query,
|
||||
variables: { limit: 10 },
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.errors).toBeUndefined();
|
||||
expect(body.data.users).toHaveLength(10);
|
||||
expect(body.data.users[0]).toHaveProperty('id');
|
||||
expect(body.data.users[0]).toHaveProperty('name');
|
||||
});
|
||||
|
||||
test('should create user via mutation', async ({ apiRequest }) => {
|
||||
const mutation = `
|
||||
mutation CreateUser($input: CreateUserInput!) {
|
||||
createUser(input: $input) {
|
||||
id
|
||||
name
|
||||
email
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: GRAPHQL_ENDPOINT,
|
||||
body: {
|
||||
query: mutation,
|
||||
variables: {
|
||||
input: {
|
||||
name: 'GraphQL User',
|
||||
email: 'graphql@example.com',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.errors).toBeUndefined();
|
||||
expect(body.data.createUser.id).toBeDefined();
|
||||
expect(body.data.createUser.name).toBe('GraphQL User');
|
||||
});
|
||||
|
||||
test('should handle GraphQL errors', async ({ apiRequest }) => {
|
||||
const query = `
|
||||
query GetUser($id: ID!) {
|
||||
user(id: $id) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: GRAPHQL_ENDPOINT,
|
||||
body: {
|
||||
query,
|
||||
variables: { id: 'non-existent' },
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(200); // GraphQL returns 200 even for errors
|
||||
expect(body.errors).toBeDefined();
|
||||
expect(body.errors[0].message).toContain('not found');
|
||||
expect(body.data.user).toBeNull();
|
||||
});
|
||||
|
||||
test('should handle validation errors', async ({ apiRequest }) => {
|
||||
const mutation = `
|
||||
mutation CreateUser($input: CreateUserInput!) {
|
||||
createUser(input: $input) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: GRAPHQL_ENDPOINT,
|
||||
body: {
|
||||
query: mutation,
|
||||
variables: {
|
||||
input: {
|
||||
name: '', // Invalid: empty name
|
||||
email: 'invalid-email', // Invalid: bad format
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.errors).toBeDefined();
|
||||
expect(body.errors[0].extensions.code).toBe('BAD_USER_INPUT');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- GraphQL queries and mutations via POST
|
||||
- Variables passed in request body
|
||||
- GraphQL returns 200 even for errors (check `body.errors`)
|
||||
- Test validation and business logic errors
|
||||
|
||||
### Example 5: Database Seeding and Cleanup via API
|
||||
|
||||
**Context**: Use API calls to set up and tear down test data without direct database access.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// tests/api/with-data-setup.spec.ts
|
||||
import { test, expect } from '@seontechnologies/playwright-utils/fixtures';
|
||||
|
||||
test.describe('Orders with Data Setup', () => {
|
||||
let testUser: { id: string; email: string };
|
||||
let testProducts: Array<{ id: string; name: string; price: number }>;
|
||||
|
||||
test.beforeAll(async ({ request }) => {
|
||||
// Seed user via API
|
||||
const userResponse = await request.post('/api/users', {
|
||||
data: {
|
||||
name: 'Test User',
|
||||
email: `test-${Date.now()}@example.com`,
|
||||
},
|
||||
});
|
||||
testUser = await userResponse.json();
|
||||
|
||||
// Seed products via API
|
||||
testProducts = [];
|
||||
for (const product of [
|
||||
{ name: 'Widget A', price: 29.99 },
|
||||
{ name: 'Widget B', price: 49.99 },
|
||||
{ name: 'Widget C', price: 99.99 },
|
||||
]) {
|
||||
const productResponse = await request.post('/api/products', {
|
||||
data: product,
|
||||
});
|
||||
testProducts.push(await productResponse.json());
|
||||
}
|
||||
});
|
||||
|
||||
test.afterAll(async ({ request }) => {
|
||||
// Cleanup via API
|
||||
if (testUser?.id) {
|
||||
await request.delete(`/api/users/${testUser.id}`);
|
||||
}
|
||||
for (const product of testProducts) {
|
||||
await request.delete(`/api/products/${product.id}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('should create order with seeded data', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
body: {
|
||||
userId: testUser.id,
|
||||
items: [
|
||||
{ productId: testProducts[0].id, quantity: 2 },
|
||||
{ productId: testProducts[1].id, quantity: 1 },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(body.userId).toBe(testUser.id);
|
||||
expect(body.items).toHaveLength(2);
|
||||
expect(body.total).toBe(2 * 29.99 + 49.99);
|
||||
});
|
||||
|
||||
test('should list user orders', async ({ apiRequest }) => {
|
||||
// Create an order first
|
||||
await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
body: {
|
||||
userId: testUser.id,
|
||||
items: [{ productId: testProducts[2].id, quantity: 1 }],
|
||||
},
|
||||
});
|
||||
|
||||
// List orders for user
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/orders',
|
||||
params: { userId: testUser.id },
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.orders.length).toBeGreaterThanOrEqual(1);
|
||||
expect(body.orders.every((o: any) => o.userId === testUser.id)).toBe(true);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- `beforeAll`/`afterAll` for test data setup/cleanup
|
||||
- API-based seeding (no direct DB access needed)
|
||||
- Unique emails to prevent conflicts in parallel runs
|
||||
- Cleanup after all tests complete
|
||||
|
||||
### Example 6: Background Job Testing with Recurse
|
||||
|
||||
**Context**: Test async operations like background jobs, webhooks, and eventual consistency.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// tests/api/background-jobs.spec.ts
|
||||
import { test, expect } from '@seontechnologies/playwright-utils/fixtures';
|
||||
|
||||
test.describe('Background Jobs', () => {
|
||||
test('should process export job', async ({ apiRequest, recurse }) => {
|
||||
// Trigger export job
|
||||
const { body: job } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/exports',
|
||||
body: {
|
||||
type: 'users',
|
||||
format: 'csv',
|
||||
filters: { createdAfter: '2024-01-01' },
|
||||
},
|
||||
});
|
||||
|
||||
expect(job.id).toBeDefined();
|
||||
expect(job.status).toBe('pending');
|
||||
|
||||
// Poll until job completes
|
||||
const { body: completedJob } = await recurse(
|
||||
() => apiRequest({ method: 'GET', path: `/api/exports/${job.id}` }),
|
||||
(response) => response.body.status === 'completed',
|
||||
{
|
||||
timeout: 60000,
|
||||
interval: 2000,
|
||||
log: `Waiting for export job ${job.id} to complete`,
|
||||
}
|
||||
);
|
||||
|
||||
expect(completedJob.status).toBe('completed');
|
||||
expect(completedJob.downloadUrl).toBeDefined();
|
||||
expect(completedJob.recordCount).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('should handle job failure gracefully', async ({ apiRequest, recurse }) => {
|
||||
// Trigger job that will fail
|
||||
const { body: job } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/exports',
|
||||
body: {
|
||||
type: 'invalid-type', // This will cause failure
|
||||
format: 'csv',
|
||||
},
|
||||
});
|
||||
|
||||
// Poll until job fails
|
||||
const { body: failedJob } = await recurse(
|
||||
() => apiRequest({ method: 'GET', path: `/api/exports/${job.id}` }),
|
||||
(response) => ['completed', 'failed'].includes(response.body.status),
|
||||
{ timeout: 30000 }
|
||||
);
|
||||
|
||||
expect(failedJob.status).toBe('failed');
|
||||
expect(failedJob.error).toBeDefined();
|
||||
expect(failedJob.error.code).toBe('INVALID_EXPORT_TYPE');
|
||||
});
|
||||
|
||||
test('should process webhook delivery', async ({ apiRequest, recurse }) => {
|
||||
// Trigger action that sends webhook
|
||||
const { body: order } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
body: {
|
||||
userId: 'user-123',
|
||||
items: [{ productId: 'prod-1', quantity: 1 }],
|
||||
webhookUrl: 'https://webhook.site/test-endpoint',
|
||||
},
|
||||
});
|
||||
|
||||
// Poll for webhook delivery status
|
||||
const { body: webhookStatus } = await recurse(
|
||||
() => apiRequest({ method: 'GET', path: `/api/webhooks/order/${order.id}` }),
|
||||
(response) => response.body.delivered === true,
|
||||
{ timeout: 30000, interval: 1000 }
|
||||
);
|
||||
|
||||
expect(webhookStatus.delivered).toBe(true);
|
||||
expect(webhookStatus.deliveredAt).toBeDefined();
|
||||
expect(webhookStatus.responseStatus).toBe(200);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- `recurse` for polling async operations
|
||||
- Test both success and failure scenarios
|
||||
- Configurable timeout and interval
|
||||
- Log messages for debugging
|
||||
|
||||
### Example 7: Service Authentication (No Browser)
|
||||
|
||||
**Context**: Test authenticated API endpoints using tokens directly - no browser login needed.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// tests/api/authenticated.spec.ts
|
||||
import { test, expect } from '@seontechnologies/playwright-utils/fixtures';
|
||||
|
||||
test.describe('Authenticated API Tests', () => {
|
||||
let authToken: string;
|
||||
|
||||
test.beforeAll(async ({ request }) => {
|
||||
// Get token via API (no browser!)
|
||||
const response = await request.post('/api/auth/login', {
|
||||
data: {
|
||||
email: process.env.TEST_USER_EMAIL,
|
||||
password: process.env.TEST_USER_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
const { token } = await response.json();
|
||||
authToken = token;
|
||||
});
|
||||
|
||||
test('should access protected endpoint with token', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/me',
|
||||
headers: {
|
||||
Authorization: `Bearer ${authToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.email).toBe(process.env.TEST_USER_EMAIL);
|
||||
});
|
||||
|
||||
test('should reject request without token', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/me',
|
||||
// No Authorization header
|
||||
});
|
||||
|
||||
expect(status).toBe(401);
|
||||
expect(body.code).toBe('UNAUTHORIZED');
|
||||
});
|
||||
|
||||
test('should reject expired token', async ({ apiRequest }) => {
|
||||
const expiredToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // Expired token
|
||||
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/me',
|
||||
headers: {
|
||||
Authorization: `Bearer ${expiredToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(401);
|
||||
expect(body.code).toBe('TOKEN_EXPIRED');
|
||||
});
|
||||
|
||||
test('should handle role-based access', async ({ apiRequest }) => {
|
||||
// User token (non-admin)
|
||||
const { status } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/admin/users',
|
||||
headers: {
|
||||
Authorization: `Bearer ${authToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
expect(status).toBe(403); // Forbidden for non-admin
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Token obtained via API login (no browser)
|
||||
- Token reused across all tests in describe block
|
||||
- Test auth, expired tokens, and RBAC
|
||||
- Pure API testing without UI
|
||||
|
||||
## API Test Configuration
|
||||
|
||||
### Playwright Config for API-Only Tests
|
||||
|
||||
```typescript
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests/api',
|
||||
|
||||
// No browser needed for API tests
|
||||
use: {
|
||||
baseURL: process.env.API_URL || 'http://localhost:3000',
|
||||
extraHTTPHeaders: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
|
||||
// Faster without browser overhead
|
||||
timeout: 30000,
|
||||
|
||||
// Run API tests in parallel
|
||||
workers: 4,
|
||||
fullyParallel: true,
|
||||
|
||||
// No screenshots/traces needed for API tests
|
||||
reporter: [['html'], ['json', { outputFile: 'api-test-results.json' }]],
|
||||
});
|
||||
```
|
||||
|
||||
### Separate API Test Project
|
||||
|
||||
```typescript
|
||||
// playwright.config.ts
|
||||
export default defineConfig({
|
||||
projects: [
|
||||
{
|
||||
name: 'api',
|
||||
testDir: './tests/api',
|
||||
use: {
|
||||
baseURL: process.env.API_URL,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'e2e',
|
||||
testDir: './tests/e2e',
|
||||
use: {
|
||||
baseURL: process.env.APP_URL,
|
||||
...devices['Desktop Chrome'],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## Comparison: API Tests vs E2E Tests
|
||||
|
||||
| Aspect | API Test | E2E Test |
|
||||
|--------|----------|----------|
|
||||
| **Speed** | ~50-100ms per test | ~2-10s per test |
|
||||
| **Stability** | Very stable | More flaky (UI timing) |
|
||||
| **Setup** | Minimal | Browser, context, page |
|
||||
| **Debugging** | Clear request/response | DOM, screenshots, traces |
|
||||
| **Coverage** | Service logic | User experience |
|
||||
| **Parallelization** | Easy (stateless) | Complex (browser resources) |
|
||||
| **CI Cost** | Low (no browser) | High (browser containers) |
|
||||
|
||||
## Related Fragments
|
||||
|
||||
- `api-request.md` - apiRequest utility details
|
||||
- `recurse.md` - Polling patterns for async operations
|
||||
- `auth-session.md` - Token management
|
||||
- `contract-testing.md` - Pact contract testing
|
||||
- `test-levels-framework.md` - When to use which test level
|
||||
- `data-factories.md` - Test data setup patterns
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
**DON'T use E2E for API validation:**
|
||||
|
||||
```typescript
|
||||
// Bad: Testing API through UI
|
||||
test('validate user creation', async ({ page }) => {
|
||||
await page.goto('/admin/users');
|
||||
await page.fill('#name', 'John');
|
||||
await page.click('#submit');
|
||||
await expect(page.getByText('User created')).toBeVisible();
|
||||
});
|
||||
```
|
||||
|
||||
**DO test APIs directly:**
|
||||
|
||||
```typescript
|
||||
// Good: Direct API test
|
||||
test('validate user creation', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/users',
|
||||
body: { name: 'John' },
|
||||
});
|
||||
expect(status).toBe(201);
|
||||
expect(body.id).toBeDefined();
|
||||
});
|
||||
```
|
||||
|
||||
**DON'T ignore API tests because "E2E covers it":**
|
||||
|
||||
```typescript
|
||||
// Bad thinking: "Our E2E tests create users, so API is tested"
|
||||
// Reality: E2E tests one happy path; API tests cover edge cases
|
||||
```
|
||||
|
||||
**DO have dedicated API test coverage:**
|
||||
|
||||
```typescript
|
||||
// Good: Explicit API test suite
|
||||
test.describe('Users API', () => {
|
||||
test('creates user', async ({ apiRequest }) => { /* ... */ });
|
||||
test('handles duplicate email', async ({ apiRequest }) => { /* ... */ });
|
||||
test('validates required fields', async ({ apiRequest }) => { /* ... */ });
|
||||
test('handles malformed JSON', async ({ apiRequest }) => { /* ... */ });
|
||||
test('rate limits requests', async ({ apiRequest }) => { /* ... */ });
|
||||
});
|
||||
```
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Principle
|
||||
|
||||
Persist authentication tokens to disk and reuse across test runs. Support multiple user identifiers, ephemeral authentication, and worker-specific accounts for parallel execution. Fetch tokens once, use everywhere.
|
||||
Persist authentication tokens to disk and reuse across test runs. Support multiple user identifiers, ephemeral authentication, and worker-specific accounts for parallel execution. Fetch tokens once, use everywhere. **Works for both API-only tests and browser tests.**
|
||||
|
||||
## Rationale
|
||||
|
||||
|
|
@ -22,6 +22,7 @@ The `auth-session` utility provides:
|
|||
- **Worker-specific accounts**: Parallel execution with isolated user accounts
|
||||
- **Automatic token management**: Checks validity, renews if expired
|
||||
- **Flexible provider pattern**: Adapt to any auth system (OAuth2, JWT, custom)
|
||||
- **API-first design**: Get tokens for API tests without browser overhead
|
||||
|
||||
## Pattern Examples
|
||||
|
||||
|
|
@ -244,6 +245,200 @@ test('parallel test 2', async ({ page }) => {
|
|||
- Token management automatic per worker
|
||||
- Scales to any number of workers
|
||||
|
||||
### Example 6: Pure API Authentication (No Browser)
|
||||
|
||||
**Context**: Get auth tokens for API-only tests using auth-session disk persistence.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// Step 1: Create API-only auth provider (no browser needed)
|
||||
// playwright/support/api-auth-provider.ts
|
||||
import { type AuthProvider } from '@seontechnologies/playwright-utils/auth-session';
|
||||
|
||||
const apiAuthProvider: AuthProvider = {
|
||||
getEnvironment: (options) => options.environment || 'local',
|
||||
getUserIdentifier: (options) => options.userIdentifier || 'api-user',
|
||||
|
||||
extractToken: (storageState) => {
|
||||
// Token stored in localStorage format for disk persistence
|
||||
const tokenEntry = storageState.origins?.[0]?.localStorage?.find(
|
||||
(item) => item.name === 'auth_token'
|
||||
);
|
||||
return tokenEntry?.value;
|
||||
},
|
||||
|
||||
isTokenExpired: (storageState) => {
|
||||
const expiryEntry = storageState.origins?.[0]?.localStorage?.find(
|
||||
(item) => item.name === 'token_expiry'
|
||||
);
|
||||
if (!expiryEntry) return true;
|
||||
return Date.now() > parseInt(expiryEntry.value, 10);
|
||||
},
|
||||
|
||||
manageAuthToken: async (request, options) => {
|
||||
const email = process.env.TEST_USER_EMAIL;
|
||||
const password = process.env.TEST_USER_PASSWORD;
|
||||
|
||||
if (!email || !password) {
|
||||
throw new Error('TEST_USER_EMAIL and TEST_USER_PASSWORD must be set');
|
||||
}
|
||||
|
||||
// Pure API login - no browser!
|
||||
const response = await request.post('/api/auth/login', {
|
||||
data: { email, password },
|
||||
});
|
||||
|
||||
if (!response.ok()) {
|
||||
throw new Error(`Auth failed: ${response.status()}`);
|
||||
}
|
||||
|
||||
const { token, expiresIn } = await response.json();
|
||||
const expiryTime = Date.now() + expiresIn * 1000;
|
||||
|
||||
// Return storage state format for disk persistence
|
||||
return {
|
||||
cookies: [],
|
||||
origins: [
|
||||
{
|
||||
origin: process.env.API_BASE_URL || 'http://localhost:3000',
|
||||
localStorage: [
|
||||
{ name: 'auth_token', value: token },
|
||||
{ name: 'token_expiry', value: String(expiryTime) },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default apiAuthProvider;
|
||||
|
||||
// Step 2: Create auth fixture
|
||||
// playwright/support/fixtures.ts
|
||||
import { test as base } from '@playwright/test';
|
||||
import { createAuthFixtures, setAuthProvider } from '@seontechnologies/playwright-utils/auth-session';
|
||||
import apiAuthProvider from './api-auth-provider';
|
||||
|
||||
setAuthProvider(apiAuthProvider);
|
||||
|
||||
export const test = base.extend(createAuthFixtures());
|
||||
|
||||
// Step 3: Use in tests - token persisted to disk!
|
||||
// tests/api/authenticated-api.spec.ts
|
||||
import { test } from '../support/fixtures';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('should access protected endpoint', async ({ authToken, apiRequest }) => {
|
||||
// authToken is automatically loaded from disk or fetched if expired
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/api/me',
|
||||
headers: { Authorization: `Bearer ${authToken}` },
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
});
|
||||
|
||||
test('should create resource with auth', async ({ authToken, apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
headers: { Authorization: `Bearer ${authToken}` },
|
||||
body: { items: [{ productId: 'prod-1', quantity: 2 }] },
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(body.id).toBeDefined();
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Token persisted to disk (not in-memory) - survives test reruns
|
||||
- Provider fetches token once, reuses until expired
|
||||
- Pure API authentication - no browser context needed
|
||||
- `authToken` fixture handles disk read/write automatically
|
||||
- Environment variables validated with clear error message
|
||||
|
||||
### Example 7: Service-to-Service Authentication
|
||||
|
||||
**Context**: Test microservice authentication patterns (API keys, service tokens) with proper environment validation.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// tests/api/service-auth.spec.ts
|
||||
import { test as base, expect } from '@playwright/test';
|
||||
import { test as apiFixture } from '@seontechnologies/playwright-utils/api-request/fixtures';
|
||||
import { mergeTests } from '@playwright/test';
|
||||
|
||||
// Validate environment variables at module load
|
||||
const SERVICE_API_KEY = process.env.SERVICE_API_KEY;
|
||||
const INTERNAL_SERVICE_URL = process.env.INTERNAL_SERVICE_URL;
|
||||
|
||||
if (!SERVICE_API_KEY) {
|
||||
throw new Error('SERVICE_API_KEY environment variable is required');
|
||||
}
|
||||
if (!INTERNAL_SERVICE_URL) {
|
||||
throw new Error('INTERNAL_SERVICE_URL environment variable is required');
|
||||
}
|
||||
|
||||
const test = mergeTests(base, apiFixture);
|
||||
|
||||
test.describe('Service-to-Service Auth', () => {
|
||||
test('should authenticate with API key', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/internal/health',
|
||||
baseUrl: INTERNAL_SERVICE_URL,
|
||||
headers: { 'X-API-Key': SERVICE_API_KEY },
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.status).toBe('healthy');
|
||||
});
|
||||
|
||||
test('should reject invalid API key', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'GET',
|
||||
path: '/internal/health',
|
||||
baseUrl: INTERNAL_SERVICE_URL,
|
||||
headers: { 'X-API-Key': 'invalid-key' },
|
||||
});
|
||||
|
||||
expect(status).toBe(401);
|
||||
expect(body.code).toBe('INVALID_API_KEY');
|
||||
});
|
||||
|
||||
test('should call downstream service with propagated auth', async ({ apiRequest }) => {
|
||||
const { status, body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/internal/aggregate-data',
|
||||
baseUrl: INTERNAL_SERVICE_URL,
|
||||
headers: {
|
||||
'X-API-Key': SERVICE_API_KEY,
|
||||
'X-Request-ID': `test-${Date.now()}`,
|
||||
},
|
||||
body: { sources: ['users', 'orders', 'inventory'] },
|
||||
});
|
||||
|
||||
expect(status).toBe(200);
|
||||
expect(body.aggregatedFrom).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Environment variables validated at module load with clear errors
|
||||
- API key authentication (simpler than OAuth - no disk persistence needed)
|
||||
- Test internal/service endpoints
|
||||
- Validate auth rejection scenarios
|
||||
- Correlation ID for request tracing
|
||||
|
||||
> **Note**: API keys are typically static secrets that don't expire, so disk persistence (auth-session) isn't needed. For rotating service tokens, use the auth-session provider pattern from Example 6.
|
||||
|
||||
## Custom Auth Provider Pattern
|
||||
|
||||
**Context**: Adapt auth-session to your authentication system (OAuth2, JWT, SAML, custom).
|
||||
|
|
@ -310,6 +505,7 @@ test('authenticated API call', async ({ apiRequest, authToken }) => {
|
|||
|
||||
## Related Fragments
|
||||
|
||||
- `api-testing-patterns.md` - Pure API testing patterns (no browser)
|
||||
- `overview.md` - Installation and fixture composition
|
||||
- `api-request.md` - Authenticated API requests
|
||||
- `fixtures-composition.md` - Merging auth with other utilities
|
||||
|
|
|
|||
|
|
@ -22,6 +22,16 @@ The `file-utils` module provides:
|
|||
- **Validation helpers**: Row count, header checks, content validation
|
||||
- **Format support**: Multiple sheet support (XLSX), text extraction (PDF), archive extraction (ZIP)
|
||||
|
||||
## Why Use This Instead of Vanilla Playwright?
|
||||
|
||||
| Vanilla Playwright | File Utils |
|
||||
| ------------------------------------------- | ------------------------------------------------ |
|
||||
| ~80 lines per CSV flow (download + parse) | ~10 lines end-to-end |
|
||||
| Manual event orchestration for downloads | Encapsulated in `handleDownload()` |
|
||||
| Manual path handling and `saveAs` | Returns a ready-to-use file path |
|
||||
| Manual existence checks and error handling | Centralized in one place via utility patterns |
|
||||
| Manual CSV parsing config (headers, typing) | `readCSV()` returns `{ data, headers }` directly |
|
||||
|
||||
## Pattern Examples
|
||||
|
||||
### Example 1: UI-Triggered CSV Download
|
||||
|
|
@ -40,20 +50,18 @@ test('should download and validate CSV', async ({ page }) => {
|
|||
const downloadPath = await handleDownload({
|
||||
page,
|
||||
downloadDir: DOWNLOAD_DIR,
|
||||
trigger: () => page.click('[data-testid="export-csv"]'),
|
||||
trigger: () => page.getByTestId('download-button-text/csv').click(),
|
||||
});
|
||||
|
||||
const { content } = await readCSV({ filePath: downloadPath });
|
||||
const csvResult = await readCSV({ filePath: downloadPath });
|
||||
|
||||
// Validate headers
|
||||
expect(content.headers).toEqual(['ID', 'Name', 'Email', 'Role']);
|
||||
|
||||
// Validate data
|
||||
expect(content.data).toHaveLength(10);
|
||||
expect(content.data[0]).toMatchObject({
|
||||
// Access parsed data and headers
|
||||
const { data, headers } = csvResult.content;
|
||||
expect(headers).toEqual(['ID', 'Name', 'Email']);
|
||||
expect(data[0]).toMatchObject({
|
||||
ID: expect.any(String),
|
||||
Name: expect.any(String),
|
||||
Email: expect.stringMatching(/@/),
|
||||
Email: expect.any(String),
|
||||
});
|
||||
});
|
||||
```
|
||||
|
|
@ -81,25 +89,27 @@ test('should read multi-sheet XLSX', async () => {
|
|||
trigger: () => page.click('[data-testid="export-xlsx"]'),
|
||||
});
|
||||
|
||||
const { content } = await readXLSX({ filePath: downloadPath });
|
||||
const xlsxResult = await readXLSX({ filePath: downloadPath });
|
||||
|
||||
// Access specific sheets
|
||||
const summarySheet = content.sheets.find((s) => s.name === 'Summary');
|
||||
const detailsSheet = content.sheets.find((s) => s.name === 'Details');
|
||||
// Verify worksheet structure
|
||||
expect(xlsxResult.content.worksheets.length).toBeGreaterThan(0);
|
||||
const worksheet = xlsxResult.content.worksheets[0];
|
||||
expect(worksheet).toBeDefined();
|
||||
expect(worksheet).toHaveProperty('name');
|
||||
|
||||
// Validate summary
|
||||
expect(summarySheet.data).toHaveLength(1);
|
||||
expect(summarySheet.data[0].TotalRecords).toBe('150');
|
||||
// Access sheet data
|
||||
const sheetData = worksheet?.data;
|
||||
expect(Array.isArray(sheetData)).toBe(true);
|
||||
|
||||
// Validate details
|
||||
expect(detailsSheet.data).toHaveLength(150);
|
||||
expect(detailsSheet.headers).toContain('TransactionID');
|
||||
// Use type assertion for type safety
|
||||
const firstRow = sheetData![0] as Record<string, unknown>;
|
||||
expect(firstRow).toHaveProperty('id');
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- `sheets` array with `name` and `data` properties
|
||||
- `worksheets` array with `name` and `data` properties
|
||||
- Access sheets by name
|
||||
- Each sheet has its own headers and data
|
||||
- Type-safe sheet iteration
|
||||
|
|
@ -117,26 +127,48 @@ test('should validate PDF report', async () => {
|
|||
const downloadPath = await handleDownload({
|
||||
page,
|
||||
downloadDir: DOWNLOAD_DIR,
|
||||
trigger: () => page.click('[data-testid="download-report"]'),
|
||||
trigger: () => page.getByTestId('download-button-Text-based PDF Document').click(),
|
||||
});
|
||||
|
||||
const { content } = await readPDF({ filePath: downloadPath });
|
||||
const pdfResult = await readPDF({ filePath: downloadPath });
|
||||
|
||||
// content.text is extracted text from all pages
|
||||
expect(content.text).toContain('Financial Report Q4 2024');
|
||||
expect(content.text).toContain('Total Revenue:');
|
||||
|
||||
// Validate page count
|
||||
expect(content.numpages).toBeGreaterThan(10);
|
||||
// content is extracted text from all pages
|
||||
expect(pdfResult.pagesCount).toBe(1);
|
||||
expect(pdfResult.fileName).toContain('.pdf');
|
||||
expect(pdfResult.content).toContain('All you need is the free Adobe Acrobat Reader');
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
**PDF Reader Options:**
|
||||
|
||||
- `content.text` contains all extracted text
|
||||
- `content.numpages` for page count
|
||||
- PDF parsing handles multi-page documents
|
||||
- Search for specific phrases
|
||||
```typescript
|
||||
const result = await readPDF({
|
||||
filePath: '/path/to/document.pdf',
|
||||
mergePages: false, // Keep pages separate (default: true)
|
||||
debug: true, // Enable debug logging
|
||||
maxPages: 10, // Limit processing to first 10 pages
|
||||
});
|
||||
```
|
||||
|
||||
**Important Limitation - Vector-based PDFs:**
|
||||
|
||||
Text extraction may fail for PDFs that store text as vector graphics (e.g., those generated by jsPDF):
|
||||
|
||||
```typescript
|
||||
// Vector-based PDF example (extraction fails gracefully)
|
||||
const pdfResult = await readPDF({ filePath: downloadPath });
|
||||
|
||||
expect(pdfResult.pagesCount).toBe(1);
|
||||
expect(pdfResult.info.extractionNotes).toContain(
|
||||
'Text extraction from vector-based PDFs is not supported.'
|
||||
);
|
||||
```
|
||||
|
||||
Such PDFs will have:
|
||||
|
||||
- `textExtractionSuccess: false`
|
||||
- `isVectorBased: true`
|
||||
- Explanatory message in `extractionNotes`
|
||||
|
||||
### Example 4: ZIP Archive Validation
|
||||
|
||||
|
|
@ -154,25 +186,33 @@ test('should validate ZIP archive', async () => {
|
|||
trigger: () => page.click('[data-testid="download-backup"]'),
|
||||
});
|
||||
|
||||
const { content } = await readZIP({ filePath: downloadPath });
|
||||
const zipResult = await readZIP({ filePath: downloadPath });
|
||||
|
||||
// Check file list
|
||||
expect(content.files).toContain('data.csv');
|
||||
expect(content.files).toContain('config.json');
|
||||
expect(content.files).toContain('readme.txt');
|
||||
expect(Array.isArray(zipResult.content.entries)).toBe(true);
|
||||
expect(zipResult.content.entries).toContain(
|
||||
'Case_53125_10-19-22_AM/Case_53125_10-19-22_AM_case_data.csv'
|
||||
);
|
||||
|
||||
// Read specific file from archive
|
||||
const configContent = content.zip.readAsText('config.json');
|
||||
const config = JSON.parse(configContent);
|
||||
// Extract specific file
|
||||
const targetFile = 'Case_53125_10-19-22_AM/Case_53125_10-19-22_AM_case_data.csv';
|
||||
const zipWithExtraction = await readZIP({
|
||||
filePath: downloadPath,
|
||||
fileToExtract: targetFile,
|
||||
});
|
||||
|
||||
expect(config.version).toBe('2.0');
|
||||
// Access extracted file buffer
|
||||
const extractedFiles = zipWithExtraction.content.extractedFiles || {};
|
||||
const fileBuffer = extractedFiles[targetFile];
|
||||
expect(fileBuffer).toBeInstanceOf(Buffer);
|
||||
expect(fileBuffer?.length).toBeGreaterThan(0);
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- `content.files` lists all files in archive
|
||||
- `content.zip.readAsText()` extracts specific files
|
||||
- `content.entries` lists all files in archive
|
||||
- `fileToExtract` extracts specific files to Buffer
|
||||
- Validate archive structure
|
||||
- Read and parse individual files from ZIP
|
||||
|
||||
|
|
@ -185,7 +225,7 @@ test('should validate ZIP archive', async () => {
|
|||
```typescript
|
||||
test('should download via API', async ({ page, request }) => {
|
||||
const downloadPath = await handleDownload({
|
||||
page,
|
||||
page, // Still need page for download events
|
||||
downloadDir: DOWNLOAD_DIR,
|
||||
trigger: async () => {
|
||||
const response = await request.get('/api/export/csv', {
|
||||
|
|
@ -211,20 +251,123 @@ test('should download via API', async ({ page, request }) => {
|
|||
- Still need `page` for download events
|
||||
- Works with authenticated endpoints
|
||||
|
||||
## Validation Helpers
|
||||
### Example 6: Reading CSV from Buffer (ZIP extraction)
|
||||
|
||||
**Context**: Read CSV content directly from a Buffer (e.g., extracted from ZIP).
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// CSV validation
|
||||
const { isValid, errors } = await validateCSV({
|
||||
filePath: downloadPath,
|
||||
expectedRowCount: 10,
|
||||
requiredHeaders: ['ID', 'Name', 'Email'],
|
||||
// Read from a Buffer (e.g., extracted from a ZIP)
|
||||
const zipResult = await readZIP({
|
||||
filePath: 'archive.zip',
|
||||
fileToExtract: 'data.csv',
|
||||
});
|
||||
const fileBuffer = zipResult.content.extractedFiles?.['data.csv'];
|
||||
const csvFromBuffer = await readCSV({ content: fileBuffer });
|
||||
|
||||
expect(isValid).toBe(true);
|
||||
expect(errors).toHaveLength(0);
|
||||
// Read from a string
|
||||
const csvString = 'name,age\nJohn,30\nJane,25';
|
||||
const csvFromString = await readCSV({ content: csvString });
|
||||
|
||||
const { data, headers } = csvFromString.content;
|
||||
expect(headers).toContain('name');
|
||||
expect(headers).toContain('age');
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### CSV Reader Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| -------------- | ------------------ | -------- | -------------------------------------- |
|
||||
| `filePath` | `string` | - | Path to CSV file (mutually exclusive) |
|
||||
| `content` | `string \| Buffer` | - | Direct content (mutually exclusive) |
|
||||
| `delimiter` | `string \| 'auto'` | `','` | Value separator, auto-detect if 'auto' |
|
||||
| `encoding` | `string` | `'utf8'` | File encoding |
|
||||
| `parseHeaders` | `boolean` | `true` | Use first row as headers |
|
||||
| `trim` | `boolean` | `true` | Trim whitespace from values |
|
||||
|
||||
### XLSX Reader Options
|
||||
|
||||
| Option | Type | Description |
|
||||
| ----------- | -------- | ------------------------------ |
|
||||
| `filePath` | `string` | Path to XLSX file |
|
||||
| `sheetName` | `string` | Name of sheet to set as active |
|
||||
|
||||
### PDF Reader Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ------------ | --------- | ------- | --------------------------- |
|
||||
| `filePath` | `string` | - | Path to PDF file (required) |
|
||||
| `mergePages` | `boolean` | `true` | Merge text from all pages |
|
||||
| `maxPages` | `number` | - | Maximum pages to extract |
|
||||
| `debug` | `boolean` | `false` | Enable debug logging |
|
||||
|
||||
### ZIP Reader Options
|
||||
|
||||
| Option | Type | Description |
|
||||
| --------------- | -------- | ---------------------------------- |
|
||||
| `filePath` | `string` | Path to ZIP file |
|
||||
| `fileToExtract` | `string` | Specific file to extract to Buffer |
|
||||
|
||||
### Return Values
|
||||
|
||||
#### CSV Reader Return Value
|
||||
|
||||
```typescript
|
||||
{
|
||||
content: {
|
||||
data: Array<Array<string | number>>, // Parsed rows (excludes header row if parseHeaders: true)
|
||||
headers: string[] | null // Column headers (null if parseHeaders: false)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### XLSX Reader Return Value
|
||||
|
||||
```typescript
|
||||
{
|
||||
content: {
|
||||
worksheets: Array<{
|
||||
name: string, // Sheet name
|
||||
rows: Array<Array<any>>, // All rows including headers
|
||||
headers?: string[] // First row as headers (if present)
|
||||
}>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### PDF Reader Return Value
|
||||
|
||||
```typescript
|
||||
{
|
||||
content: string, // Extracted text (merged or per-page based on mergePages)
|
||||
pagesCount: number, // Total pages in PDF
|
||||
fileName?: string, // Original filename if available
|
||||
info?: Record<string, any> // PDF metadata (author, title, etc.)
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**: When `mergePages: false`, `content` is an array of strings (one per page). When `maxPages` is set, only that many pages are extracted.
|
||||
|
||||
#### ZIP Reader Return Value
|
||||
|
||||
```typescript
|
||||
{
|
||||
content: {
|
||||
entries: Array<{
|
||||
name: string, // File/directory path within ZIP
|
||||
size: number, // Uncompressed size in bytes
|
||||
isDirectory: boolean // True for directories
|
||||
}>,
|
||||
extractedFiles: Record<string, Buffer | string> // Extracted file contents by path
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**: When `fileToExtract` is specified, only that file appears in `extractedFiles`.
|
||||
|
||||
## Download Cleanup Pattern
|
||||
|
||||
```typescript
|
||||
|
|
@ -234,6 +377,66 @@ test.afterEach(async () => {
|
|||
});
|
||||
```
|
||||
|
||||
## Comparison with Vanilla Playwright
|
||||
|
||||
Vanilla Playwright (real test) snippet:
|
||||
|
||||
```typescript
|
||||
// ~80 lines of boilerplate!
|
||||
const [download] = await Promise.all([
|
||||
page.waitForEvent('download'),
|
||||
page.getByTestId('download-button-CSV Export').click(),
|
||||
]);
|
||||
|
||||
const failure = await download.failure();
|
||||
expect(failure).toBeNull();
|
||||
|
||||
const filePath = testInfo.outputPath(download.suggestedFilename());
|
||||
await download.saveAs(filePath);
|
||||
|
||||
await expect
|
||||
.poll(
|
||||
async () => {
|
||||
try {
|
||||
await fs.access(filePath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{ timeout: 5000, intervals: [100, 200, 500] }
|
||||
)
|
||||
.toBe(true);
|
||||
|
||||
const csvContent = await fs.readFile(filePath, 'utf-8');
|
||||
|
||||
const parseResult = parse(csvContent, {
|
||||
header: true,
|
||||
skipEmptyLines: true,
|
||||
dynamicTyping: true,
|
||||
transformHeader: (header: string) => header.trim(),
|
||||
});
|
||||
|
||||
if (parseResult.errors.length > 0) {
|
||||
throw new Error(`CSV parsing errors: ${JSON.stringify(parseResult.errors)}`);
|
||||
}
|
||||
|
||||
const data = parseResult.data as Array<Record<string, unknown>>;
|
||||
const headers = parseResult.meta.fields || [];
|
||||
```
|
||||
|
||||
With File Utils, the same flow becomes:
|
||||
|
||||
```typescript
|
||||
const downloadPath = await handleDownload({
|
||||
page,
|
||||
downloadDir: DOWNLOAD_DIR,
|
||||
trigger: () => page.getByTestId('download-button-text/csv').click(),
|
||||
});
|
||||
|
||||
const { data, headers } = (await readCSV({ filePath: downloadPath })).content;
|
||||
```
|
||||
|
||||
## Related Fragments
|
||||
|
||||
- `overview.md` - Installation and imports
|
||||
|
|
@ -242,7 +445,7 @@ test.afterEach(async () => {
|
|||
|
||||
## Anti-Patterns
|
||||
|
||||
**❌ Not cleaning up downloads:**
|
||||
**DON'T leave downloads in place:**
|
||||
|
||||
```typescript
|
||||
test('creates file', async () => {
|
||||
|
|
@ -251,7 +454,7 @@ test('creates file', async () => {
|
|||
})
|
||||
```
|
||||
|
||||
**✅ Clean up after tests:**
|
||||
**DO clean up after tests:**
|
||||
|
||||
```typescript
|
||||
test.afterEach(async () => {
|
||||
|
|
|
|||
|
|
@ -183,7 +183,31 @@ test('should handle timeout', async ({ page, interceptNetworkCall }) => {
|
|||
- Validate error UI states
|
||||
- No real failures needed
|
||||
|
||||
### Example 5: Multiple Intercepts (Order Matters!)
|
||||
### Example 5: Order Matters - Intercept Before Navigate
|
||||
|
||||
**Context**: The interceptor must be set up before the network request occurs.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// INCORRECT - interceptor set up too late
|
||||
await page.goto('https://example.com'); // Request already happened
|
||||
const networkCall = interceptNetworkCall({ url: '**/api/data' });
|
||||
await networkCall; // Will hang indefinitely!
|
||||
|
||||
// CORRECT - Set up interception first
|
||||
const networkCall = interceptNetworkCall({ url: '**/api/data' });
|
||||
await page.goto('https://example.com');
|
||||
const result = await networkCall;
|
||||
```
|
||||
|
||||
This pattern follows the classic test spy/stub pattern:
|
||||
|
||||
1. Define the spy/stub (set up interception)
|
||||
2. Perform the action (trigger the network request)
|
||||
3. Assert on the spy/stub (await and verify the response)
|
||||
|
||||
### Example 6: Multiple Intercepts
|
||||
|
||||
**Context**: Intercepting different endpoints in same test - setup order is critical.
|
||||
|
||||
|
|
@ -191,7 +215,7 @@ test('should handle timeout', async ({ page, interceptNetworkCall }) => {
|
|||
|
||||
```typescript
|
||||
test('multiple intercepts', async ({ page, interceptNetworkCall }) => {
|
||||
// ✅ CORRECT: Setup all intercepts BEFORE navigation
|
||||
// Setup all intercepts BEFORE navigation
|
||||
const usersCall = interceptNetworkCall({ url: '**/api/users' });
|
||||
const productsCall = interceptNetworkCall({ url: '**/api/products' });
|
||||
const ordersCall = interceptNetworkCall({ url: '**/api/orders' });
|
||||
|
|
@ -211,11 +235,85 @@ test('multiple intercepts', async ({ page, interceptNetworkCall }) => {
|
|||
|
||||
- Setup all intercepts before triggering actions
|
||||
- Use `Promise.all()` to wait for multiple calls
|
||||
- Order: intercept → navigate → await
|
||||
- Order: intercept -> navigate -> await
|
||||
- Prevents race conditions
|
||||
|
||||
### Example 7: Capturing Multiple Requests to the Same Endpoint
|
||||
|
||||
**Context**: Each `interceptNetworkCall` captures only the first matching request.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// Capturing a known number of requests
|
||||
const firstRequest = interceptNetworkCall({ url: '/api/data' });
|
||||
const secondRequest = interceptNetworkCall({ url: '/api/data' });
|
||||
|
||||
await page.click('#load-data-button');
|
||||
|
||||
const firstResponse = await firstRequest;
|
||||
const secondResponse = await secondRequest;
|
||||
|
||||
expect(firstResponse.status).toBe(200);
|
||||
expect(secondResponse.status).toBe(200);
|
||||
|
||||
// Handling an unknown number of requests
|
||||
const getDataRequestInterceptor = () =>
|
||||
interceptNetworkCall({
|
||||
url: '/api/data',
|
||||
timeout: 1000, // Short timeout to detect when no more requests are coming
|
||||
});
|
||||
|
||||
let currentInterceptor = getDataRequestInterceptor();
|
||||
const allResponses = [];
|
||||
|
||||
await page.click('#load-multiple-data-button');
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const response = await currentInterceptor;
|
||||
allResponses.push(response);
|
||||
currentInterceptor = getDataRequestInterceptor();
|
||||
} catch (error) {
|
||||
// No more requests (timeout)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Captured ${allResponses.length} requests to /api/data`);
|
||||
```
|
||||
|
||||
### Example 8: Using Timeout
|
||||
|
||||
**Context**: Set a timeout for waiting on a network request.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
const dataCall = interceptNetworkCall({
|
||||
method: 'GET',
|
||||
url: '/api/data-that-might-be-slow',
|
||||
timeout: 5000, // 5 seconds timeout
|
||||
});
|
||||
|
||||
await page.goto('/data-page');
|
||||
|
||||
try {
|
||||
const { responseJson } = await dataCall;
|
||||
console.log('Data loaded successfully:', responseJson);
|
||||
} catch (error) {
|
||||
if (error.message.includes('timeout')) {
|
||||
console.log('Request timed out as expected');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## URL Pattern Matching
|
||||
|
||||
The utility uses [picomatch](https://github.com/micromatch/picomatch) for powerful glob pattern matching, dramatically simplifying URL targeting:
|
||||
|
||||
**Supported glob patterns:**
|
||||
|
||||
```typescript
|
||||
|
|
@ -226,7 +324,59 @@ test('multiple intercepts', async ({ page, interceptNetworkCall }) => {
|
|||
'**/api/users?id=*'; // With query params
|
||||
```
|
||||
|
||||
**Uses picomatch library** - same pattern syntax as Playwright's `page.route()` but cleaner API.
|
||||
**Comparison with vanilla Playwright:**
|
||||
|
||||
```typescript
|
||||
// Vanilla Playwright - complex predicate
|
||||
const predicate = (response) => {
|
||||
const url = response.url();
|
||||
return (
|
||||
url.endsWith('/api/users') ||
|
||||
url.match(/\/api\/users\/\d+/) ||
|
||||
(url.includes('/api/users/') && url.includes('/profile'))
|
||||
);
|
||||
};
|
||||
page.waitForResponse(predicate);
|
||||
|
||||
// With interceptNetworkCall - simple glob patterns
|
||||
interceptNetworkCall({ url: '/api/users' }); // Exact endpoint
|
||||
interceptNetworkCall({ url: '/api/users/*' }); // User by ID pattern
|
||||
interceptNetworkCall({ url: '/api/users/*/profile' }); // Specific sub-paths
|
||||
interceptNetworkCall({ url: '/api/users/**' }); // Match all
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `interceptNetworkCall(options)`
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| ----------------- | ---------- | --------------------------------------------------------------------- |
|
||||
| `page` | `Page` | Required when using direct import (not needed with fixture) |
|
||||
| `method` | `string` | Optional: HTTP method to match (e.g., 'GET', 'POST') |
|
||||
| `url` | `string` | Optional: URL pattern to match (supports glob patterns via picomatch) |
|
||||
| `fulfillResponse` | `object` | Optional: Response to use when mocking |
|
||||
| `handler` | `function` | Optional: Custom handler function for the route |
|
||||
| `timeout` | `number` | Optional: Timeout in milliseconds for the network request |
|
||||
|
||||
### `fulfillResponse` Object
|
||||
|
||||
| Property | Type | Description |
|
||||
| --------- | ------------------------ | ----------------------------------------------------- |
|
||||
| `status` | `number` | HTTP status code (default: 200) |
|
||||
| `headers` | `Record<string, string>` | Response headers |
|
||||
| `body` | `any` | Response body (will be JSON.stringified if an object) |
|
||||
|
||||
### Return Value
|
||||
|
||||
Returns a `Promise<NetworkCallResult>` with:
|
||||
|
||||
| Property | Type | Description |
|
||||
| -------------- | ---------- | --------------------------------------- |
|
||||
| `request` | `Request` | The intercepted request |
|
||||
| `response` | `Response` | The response (null if mocked) |
|
||||
| `responseJson` | `any` | Parsed JSON response (if available) |
|
||||
| `status` | `number` | HTTP status code |
|
||||
| `requestJson` | `any` | Parsed JSON request body (if available) |
|
||||
|
||||
## Comparison with Vanilla Playwright
|
||||
|
||||
|
|
@ -238,7 +388,7 @@ test('multiple intercepts', async ({ page, interceptNetworkCall }) => {
|
|||
| `const status = resp.status()` | `const { status } = await call` |
|
||||
| Complex filter predicates | Simple glob patterns |
|
||||
|
||||
**Reduction:** ~5-7 lines → ~2-3 lines per interception
|
||||
**Reduction:** ~5-7 lines -> ~2-3 lines per interception
|
||||
|
||||
## Related Fragments
|
||||
|
||||
|
|
@ -248,14 +398,14 @@ test('multiple intercepts', async ({ page, interceptNetworkCall }) => {
|
|||
|
||||
## Anti-Patterns
|
||||
|
||||
**❌ Intercepting after navigation:**
|
||||
**DON'T intercept after navigation:**
|
||||
|
||||
```typescript
|
||||
await page.goto('/dashboard'); // Navigation starts
|
||||
const usersCall = interceptNetworkCall({ url: '**/api/users' }); // Too late!
|
||||
```
|
||||
|
||||
**✅ Intercept before navigate:**
|
||||
**DO intercept before navigate:**
|
||||
|
||||
```typescript
|
||||
const usersCall = interceptNetworkCall({ url: '**/api/users' }); // First
|
||||
|
|
@ -263,7 +413,7 @@ await page.goto('/dashboard'); // Then navigate
|
|||
const { responseJson } = await usersCall; // Then await
|
||||
```
|
||||
|
||||
**❌ Ignoring the returned Promise:**
|
||||
**DON'T ignore the returned Promise:**
|
||||
|
||||
```typescript
|
||||
interceptNetworkCall({ url: '**/api/users' }); // Not awaited!
|
||||
|
|
@ -271,7 +421,7 @@ await page.goto('/dashboard');
|
|||
// No deterministic wait - race condition
|
||||
```
|
||||
|
||||
**✅ Always await the intercept:**
|
||||
**DO always await the intercept:**
|
||||
|
||||
```typescript
|
||||
const usersCall = interceptNetworkCall({ url: '**/api/users' });
|
||||
|
|
|
|||
|
|
@ -21,6 +21,20 @@ The `log` utility provides:
|
|||
- **Multiple levels**: info, step, success, warning, error, debug
|
||||
- **Optional console**: Can disable console output but keep report logs
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
import { log } from '@seontechnologies/playwright-utils';
|
||||
|
||||
// Basic logging
|
||||
await log.info('Starting test');
|
||||
await log.step('Test step shown in Playwright UI');
|
||||
await log.success('Operation completed');
|
||||
await log.warning('Something to note');
|
||||
await log.error('Something went wrong');
|
||||
await log.debug('Debug information');
|
||||
```
|
||||
|
||||
## Pattern Examples
|
||||
|
||||
### Example 1: Basic Logging Levels
|
||||
|
|
@ -143,41 +157,105 @@ test('organized with steps', async ({ page, apiRequest }) => {
|
|||
- Steps visible in Playwright trace viewer
|
||||
- Better debugging when tests fail
|
||||
|
||||
### Example 4: Conditional Logging
|
||||
### Example 4: Test Step Decorators
|
||||
|
||||
**Context**: Log different messages based on environment or test conditions.
|
||||
**Context**: Create collapsible test steps in Playwright UI using decorators.
|
||||
|
||||
**Page Object Methods with @methodTestStep:**
|
||||
|
||||
```typescript
|
||||
import { methodTestStep } from '@seontechnologies/playwright-utils';
|
||||
|
||||
class TodoPage {
|
||||
constructor(private page: Page) {
|
||||
this.name = 'TodoPage';
|
||||
}
|
||||
|
||||
readonly name: string;
|
||||
|
||||
@methodTestStep('Add todo item')
|
||||
async addTodo(text: string) {
|
||||
await log.info(`Adding todo: ${text}`);
|
||||
const newTodo = this.page.getByPlaceholder('What needs to be done?');
|
||||
await newTodo.fill(text);
|
||||
await newTodo.press('Enter');
|
||||
await log.step('step within a decorator');
|
||||
await log.success(`Added todo: ${text}`);
|
||||
}
|
||||
|
||||
@methodTestStep('Get all todos')
|
||||
async getTodos() {
|
||||
await log.info('Getting all todos');
|
||||
return this.page.getByTestId('todo-title');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Function Helpers with functionTestStep:**
|
||||
|
||||
```typescript
|
||||
import { functionTestStep } from '@seontechnologies/playwright-utils';
|
||||
|
||||
// Define todo items for the test
|
||||
const TODO_ITEMS = ['buy groceries', 'pay bills', 'schedule meeting'];
|
||||
|
||||
const createDefaultTodos = functionTestStep('Create default todos', async (page: Page) => {
|
||||
await log.info('Creating default todos');
|
||||
await log.step('step within a functionWrapper');
|
||||
const todoPage = new TodoPage(page);
|
||||
|
||||
for (const item of TODO_ITEMS) {
|
||||
await todoPage.addTodo(item);
|
||||
}
|
||||
|
||||
await log.success('Created all default todos');
|
||||
});
|
||||
|
||||
const checkNumberOfTodosInLocalStorage = functionTestStep(
|
||||
'Check total todos count fn-step',
|
||||
async (page: Page, expected: number) => {
|
||||
await log.info(`Verifying todo count: ${expected}`);
|
||||
const result = await page.waitForFunction(
|
||||
(e) => JSON.parse(localStorage['react-todos']).length === e,
|
||||
expected
|
||||
);
|
||||
await log.success(`Verified todo count: ${expected}`);
|
||||
return result;
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Example 5: File Logging
|
||||
|
||||
**Context**: Enable file logging for persistent logs.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
test('conditional logging', async ({ page }) => {
|
||||
const isCI = process.env.CI === 'true';
|
||||
// playwright/support/fixtures.ts
|
||||
import { test as base } from '@playwright/test';
|
||||
import { log, captureTestContext } from '@seontechnologies/playwright-utils';
|
||||
|
||||
if (isCI) {
|
||||
await log.info('Running in CI environment');
|
||||
} else {
|
||||
await log.debug('Running locally');
|
||||
}
|
||||
// Configure file logging globally
|
||||
log.configure({
|
||||
fileLogging: {
|
||||
enabled: true,
|
||||
outputDir: 'playwright-logs/organized-logs',
|
||||
forceConsolidated: false, // One file per test
|
||||
},
|
||||
});
|
||||
|
||||
const isKafkaWorking = await checkKafkaHealth();
|
||||
|
||||
if (!isKafkaWorking) {
|
||||
await log.warning('Kafka unavailable - skipping event checks');
|
||||
} else {
|
||||
await log.step('Verifying Kafka events');
|
||||
// ... event verification
|
||||
}
|
||||
// Extend base test with file logging context capture
|
||||
export const test = base.extend({
|
||||
// Auto-capture test context for file logging
|
||||
autoTestContext: [async ({}, use, testInfo) => {
|
||||
captureTestContext(testInfo);
|
||||
await use(undefined);
|
||||
}, { auto: true }],
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Log based on environment
|
||||
- Skip logging with conditionals
|
||||
- Use appropriate log levels
|
||||
- Debug info for local, minimal for CI
|
||||
|
||||
### Example 5: Integration with Auth and API
|
||||
### Example 6: Integration with Auth and API
|
||||
|
||||
**Context**: Log authenticated API requests with tokens (safely).
|
||||
|
||||
|
|
@ -221,16 +299,73 @@ test('should log auth flow', async ({ authToken, apiRequest }) => {
|
|||
- Combine with auth and API utilities
|
||||
- Log at appropriate detail level
|
||||
|
||||
## Configuration
|
||||
|
||||
**Defaults:** console logging enabled, file logging disabled.
|
||||
|
||||
```typescript
|
||||
// Enable file logging in config
|
||||
log.configure({
|
||||
console: true, // default
|
||||
fileLogging: {
|
||||
enabled: true,
|
||||
outputDir: 'playwright-logs',
|
||||
forceConsolidated: false, // One file per test
|
||||
},
|
||||
});
|
||||
|
||||
// Per-test override
|
||||
await log.info('Message', {
|
||||
console: { enabled: false },
|
||||
fileLogging: { enabled: true },
|
||||
});
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
# Disable all logging
|
||||
SILENT=true
|
||||
|
||||
# Disable only file logging
|
||||
DISABLE_FILE_LOGS=true
|
||||
|
||||
# Disable only console logging
|
||||
DISABLE_CONSOLE_LOGS=true
|
||||
```
|
||||
|
||||
### Level Filtering
|
||||
|
||||
```typescript
|
||||
log.configure({
|
||||
level: 'warning', // Only warning, error levels will show
|
||||
});
|
||||
|
||||
// Available levels (in priority order):
|
||||
// debug < info < step < success < warning < error
|
||||
```
|
||||
|
||||
### Sync Methods
|
||||
|
||||
For non-test contexts (global setup, utility functions):
|
||||
|
||||
```typescript
|
||||
// Use sync methods when async/await isn't available
|
||||
log.infoSync('Initializing configuration');
|
||||
log.successSync('Environment configured');
|
||||
log.errorSync('Setup failed');
|
||||
```
|
||||
|
||||
## Log Levels Guide
|
||||
|
||||
| Level | When to Use | Shows in Report | Shows in Console |
|
||||
| --------- | ----------------------------------- | -------------------- | ---------------- |
|
||||
| `step` | Test organization, major actions | ✅ Collapsible steps | ✅ Yes |
|
||||
| `info` | General information, state changes | ✅ Yes | ✅ Yes |
|
||||
| `success` | Successful operations | ✅ Yes | ✅ Yes |
|
||||
| `warning` | Non-critical issues, skipped checks | ✅ Yes | ✅ Yes |
|
||||
| `error` | Failures, exceptions | ✅ Yes | ✅ Configurable |
|
||||
| `debug` | Detailed data, objects | ✅ Yes (attached) | ✅ Configurable |
|
||||
| --------- | ----------------------------------- | ----------------- | ---------------- |
|
||||
| `step` | Test organization, major actions | Collapsible steps | Yes |
|
||||
| `info` | General information, state changes | Yes | Yes |
|
||||
| `success` | Successful operations | Yes | Yes |
|
||||
| `warning` | Non-critical issues, skipped checks | Yes | Yes |
|
||||
| `error` | Failures, exceptions | Yes | Configurable |
|
||||
| `debug` | Detailed data, objects | Yes (attached) | Configurable |
|
||||
|
||||
## Comparison with console.log
|
||||
|
||||
|
|
@ -251,34 +386,34 @@ test('should log auth flow', async ({ authToken, apiRequest }) => {
|
|||
|
||||
## Anti-Patterns
|
||||
|
||||
**❌ Logging objects in steps:**
|
||||
**DON'T log objects in steps:**
|
||||
|
||||
```typescript
|
||||
await log.step({ user: 'test', action: 'create' }); // Shows empty in UI
|
||||
```
|
||||
|
||||
**✅ Use strings for steps, objects for debug:**
|
||||
**DO use strings for steps, objects for debug:**
|
||||
|
||||
```typescript
|
||||
await log.step('Creating user: test'); // Readable in UI
|
||||
await log.debug({ user: 'test', action: 'create' }); // Detailed data
|
||||
```
|
||||
|
||||
**❌ Logging sensitive data:**
|
||||
**DON'T log sensitive data:**
|
||||
|
||||
```typescript
|
||||
await log.info(`Password: ${password}`); // Security risk!
|
||||
await log.info(`Token: ${authToken}`); // Full token exposed!
|
||||
```
|
||||
|
||||
**✅ Use previews or omit sensitive data:**
|
||||
**DO use previews or omit sensitive data:**
|
||||
|
||||
```typescript
|
||||
await log.info('User authenticated successfully'); // No sensitive data
|
||||
await log.debug({ tokenPreview: token.slice(0, 6) + '...' });
|
||||
```
|
||||
|
||||
**❌ Excessive logging in loops:**
|
||||
**DON'T log excessively in loops:**
|
||||
|
||||
```typescript
|
||||
for (const item of items) {
|
||||
|
|
@ -286,7 +421,7 @@ for (const item of items) {
|
|||
}
|
||||
```
|
||||
|
||||
**✅ Log summary or use debug level:**
|
||||
**DO log summary or use debug level:**
|
||||
|
||||
```typescript
|
||||
await log.step(`Processing ${items.length} items`);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,19 @@ The `network-error-monitor` provides:
|
|||
- **Smart opt-out**: Disable for validation tests expecting errors
|
||||
- **Deduplication**: Group repeated errors by pattern
|
||||
- **Domino effect prevention**: Limit test failures per error pattern
|
||||
- **Respects test status**: Won't suppress actual test failures
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
import { test } from '@seontechnologies/playwright-utils/network-error-monitor/fixtures';
|
||||
|
||||
// That's it! Network monitoring is automatically enabled
|
||||
test('my test', async ({ page }) => {
|
||||
await page.goto('/dashboard');
|
||||
// If any HTTP 4xx/5xx errors occur, the test will fail
|
||||
});
|
||||
```
|
||||
|
||||
## Pattern Examples
|
||||
|
||||
|
|
@ -38,8 +51,8 @@ test('should load dashboard', async ({ page }) => {
|
|||
await page.goto('/dashboard');
|
||||
await expect(page.locator('h1')).toContainText('Dashboard');
|
||||
|
||||
// ✅ Passes if no HTTP errors
|
||||
// ❌ Fails if any 4xx/5xx errors detected with clear message:
|
||||
// Passes if no HTTP errors
|
||||
// Fails if any 4xx/5xx errors detected with clear message:
|
||||
// "Network errors detected: 2 request(s) failed"
|
||||
// Failed requests:
|
||||
// GET 500 https://api.example.com/users
|
||||
|
|
@ -64,13 +77,17 @@ test('should load dashboard', async ({ page }) => {
|
|||
import { test } from '@seontechnologies/playwright-utils/network-error-monitor/fixtures';
|
||||
|
||||
// Opt-out with annotation
|
||||
test('should show error on invalid input', { annotation: [{ type: 'skipNetworkMonitoring' }] }, async ({ page }) => {
|
||||
test(
|
||||
'should show error on invalid input',
|
||||
{ annotation: [{ type: 'skipNetworkMonitoring' }] },
|
||||
async ({ page }) => {
|
||||
await page.goto('/form');
|
||||
await page.click('#submit'); // Triggers 400 error
|
||||
|
||||
// Monitoring disabled - test won't fail on 400
|
||||
await expect(page.getByText('Invalid input')).toBeVisible();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// Or opt-out entire describe block
|
||||
test.describe('error handling', { annotation: [{ type: 'skipNetworkMonitoring' }] }, () => {
|
||||
|
|
@ -91,7 +108,139 @@ test.describe('error handling', { annotation: [{ type: 'skipNetworkMonitoring' }
|
|||
- Monitoring still active for other tests
|
||||
- Perfect for intentional error scenarios
|
||||
|
||||
### Example 3: Integration with Merged Fixtures
|
||||
### Example 3: Respects Test Status
|
||||
|
||||
**Context**: The monitor respects final test statuses to avoid suppressing important test outcomes.
|
||||
|
||||
**Behavior by test status:**
|
||||
|
||||
- **`failed`**: Network errors logged as additional context, not thrown
|
||||
- **`timedOut`**: Network errors logged as additional context
|
||||
- **`skipped`**: Network errors logged, skip status preserved
|
||||
- **`interrupted`**: Network errors logged, interrupted status preserved
|
||||
- **`passed`**: Network errors throw and fail the test
|
||||
|
||||
**Example with test.skip():**
|
||||
|
||||
```typescript
|
||||
test('feature gated test', async ({ page }) => {
|
||||
const featureEnabled = await checkFeatureFlag();
|
||||
test.skip(!featureEnabled, 'Feature not enabled');
|
||||
// If skipped, network errors won't turn this into a failure
|
||||
await page.goto('/new-feature');
|
||||
});
|
||||
```
|
||||
|
||||
### Example 4: Excluding Legitimate Errors
|
||||
|
||||
**Context**: Some endpoints legitimately return 4xx/5xx responses.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
import { test as base } from '@playwright/test';
|
||||
import { createNetworkErrorMonitorFixture } from '@seontechnologies/playwright-utils/network-error-monitor/fixtures';
|
||||
|
||||
export const test = base.extend(
|
||||
createNetworkErrorMonitorFixture({
|
||||
excludePatterns: [
|
||||
/email-cluster\/ml-app\/has-active-run/, // ML service returns 404 when no active run
|
||||
/idv\/session-templates\/list/, // IDV service returns 404 when not configured
|
||||
/sentry\.io\/api/, // External Sentry errors should not fail tests
|
||||
],
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
**For merged fixtures:**
|
||||
|
||||
```typescript
|
||||
import { test as base, mergeTests } from '@playwright/test';
|
||||
import { createNetworkErrorMonitorFixture } from '@seontechnologies/playwright-utils/network-error-monitor/fixtures';
|
||||
|
||||
const networkErrorMonitor = base.extend(
|
||||
createNetworkErrorMonitorFixture({
|
||||
excludePatterns: [/analytics\.google\.com/, /cdn\.example\.com/],
|
||||
})
|
||||
);
|
||||
|
||||
export const test = mergeTests(authFixture, networkErrorMonitor);
|
||||
```
|
||||
|
||||
### Example 5: Preventing Domino Effect
|
||||
|
||||
**Context**: One failing endpoint shouldn't fail all tests.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
import { test as base } from '@playwright/test';
|
||||
import { createNetworkErrorMonitorFixture } from '@seontechnologies/playwright-utils/network-error-monitor/fixtures';
|
||||
|
||||
const networkErrorMonitor = base.extend(
|
||||
createNetworkErrorMonitorFixture({
|
||||
excludePatterns: [], // Required when using maxTestsPerError
|
||||
maxTestsPerError: 1, // Only first test fails per error pattern, rest just log
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
**How it works:**
|
||||
|
||||
When `/api/v2/case-management/cases` returns 500:
|
||||
|
||||
- **First test** encountering this error: **FAILS** with clear error message
|
||||
- **Subsequent tests** encountering same error: **PASSES** but logs warning
|
||||
|
||||
Error patterns are grouped by `method + status + base path`:
|
||||
|
||||
- `GET /api/v2/case-management/cases/123` -> Pattern: `GET:500:/api/v2/case-management`
|
||||
- `GET /api/v2/case-management/quota` -> Pattern: `GET:500:/api/v2/case-management` (same group!)
|
||||
- `POST /api/v2/case-management/cases` -> Pattern: `POST:500:/api/v2/case-management` (different group!)
|
||||
|
||||
**Why include HTTP method?** A GET 404 vs POST 404 might represent different issues:
|
||||
|
||||
- `GET 404 /api/users/123` -> User not found (expected in some tests)
|
||||
- `POST 404 /api/users` -> Endpoint doesn't exist (critical error)
|
||||
|
||||
**Output for subsequent tests:**
|
||||
|
||||
```
|
||||
Warning: Network errors detected but not failing test (maxTestsPerError limit reached):
|
||||
GET 500 https://api.example.com/api/v2/case-management/cases
|
||||
```
|
||||
|
||||
**Recommended configuration:**
|
||||
|
||||
```typescript
|
||||
createNetworkErrorMonitorFixture({
|
||||
excludePatterns: [...], // Required - known broken endpoints (can be empty [])
|
||||
maxTestsPerError: 1 // Stop domino effect (requires excludePatterns)
|
||||
})
|
||||
```
|
||||
|
||||
**Understanding worker-level state:**
|
||||
|
||||
Error pattern counts are stored in worker-level global state:
|
||||
|
||||
```typescript
|
||||
// test-file-1.spec.ts (runs in Worker 1)
|
||||
test('test A', () => {
|
||||
/* triggers GET:500:/api/v2/cases */
|
||||
}); // FAILS
|
||||
|
||||
// test-file-2.spec.ts (runs later in Worker 1)
|
||||
test('test B', () => {
|
||||
/* triggers GET:500:/api/v2/cases */
|
||||
}); // PASSES (limit reached)
|
||||
|
||||
// test-file-3.spec.ts (runs in Worker 2 - different worker)
|
||||
test('test C', () => {
|
||||
/* triggers GET:500:/api/v2/cases */
|
||||
}); // FAILS (fresh worker)
|
||||
```
|
||||
|
||||
### Example 6: Integration with Merged Fixtures
|
||||
|
||||
**Context**: Combine network-error-monitor with other utilities.
|
||||
|
||||
|
|
@ -105,7 +254,7 @@ import { test as networkErrorMonitorFixture } from '@seontechnologies/playwright
|
|||
|
||||
export const test = mergeTests(
|
||||
authFixture,
|
||||
networkErrorMonitorFixture,
|
||||
networkErrorMonitorFixture
|
||||
// Add other fixtures
|
||||
);
|
||||
|
||||
|
|
@ -127,110 +276,94 @@ test('authenticated with monitoring', async ({ page, authToken }) => {
|
|||
- Monitoring active automatically
|
||||
- No extra setup needed
|
||||
|
||||
### Example 4: Domino Effect Prevention
|
||||
|
||||
**Context**: One failing endpoint shouldn't fail all tests.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// Configuration (internal to utility)
|
||||
const config = {
|
||||
maxTestsPerError: 3, // Max 3 tests fail per unique error pattern
|
||||
};
|
||||
|
||||
// Scenario:
|
||||
// Test 1: GET /api/broken → 500 error → Test fails ❌
|
||||
// Test 2: GET /api/broken → 500 error → Test fails ❌
|
||||
// Test 3: GET /api/broken → 500 error → Test fails ❌
|
||||
// Test 4: GET /api/broken → 500 error → Test passes ⚠️ (limit reached, warning logged)
|
||||
// Test 5: Different error pattern → Test fails ❌ (new pattern, counter resets)
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Limits cascading failures
|
||||
- Groups errors by URL + status code pattern
|
||||
- Warns when limit reached
|
||||
- Prevents flaky backend from failing entire suite
|
||||
|
||||
### Example 5: Artifact Structure
|
||||
### Example 7: Artifact Structure
|
||||
|
||||
**Context**: Debugging failed tests with network error artifacts.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
When test fails due to network errors, artifact attached:
|
||||
|
||||
```json
|
||||
// test-results/my-test/network-errors.json
|
||||
{
|
||||
"errors": [
|
||||
[
|
||||
{
|
||||
"url": "https://api.example.com/users",
|
||||
"method": "GET",
|
||||
"status": 500,
|
||||
"statusText": "Internal Server Error",
|
||||
"timestamp": "2024-08-13T10:30:45.123Z"
|
||||
"method": "GET",
|
||||
"timestamp": "2025-11-10T12:34:56.789Z"
|
||||
},
|
||||
{
|
||||
"url": "https://api.example.com/metrics",
|
||||
"method": "POST",
|
||||
"status": 503,
|
||||
"statusText": "Service Unavailable",
|
||||
"timestamp": "2024-08-13T10:30:46.456Z"
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"totalErrors": 2,
|
||||
"uniquePatterns": 2
|
||||
}
|
||||
"method": "POST",
|
||||
"timestamp": "2025-11-10T12:34:57.123Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
## Implementation Details
|
||||
|
||||
- JSON artifact per failed test
|
||||
- Full error details (URL, method, status, timestamp)
|
||||
- Summary statistics
|
||||
- Easy debugging with structured data
|
||||
### How It Works
|
||||
|
||||
## Comparison with Manual Error Checks
|
||||
1. **Fixture Extension**: Uses Playwright's `base.extend()` with `auto: true`
|
||||
2. **Response Listener**: Attaches `page.on('response')` listener at test start
|
||||
3. **Multi-Page Monitoring**: Automatically monitors popups and new tabs via `context.on('page')`
|
||||
4. **Error Collection**: Captures 4xx/5xx responses, checking exclusion patterns
|
||||
5. **Try/Finally**: Ensures error processing runs even if test fails early
|
||||
6. **Status Check**: Only throws errors if test hasn't already reached final status
|
||||
7. **Artifact**: Attaches JSON file to test report for debugging
|
||||
|
||||
| Manual Approach | network-error-monitor |
|
||||
| ------------------------------------------------------ | -------------------------- |
|
||||
| `page.on('response', resp => { if (!resp.ok()) ... })` | Auto-enabled, zero setup |
|
||||
| Check each response manually | Automatic for all requests |
|
||||
| Custom error tracking logic | Built-in deduplication |
|
||||
| No structured artifacts | JSON artifacts attached |
|
||||
| Easy to forget | Never miss a backend error |
|
||||
### Performance
|
||||
|
||||
The monitor has minimal performance impact:
|
||||
|
||||
- Event listener overhead: ~0.1ms per response
|
||||
- Memory: ~200 bytes per unique error
|
||||
- No network delay (observes responses, doesn't intercept them)
|
||||
|
||||
## Comparison with Alternatives
|
||||
|
||||
| Approach | Network Error Monitor | Manual afterEach |
|
||||
| --------------------------- | --------------------- | --------------------- |
|
||||
| **Setup Required** | Zero (auto-enabled) | Every test file |
|
||||
| **Catches Silent Failures** | Yes | Yes (if configured) |
|
||||
| **Structured Artifacts** | JSON attached | Custom impl |
|
||||
| **Test Failure Safety** | Try/finally | afterEach may not run |
|
||||
| **Opt-Out Mechanism** | Annotation | Custom logic |
|
||||
| **Status Aware** | Respects skip/failed | No |
|
||||
|
||||
## When to Use
|
||||
|
||||
**Auto-enabled for:**
|
||||
|
||||
- ✅ All E2E tests
|
||||
- ✅ Integration tests
|
||||
- ✅ Any test hitting real APIs
|
||||
- All E2E tests
|
||||
- Integration tests
|
||||
- Any test hitting real APIs
|
||||
|
||||
**Opt-out for:**
|
||||
|
||||
- ❌ Validation tests (expecting 4xx)
|
||||
- ❌ Error handling tests (expecting 5xx)
|
||||
- ❌ Offline tests (network-recorder playback)
|
||||
- Validation tests (expecting 4xx)
|
||||
- Error handling tests (expecting 5xx)
|
||||
- Offline tests (network-recorder playback)
|
||||
|
||||
## Integration with Framework Setup
|
||||
## Troubleshooting
|
||||
|
||||
In `*framework` workflow, mention network-error-monitor:
|
||||
### Test fails with network errors but I don't see them in my app
|
||||
|
||||
The errors might be happening during page load or in background polling. Check the `network-errors.json` artifact in your test report for full details including timestamps.
|
||||
|
||||
### False positives from external services
|
||||
|
||||
Configure exclusion patterns as shown in the "Excluding Legitimate Errors" section above.
|
||||
|
||||
### Network errors not being caught
|
||||
|
||||
Ensure you're importing the test from the correct fixture:
|
||||
|
||||
```typescript
|
||||
// Add to merged-fixtures.ts
|
||||
import { test as networkErrorMonitorFixture } from '@seontechnologies/playwright-utils/network-error-monitor/fixtures';
|
||||
// Correct
|
||||
import { test } from '@seontechnologies/playwright-utils/network-error-monitor/fixtures';
|
||||
|
||||
export const test = mergeTests(
|
||||
// ... other fixtures
|
||||
networkErrorMonitorFixture,
|
||||
);
|
||||
// Wrong - this won't have network monitoring
|
||||
import { test } from '@playwright/test';
|
||||
```
|
||||
|
||||
## Related Fragments
|
||||
|
|
@ -241,14 +374,14 @@ export const test = mergeTests(
|
|||
|
||||
## Anti-Patterns
|
||||
|
||||
**❌ Opting out of monitoring globally:**
|
||||
**DON'T opt out of monitoring globally:**
|
||||
|
||||
```typescript
|
||||
// Every test skips monitoring
|
||||
test.use({ annotation: [{ type: 'skipNetworkMonitoring' }] });
|
||||
```
|
||||
|
||||
**✅ Opt-out only for specific error tests:**
|
||||
**DO opt-out only for specific error tests:**
|
||||
|
||||
```typescript
|
||||
test.describe('error scenarios', { annotation: [{ type: 'skipNetworkMonitoring' }] }, () => {
|
||||
|
|
@ -256,17 +389,17 @@ test.describe('error scenarios', { annotation: [{ type: 'skipNetworkMonitoring'
|
|||
});
|
||||
```
|
||||
|
||||
**❌ Ignoring network error artifacts:**
|
||||
**DON'T ignore network error artifacts:**
|
||||
|
||||
```typescript
|
||||
// Test fails, artifact shows 500 errors
|
||||
// Developer: "Works on my machine" ¯\_(ツ)_/¯
|
||||
```
|
||||
|
||||
**✅ Check artifacts for root cause:**
|
||||
**DO check artifacts for root cause:**
|
||||
|
||||
```typescript
|
||||
// Read network-errors.json artifact
|
||||
// Identify failing endpoint: GET /api/users → 500
|
||||
// Identify failing endpoint: GET /api/users -> 500
|
||||
// Fix backend issue before merging
|
||||
```
|
||||
|
|
|
|||
|
|
@ -21,6 +21,46 @@ HAR-based recording/playback provides:
|
|||
- **Stateful mocking**: CRUD operations work naturally (not just read-only)
|
||||
- **Environment flexibility**: Map URLs for any environment
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Record Network Traffic
|
||||
|
||||
```typescript
|
||||
// Set mode to 'record' to capture network traffic
|
||||
process.env.PW_NET_MODE = 'record';
|
||||
|
||||
test('should add, edit and delete a movie', async ({ page, context, networkRecorder }) => {
|
||||
// Setup network recorder - it will record all network traffic
|
||||
await networkRecorder.setup(context);
|
||||
|
||||
// Your normal test code
|
||||
await page.goto('/');
|
||||
await page.fill('#movie-name', 'Inception');
|
||||
await page.click('#add-movie');
|
||||
|
||||
// Network traffic is automatically saved to HAR file
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Playback Network Traffic
|
||||
|
||||
```typescript
|
||||
// Set mode to 'playback' to use recorded traffic
|
||||
process.env.PW_NET_MODE = 'playback';
|
||||
|
||||
test('should add, edit and delete a movie', async ({ page, context, networkRecorder }) => {
|
||||
// Setup network recorder - it will replay from HAR file
|
||||
await networkRecorder.setup(context);
|
||||
|
||||
// Same test code runs without hitting real backend!
|
||||
await page.goto('/');
|
||||
await page.fill('#movie-name', 'Inception');
|
||||
await page.click('#add-movie');
|
||||
});
|
||||
```
|
||||
|
||||
That's it! Your tests now run completely offline using recorded network traffic.
|
||||
|
||||
## Pattern Examples
|
||||
|
||||
### Example 1: Basic Record and Playback
|
||||
|
|
@ -115,74 +155,173 @@ test.describe('Movie CRUD - offline with network recorder', () => {
|
|||
- Combine with `interceptNetworkCall` for deterministic waits
|
||||
- First run records, subsequent runs replay
|
||||
|
||||
### Example 3: Environment Switching
|
||||
### Example 3: Common Patterns
|
||||
|
||||
**Recording Only API Calls**:
|
||||
|
||||
```typescript
|
||||
await networkRecorder.setup(context, {
|
||||
recording: {
|
||||
urlFilter: /\/api\// // Only record API calls, ignore static assets
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Playback with Fallback**:
|
||||
|
||||
```typescript
|
||||
await networkRecorder.setup(context, {
|
||||
playback: {
|
||||
fallback: true // Fall back to live requests if HAR entry missing
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Custom HAR File Location**:
|
||||
|
||||
```typescript
|
||||
await networkRecorder.setup(context, {
|
||||
harFile: {
|
||||
harDir: 'recordings/api-calls',
|
||||
baseName: 'user-journey',
|
||||
organizeByTestFile: false // Optional: flatten directory structure
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Directory Organization:**
|
||||
|
||||
- `organizeByTestFile: true` (default): `har-files/test-file-name/baseName-test-title.har`
|
||||
- `organizeByTestFile: false`: `har-files/baseName-test-title.har`
|
||||
|
||||
### Example 4: Response Content Storage - Embed vs Attach
|
||||
|
||||
**Context**: Choose how response content is stored in HAR files.
|
||||
|
||||
**`embed` (Default - Recommended):**
|
||||
|
||||
```typescript
|
||||
await networkRecorder.setup(context, {
|
||||
recording: {
|
||||
content: 'embed' // Store content inline (default)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Single self-contained file - Easy to share, version control
|
||||
- Better for small-medium responses (API JSON, HTML pages)
|
||||
- HAR specification compliant
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Larger HAR files
|
||||
- Not ideal for large binary content (images, videos)
|
||||
|
||||
**`attach` (Alternative):**
|
||||
|
||||
```typescript
|
||||
await networkRecorder.setup(context, {
|
||||
recording: {
|
||||
content: 'attach' // Store content separately
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Smaller HAR files
|
||||
- Better for large responses (images, videos, documents)
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Multiple files to manage
|
||||
- Harder to share
|
||||
|
||||
**When to Use Each:**
|
||||
|
||||
| Use `embed` (default) when | Use `attach` when |
|
||||
|---------------------------|-------------------|
|
||||
| Recording API responses (JSON, XML) | Recording large images, videos |
|
||||
| Small to medium HTML pages | HAR file size >50MB |
|
||||
| You want a single, portable file | Maximum disk efficiency needed |
|
||||
| Sharing HAR files with team | Working with ZIP archive output |
|
||||
|
||||
### Example 5: Cross-Environment Compatibility (URL Mapping)
|
||||
|
||||
**Context**: Record in dev environment, play back in CI with different base URLs.
|
||||
|
||||
**Implementation**:
|
||||
**The Problem**: HAR files contain URLs for the recording environment (e.g., `dev.example.com`). Playing back on a different environment fails.
|
||||
|
||||
**Simple Hostname Mapping:**
|
||||
|
||||
```typescript
|
||||
// playwright.config.ts - Map URLs for different environments
|
||||
export default defineConfig({
|
||||
use: {
|
||||
baseURL: process.env.CI ? 'https://app.ci.example.com' : 'http://localhost:3000',
|
||||
await networkRecorder.setup(context, {
|
||||
playback: {
|
||||
urlMapping: {
|
||||
hostMapping: {
|
||||
'preview.example.com': 'dev.example.com',
|
||||
'staging.example.com': 'dev.example.com',
|
||||
'localhost:3000': 'dev.example.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Pattern-Based Mapping (Recommended):**
|
||||
|
||||
```typescript
|
||||
await networkRecorder.setup(context, {
|
||||
playback: {
|
||||
urlMapping: {
|
||||
patterns: [
|
||||
// Map any preview-XXXX subdomain to dev
|
||||
{ match: /preview-\d+\.example\.com/, replace: 'dev.example.com' }
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Custom Function:**
|
||||
|
||||
```typescript
|
||||
await networkRecorder.setup(context, {
|
||||
playback: {
|
||||
urlMapping: {
|
||||
mapUrl: (url) => url.replace('staging.example.com', 'dev.example.com')
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Complex Multi-Environment Example:**
|
||||
|
||||
```typescript
|
||||
await networkRecorder.setup(context, {
|
||||
playback: {
|
||||
urlMapping: {
|
||||
hostMapping: {
|
||||
'localhost:3000': 'admin.seondev.space',
|
||||
'admin-staging.seon.io': 'admin.seondev.space',
|
||||
'admin.seon.io': 'admin.seondev.space',
|
||||
},
|
||||
});
|
||||
|
||||
// Test works in both environments
|
||||
test('cross-environment playback', async ({ page, context, networkRecorder }) => {
|
||||
await networkRecorder.setup(context);
|
||||
|
||||
// In dev: hits http://localhost:3000/api/movies
|
||||
// In CI: HAR replays with https://app.ci.example.com/api/movies
|
||||
await page.goto('/movies');
|
||||
|
||||
// Network recorder auto-maps URLs
|
||||
await expect(page.getByTestId('movie-list')).toBeVisible();
|
||||
patterns: [
|
||||
{ match: /admin-\d+\.seondev\.space/, replace: 'admin.seondev.space' },
|
||||
{ match: /admin-staging-pr-\w+-\d\.seon\.io/, replace: 'admin.seondev.space' }
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
**Benefits:**
|
||||
|
||||
- HAR files record absolute URLs
|
||||
- Playback maps to current baseURL
|
||||
- Same HAR works across environments
|
||||
- No manual URL rewriting needed
|
||||
|
||||
### Example 4: Automatic vs Manual Mode Control
|
||||
|
||||
**Context**: Choose between environment-based switching or in-test mode control.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
// Option 1: Environment variable (recommended for CI)
|
||||
PW_NET_MODE=record npm run test:pw # Record traffic
|
||||
PW_NET_MODE=playback npm run test:pw # Playback traffic
|
||||
|
||||
// Option 2: In-test control (recommended for development)
|
||||
process.env.PW_NET_MODE = 'record' // Set at top of test file
|
||||
|
||||
test('my test', async ({ page, context, networkRecorder }) => {
|
||||
await networkRecorder.setup(context)
|
||||
// ...
|
||||
})
|
||||
|
||||
// Option 3: Auto-fallback (record if HAR missing, else playback)
|
||||
// This is the default behavior when PW_NET_MODE not set
|
||||
test('auto mode', async ({ page, context, networkRecorder }) => {
|
||||
await networkRecorder.setup(context)
|
||||
// First run: auto-records
|
||||
// Subsequent runs: auto-plays back
|
||||
})
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- Three mode options: record, playback, auto
|
||||
- `PW_NET_MODE` environment variable
|
||||
- In-test `process.env.PW_NET_MODE` assignment
|
||||
- Auto-fallback when no mode specified
|
||||
- Record once on dev, all environments map back to recordings
|
||||
- CORS headers automatically updated based on request origin
|
||||
- Debug with: `LOG_LEVEL=debug npm run test`
|
||||
|
||||
## Why Use This Instead of Native Playwright?
|
||||
|
||||
|
|
@ -191,7 +330,7 @@ test('auto mode', async ({ page, context, networkRecorder }) => {
|
|||
| ~80 lines setup boilerplate | ~5 lines total |
|
||||
| Manual HAR file management | Automatic file organization |
|
||||
| Complex setup/teardown | Automatic cleanup via fixtures |
|
||||
| **Read-only tests** | **Full CRUD support** |
|
||||
| **Read-only tests only** | **Full CRUD support** |
|
||||
| **Stateless** | **Stateful mocking** |
|
||||
| Manual URL mapping | Automatic environment mapping |
|
||||
|
||||
|
|
@ -199,9 +338,132 @@ test('auto mode', async ({ page, context, networkRecorder }) => {
|
|||
|
||||
Native Playwright HAR playback is stateless - a POST create followed by GET list won't show the created item. This utility intelligently tracks CRUD operations in memory to reflect state changes, making offline tests behave like real APIs.
|
||||
|
||||
## How Stateful CRUD Detection Works
|
||||
|
||||
When in playback mode, the Network Recorder automatically analyzes your HAR file to detect CRUD patterns. If it finds:
|
||||
|
||||
- Multiple GET requests to the same resource endpoint (e.g., `/movies`)
|
||||
- Mutation operations (POST, PUT, DELETE) to those resources
|
||||
- Evidence of state changes between identical requests
|
||||
|
||||
It automatically switches from static HAR playback to an intelligent stateful mock that:
|
||||
|
||||
- Maintains state across requests
|
||||
- Auto-generates IDs for new resources
|
||||
- Returns proper 404s for deleted resources
|
||||
- Supports polling scenarios where state changes over time
|
||||
|
||||
**This happens automatically - no configuration needed!**
|
||||
|
||||
## API Reference
|
||||
|
||||
### NetworkRecorder Methods
|
||||
|
||||
| Method | Return Type | Description |
|
||||
| -------------------- | ------------------------ | ----------------------------------------------------- |
|
||||
| `setup(context)` | `Promise<void>` | Sets up recording/playback on browser context |
|
||||
| `cleanup()` | `Promise<void>` | Flushes data to disk and cleans up memory |
|
||||
| `getContext()` | `NetworkRecorderContext` | Gets current recorder context information |
|
||||
| `getStatusMessage()` | `string` | Gets human-readable status message |
|
||||
| `getHarStats()` | `Promise<HarFileStats>` | Gets HAR file statistics and metadata |
|
||||
|
||||
### Understanding `cleanup()`
|
||||
|
||||
The `cleanup()` method performs memory and resource cleanup - **it does NOT delete HAR files**:
|
||||
|
||||
**What it does:**
|
||||
|
||||
- Flushes recorded data to disk (writes HAR file in recording mode)
|
||||
- Releases file locks
|
||||
- Clears in-memory data
|
||||
- Resets internal state
|
||||
|
||||
**What it does NOT do:**
|
||||
|
||||
- Delete HAR files from disk
|
||||
- Remove recorded network traffic
|
||||
- Clear browser context or cookies
|
||||
|
||||
### Configuration Options
|
||||
|
||||
```typescript
|
||||
type NetworkRecorderConfig = {
|
||||
harFile?: {
|
||||
harDir?: string // Directory for HAR files (default: 'har-files')
|
||||
baseName?: string // Base name for HAR files (default: 'network-traffic')
|
||||
organizeByTestFile?: boolean // Organize by test file (default: true)
|
||||
}
|
||||
|
||||
recording?: {
|
||||
content?: 'embed' | 'attach' // Response content handling (default: 'embed')
|
||||
urlFilter?: string | RegExp // URL filter for recording
|
||||
update?: boolean // Update existing HAR files (default: false)
|
||||
}
|
||||
|
||||
playback?: {
|
||||
fallback?: boolean // Fall back to live requests (default: false)
|
||||
urlFilter?: string | RegExp // URL filter for playback
|
||||
updateMode?: boolean // Update mode during playback (default: false)
|
||||
}
|
||||
|
||||
forceMode?: 'record' | 'playback' | 'disabled'
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
Control the recording mode using the `PW_NET_MODE` environment variable:
|
||||
|
||||
```bash
|
||||
# Record mode - captures network traffic to HAR files
|
||||
PW_NET_MODE=record npm run test:pw
|
||||
|
||||
# Playback mode - replays network traffic from HAR files
|
||||
PW_NET_MODE=playback npm run test:pw
|
||||
|
||||
# Disabled mode - no network recording/playback
|
||||
PW_NET_MODE=disabled npm run test:pw
|
||||
|
||||
# Default behavior (when PW_NET_MODE is empty/unset) - same as disabled
|
||||
npm run test:pw
|
||||
```
|
||||
|
||||
**Tip**: We recommend setting `process.env.PW_NET_MODE` directly in your test file for better control.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### HAR File Not Found
|
||||
|
||||
If you see "HAR file not found" errors during playback:
|
||||
|
||||
1. Ensure you've recorded the test first with `PW_NET_MODE=record`
|
||||
2. Check the HAR file exists in the expected location (usually `har-files/`)
|
||||
3. Enable fallback mode: `playback: { fallback: true }`
|
||||
|
||||
### Authentication and Network Recording
|
||||
|
||||
The network recorder works seamlessly with authentication:
|
||||
|
||||
```typescript
|
||||
test('Authenticated recording', async ({ page, context, authSession, networkRecorder }) => {
|
||||
// First authenticate
|
||||
await authSession.login('testuser', 'password');
|
||||
|
||||
// Then setup network recording with authenticated context
|
||||
await networkRecorder.setup(context);
|
||||
|
||||
// Test authenticated flows
|
||||
await page.goto('/dashboard');
|
||||
});
|
||||
```
|
||||
|
||||
### Concurrent Test Issues
|
||||
|
||||
The recorder includes built-in file locking for safe parallel execution. Each test gets its own HAR file based on the test name.
|
||||
|
||||
## Integration with Other Utilities
|
||||
|
||||
**With interceptNetworkCall** (deterministic waits):
|
||||
**With interceptNetworkCall (deterministic waits):**
|
||||
|
||||
```typescript
|
||||
test('use both utilities', async ({ page, context, networkRecorder, interceptNetworkCall }) => {
|
||||
|
|
@ -228,7 +490,7 @@ test('use both utilities', async ({ page, context, networkRecorder, interceptNet
|
|||
|
||||
## Anti-Patterns
|
||||
|
||||
**❌ Mixing record and playback in same test:**
|
||||
**DON'T mix record and playback in same test:**
|
||||
|
||||
```typescript
|
||||
process.env.PW_NET_MODE = 'record';
|
||||
|
|
@ -236,7 +498,7 @@ process.env.PW_NET_MODE = 'record';
|
|||
process.env.PW_NET_MODE = 'playback'; // Don't switch mid-test
|
||||
```
|
||||
|
||||
**✅ One mode per test:**
|
||||
**DO use one mode per test:**
|
||||
|
||||
```typescript
|
||||
process.env.PW_NET_MODE = 'playback'; // Set once at top
|
||||
|
|
@ -247,7 +509,7 @@ test('my test', async ({ page, context, networkRecorder }) => {
|
|||
});
|
||||
```
|
||||
|
||||
**❌ Forgetting to call setup:**
|
||||
**DON'T forget to call setup:**
|
||||
|
||||
```typescript
|
||||
test('broken', async ({ page, networkRecorder }) => {
|
||||
|
|
@ -255,7 +517,7 @@ test('broken', async ({ page, networkRecorder }) => {
|
|||
});
|
||||
```
|
||||
|
||||
**✅ Always call setup before navigation:**
|
||||
**DO always call setup before navigation:**
|
||||
|
||||
```typescript
|
||||
test('correct', async ({ page, context, networkRecorder }) => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Principle
|
||||
|
||||
Use production-ready, fixture-based utilities from `@seontechnologies/playwright-utils` for common Playwright testing patterns. Build test helpers as pure functions first, then wrap in framework-specific fixtures for composability and reuse.
|
||||
Use production-ready, fixture-based utilities from `@seontechnologies/playwright-utils` for common Playwright testing patterns. Build test helpers as pure functions first, then wrap in framework-specific fixtures for composability and reuse. **Works equally well for pure API testing (no browser) and UI testing.**
|
||||
|
||||
## Rationale
|
||||
|
||||
|
|
@ -20,6 +20,7 @@ Writing Playwright utilities from scratch for every project leads to:
|
|||
- **Composable fixtures**: Use `mergeTests` to combine utilities
|
||||
- **TypeScript support**: Full type safety with generic types
|
||||
- **Comprehensive coverage**: API requests, auth, network, logging, file handling, burn-in
|
||||
- **Backend-first mentality**: Most utilities work without a browser - pure API/service testing is a first-class use case
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -38,16 +39,18 @@ npm install -D @seontechnologies/playwright-utils
|
|||
### Core Testing Utilities
|
||||
|
||||
| Utility | Purpose | Test Context |
|
||||
| -------------------------- | ------------------------------------------ | ------------- |
|
||||
| **api-request** | Typed HTTP client with schema validation | API tests |
|
||||
| **network-recorder** | HAR record/playback for offline testing | UI tests |
|
||||
| **auth-session** | Token persistence, multi-user auth | Both UI & API |
|
||||
| **recurse** | Cypress-style polling for async conditions | Both UI & API |
|
||||
| **intercept-network-call** | Network spy/stub with auto JSON parsing | UI tests |
|
||||
| **log** | Playwright report-integrated logging | Both UI & API |
|
||||
| **file-utils** | CSV/XLSX/PDF/ZIP reading & validation | Both UI & API |
|
||||
| **burn-in** | Smart test selection with git diff | CI/CD |
|
||||
| **network-error-monitor** | Automatic HTTP 4xx/5xx detection | UI tests |
|
||||
| -------------------------- | ---------------------------------------------------- | ------------------ |
|
||||
| **api-request** | Typed HTTP client with schema validation and retry | **API/Backend** |
|
||||
| **recurse** | Polling for async operations, background jobs | **API/Backend** |
|
||||
| **auth-session** | Token persistence, multi-user, service-to-service | **API/Backend/UI** |
|
||||
| **log** | Playwright report-integrated logging | **API/Backend/UI** |
|
||||
| **file-utils** | CSV/XLSX/PDF/ZIP reading & validation | **API/Backend/UI** |
|
||||
| **burn-in** | Smart test selection with git diff | **CI/CD** |
|
||||
| **network-recorder** | HAR record/playback for offline testing | UI only |
|
||||
| **intercept-network-call** | Network spy/stub with auto JSON parsing | UI only |
|
||||
| **network-error-monitor** | Automatic HTTP 4xx/5xx detection | UI only |
|
||||
|
||||
**Note**: 6 of 9 utilities work without a browser. Only 3 are UI-specific (network-recorder, intercept-network-call, network-error-monitor).
|
||||
|
||||
## Design Patterns
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Principle
|
||||
|
||||
Use Cypress-style polling with Playwright's `expect.poll` to wait for asynchronous conditions. Provides configurable timeout, interval, logging, and post-polling callbacks with enhanced error categorization.
|
||||
Use Cypress-style polling with Playwright's `expect.poll` to wait for asynchronous conditions. Provides configurable timeout, interval, logging, and post-polling callbacks with enhanced error categorization. **Ideal for backend testing**: polling API endpoints for job completion, database eventual consistency, message queue processing, and cache propagation.
|
||||
|
||||
## Rationale
|
||||
|
||||
|
|
@ -21,6 +21,29 @@ The `recurse` utility provides:
|
|||
- **Post-poll callbacks**: Process results after success
|
||||
- **Type-safe**: Full TypeScript generic support
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
import { test } from '@seontechnologies/playwright-utils/recurse/fixtures';
|
||||
|
||||
test('wait for job completion', async ({ recurse, apiRequest }) => {
|
||||
const { body } = await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/jobs',
|
||||
body: { type: 'export' },
|
||||
});
|
||||
|
||||
// Poll until job completes
|
||||
const result = await recurse(
|
||||
() => apiRequest({ method: 'GET', path: `/api/jobs/${body.id}` }),
|
||||
(response) => response.body.status === 'completed',
|
||||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
expect(result.body.downloadUrl).toBeDefined();
|
||||
});
|
||||
```
|
||||
|
||||
## Pattern Examples
|
||||
|
||||
### Example 1: Basic Polling
|
||||
|
|
@ -48,7 +71,7 @@ test('should wait for job completion', async ({ recurse, apiRequest }) => {
|
|||
timeout: 60000, // 60 seconds max
|
||||
interval: 2000, // Check every 2 seconds
|
||||
log: 'Waiting for export job to complete',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(result.body.downloadUrl).toBeDefined();
|
||||
|
|
@ -62,7 +85,7 @@ test('should wait for job completion', async ({ recurse, apiRequest }) => {
|
|||
- Options: timeout, interval, log message
|
||||
- Returns the value when predicate returns true
|
||||
|
||||
### Example 2: Polling with Assertions
|
||||
### Example 2: Working with Assertions
|
||||
|
||||
**Context**: Use assertions directly in predicate for more expressive tests.
|
||||
|
||||
|
|
@ -76,35 +99,76 @@ test('should poll with assertions', async ({ recurse, apiRequest }) => {
|
|||
body: { type: 'user-created', userId: '123' },
|
||||
});
|
||||
|
||||
// Poll with assertions in predicate
|
||||
// Poll with assertions in predicate - no return true needed!
|
||||
await recurse(
|
||||
async () => {
|
||||
const { body } = await apiRequest({ method: 'GET', path: '/api/events/123' });
|
||||
return body;
|
||||
},
|
||||
(event) => {
|
||||
// Use assertions instead of boolean returns
|
||||
// If all assertions pass, predicate succeeds
|
||||
expect(event.processed).toBe(true);
|
||||
expect(event.timestamp).toBeDefined();
|
||||
// If assertions pass, predicate succeeds
|
||||
// No need to return true - just let assertions pass
|
||||
},
|
||||
{ timeout: 30000 },
|
||||
{ timeout: 30000 }
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
**Why no `return true` needed?**
|
||||
|
||||
- Predicate can use `expect()` assertions
|
||||
- If assertions throw, polling continues
|
||||
- If assertions pass, polling succeeds
|
||||
- More expressive than boolean returns
|
||||
The predicate checks for "truthiness" of the return value. But there's a catch - in JavaScript, an empty `return` (or no return) returns `undefined`, which is falsy!
|
||||
|
||||
### Example 3: Custom Error Messages
|
||||
The utility handles this by checking if:
|
||||
|
||||
**Context**: Provide context-specific error messages for timeout failures.
|
||||
1. The predicate didn't throw (assertions passed)
|
||||
2. The return value was either `undefined` (implicit return) or truthy
|
||||
|
||||
**Implementation**:
|
||||
So you can:
|
||||
|
||||
```typescript
|
||||
// Option 1: Use assertions only (recommended)
|
||||
(event) => {
|
||||
expect(event.processed).toBe(true);
|
||||
};
|
||||
|
||||
// Option 2: Return boolean (also works)
|
||||
(event) => event.processed === true;
|
||||
|
||||
// Option 3: Mixed (assertions + explicit return)
|
||||
(event) => {
|
||||
expect(event.processed).toBe(true);
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
### Example 3: Error Handling
|
||||
|
||||
**Context**: Understanding the different error types.
|
||||
|
||||
**Error Types:**
|
||||
|
||||
```typescript
|
||||
// RecurseTimeoutError - Predicate never returned true within timeout
|
||||
// Contains last command value and predicate error
|
||||
try {
|
||||
await recurse(/* ... */);
|
||||
} catch (error) {
|
||||
if (error instanceof RecurseTimeoutError) {
|
||||
console.log('Timed out. Last value:', error.lastCommandValue);
|
||||
console.log('Last predicate error:', error.lastPredicateError);
|
||||
}
|
||||
}
|
||||
|
||||
// RecurseCommandError - Command function threw an error
|
||||
// The command itself failed (e.g., network error, API error)
|
||||
|
||||
// RecursePredicateError - Predicate function threw (not from assertions failing)
|
||||
// Logic error in your predicate code
|
||||
```
|
||||
|
||||
**Custom Error Messages:**
|
||||
|
||||
```typescript
|
||||
test('custom error on timeout', async ({ recurse, apiRequest }) => {
|
||||
|
|
@ -115,7 +179,7 @@ test('custom error on timeout', async ({ recurse, apiRequest }) => {
|
|||
{
|
||||
timeout: 10000,
|
||||
error: 'System failed to become ready within 10 seconds - check background workers',
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
// Error message includes custom context
|
||||
|
|
@ -125,13 +189,6 @@ test('custom error on timeout', async ({ recurse, apiRequest }) => {
|
|||
});
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
|
||||
- `error` option provides custom message
|
||||
- Replaces default "Timed out after X ms"
|
||||
- Include debugging hints in error message
|
||||
- Helps diagnose failures faster
|
||||
|
||||
### Example 4: Post-Polling Callback
|
||||
|
||||
**Context**: Process or log results after successful polling.
|
||||
|
|
@ -151,7 +208,7 @@ test('post-poll processing', async ({ recurse, apiRequest }) => {
|
|||
console.log(`Processed ${result.body.itemsProcessed} items`);
|
||||
return result.body;
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(finalResult.itemsProcessed).toBeGreaterThan(0);
|
||||
|
|
@ -165,7 +222,67 @@ test('post-poll processing', async ({ recurse, apiRequest }) => {
|
|||
- Can transform or log results
|
||||
- Return value becomes final `recurse` result
|
||||
|
||||
### Example 5: Integration with API Request (Common Pattern)
|
||||
### Example 5: UI Testing Scenarios
|
||||
|
||||
**Context**: Wait for UI elements to reach a specific state through polling.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
test('table data loads', async ({ page, recurse }) => {
|
||||
await page.goto('/reports');
|
||||
|
||||
// Poll for table rows to appear
|
||||
await recurse(
|
||||
async () => page.locator('table tbody tr').count(),
|
||||
(count) => count >= 10, // Wait for at least 10 rows
|
||||
{
|
||||
timeout: 15000,
|
||||
interval: 500,
|
||||
log: 'Waiting for table data to load',
|
||||
}
|
||||
);
|
||||
|
||||
// Now safe to interact with table
|
||||
await page.locator('table tbody tr').first().click();
|
||||
});
|
||||
```
|
||||
|
||||
### Example 6: Event-Based Systems (Kafka/Message Queues)
|
||||
|
||||
**Context**: Testing eventual consistency with message queue processing.
|
||||
|
||||
**Implementation**:
|
||||
|
||||
```typescript
|
||||
test('kafka event processed', async ({ recurse, apiRequest }) => {
|
||||
// Trigger action that publishes Kafka event
|
||||
await apiRequest({
|
||||
method: 'POST',
|
||||
path: '/api/orders',
|
||||
body: { productId: 'ABC123', quantity: 2 },
|
||||
});
|
||||
|
||||
// Poll for downstream effect of Kafka consumer processing
|
||||
const inventoryResult = await recurse(
|
||||
() => apiRequest({ method: 'GET', path: '/api/inventory/ABC123' }),
|
||||
(res) => {
|
||||
// Assumes test fixture seeds inventory at 100; in production tests,
|
||||
// fetch baseline first and assert: expect(res.body.available).toBe(baseline - 2)
|
||||
expect(res.body.available).toBeLessThanOrEqual(98);
|
||||
},
|
||||
{
|
||||
timeout: 30000, // Kafka processing may take time
|
||||
interval: 1000,
|
||||
log: 'Waiting for Kafka event to be processed',
|
||||
}
|
||||
);
|
||||
|
||||
expect(inventoryResult.body.lastOrderId).toBeDefined();
|
||||
});
|
||||
```
|
||||
|
||||
### Example 7: Integration with API Request (Common Pattern)
|
||||
|
||||
**Context**: Most common use case - polling API endpoints for state changes.
|
||||
|
||||
|
|
@ -193,7 +310,7 @@ test('end-to-end polling', async ({ apiRequest, recurse }) => {
|
|||
timeout: 120000, // 2 minutes for large imports
|
||||
interval: 5000, // Check every 5 seconds
|
||||
log: `Polling import ${createResp.importId}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(importResult.body.rowsImported).toBeGreaterThan(1000);
|
||||
|
|
@ -208,20 +325,26 @@ test('end-to-end polling', async ({ apiRequest, recurse }) => {
|
|||
- Complex predicates with multiple conditions
|
||||
- Logging shows polling progress in test reports
|
||||
|
||||
## Enhanced Error Types
|
||||
## API Reference
|
||||
|
||||
The utility categorizes errors for easier debugging:
|
||||
### RecurseOptions
|
||||
|
||||
```typescript
|
||||
// TimeoutError - Predicate never returned true
|
||||
Error: Polling timed out after 30000ms: Job never completed
|
||||
| Option | Type | Default | Description |
|
||||
| ---------- | ------------------ | ----------- | ------------------------------------ |
|
||||
| `timeout` | `number` | `30000` | Maximum time to wait (ms) |
|
||||
| `interval` | `number` | `1000` | Time between polls (ms) |
|
||||
| `log` | `string` | `undefined` | Message logged on each poll |
|
||||
| `error` | `string` | `undefined` | Custom error message for timeout |
|
||||
| `post` | `(result: T) => R` | `undefined` | Callback after successful poll |
|
||||
| `delay` | `number` | `0` | Initial delay before first poll (ms) |
|
||||
|
||||
// CommandError - Command function threw
|
||||
Error: Command failed: Request failed with status 500
|
||||
### Error Types
|
||||
|
||||
// PredicateError - Predicate function threw (not from assertions)
|
||||
Error: Predicate failed: Cannot read property 'status' of undefined
|
||||
```
|
||||
| Error Type | When Thrown | Properties |
|
||||
| ----------------------- | --------------------------------------- | ---------------------------------------- |
|
||||
| `RecurseTimeoutError` | Predicate never passed within timeout | `lastCommandValue`, `lastPredicateError` |
|
||||
| `RecurseCommandError` | Command function threw an error | `cause` (original error) |
|
||||
| `RecursePredicateError` | Predicate threw (not assertion failure) | `cause` (original error) |
|
||||
|
||||
## Comparison with Vanilla Playwright
|
||||
|
||||
|
|
@ -236,11 +359,11 @@ Error: Predicate failed: Cannot read property 'status' of undefined
|
|||
|
||||
**Use recurse for:**
|
||||
|
||||
- ✅ Background job completion
|
||||
- ✅ Webhook/event processing
|
||||
- ✅ Database eventual consistency
|
||||
- ✅ Cache propagation
|
||||
- ✅ State machine transitions
|
||||
- Background job completion
|
||||
- Webhook/event processing
|
||||
- Database eventual consistency
|
||||
- Cache propagation
|
||||
- State machine transitions
|
||||
|
||||
**Stick with vanilla expect.poll for:**
|
||||
|
||||
|
|
@ -250,13 +373,15 @@ Error: Predicate failed: Cannot read property 'status' of undefined
|
|||
|
||||
## Related Fragments
|
||||
|
||||
- `api-testing-patterns.md` - Comprehensive pure API testing patterns
|
||||
- `api-request.md` - Combine for API endpoint polling
|
||||
- `overview.md` - Fixture composition patterns
|
||||
- `fixtures-composition.md` - Using with mergeTests
|
||||
- `contract-testing.md` - Contract testing with async verification
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
**❌ Using hard waits instead of polling:**
|
||||
**DON'T use hard waits instead of polling:**
|
||||
|
||||
```typescript
|
||||
await page.click('#export');
|
||||
|
|
@ -264,33 +389,33 @@ await page.waitForTimeout(5000); // Arbitrary wait
|
|||
expect(await page.textContent('#status')).toBe('Ready');
|
||||
```
|
||||
|
||||
**✅ Poll for actual condition:**
|
||||
**DO poll for actual condition:**
|
||||
|
||||
```typescript
|
||||
await page.click('#export');
|
||||
await recurse(
|
||||
() => page.textContent('#status'),
|
||||
(status) => status === 'Ready',
|
||||
{ timeout: 10000 },
|
||||
{ timeout: 10000 }
|
||||
);
|
||||
```
|
||||
|
||||
**❌ Polling too frequently:**
|
||||
**DON'T poll too frequently:**
|
||||
|
||||
```typescript
|
||||
await recurse(
|
||||
() => apiRequest({ method: 'GET', path: '/status' }),
|
||||
(res) => res.body.ready,
|
||||
{ interval: 100 }, // Hammers API every 100ms!
|
||||
{ interval: 100 } // Hammers API every 100ms!
|
||||
);
|
||||
```
|
||||
|
||||
**✅ Reasonable interval for API calls:**
|
||||
**DO use reasonable interval for API calls:**
|
||||
|
||||
```typescript
|
||||
await recurse(
|
||||
() => apiRequest({ method: 'GET', path: '/status' }),
|
||||
(res) => res.body.ready,
|
||||
{ interval: 2000 }, // Check every 2 seconds (reasonable)
|
||||
{ interval: 2000 } // Check every 2 seconds (reasonable)
|
||||
);
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,33 +1,34 @@
|
|||
id,name,description,tags,fragment_file
|
||||
fixture-architecture,Fixture Architecture,"Composable fixture patterns (pure function → fixture → merge) and reuse rules","fixtures,architecture,playwright,cypress",knowledge/fixture-architecture.md
|
||||
network-first,Network-First Safeguards,"Intercept-before-navigate workflow, HAR capture, deterministic waits, edge mocking","network,stability,playwright,cypress",knowledge/network-first.md
|
||||
data-factories,Data Factories and API Setup,"Factories with overrides, API seeding, cleanup discipline","data,factories,setup,api",knowledge/data-factories.md
|
||||
network-first,Network-First Safeguards,"Intercept-before-navigate workflow, HAR capture, deterministic waits, edge mocking","network,stability,playwright,cypress,ui",knowledge/network-first.md
|
||||
data-factories,Data Factories and API Setup,"Factories with overrides, API seeding, cleanup discipline","data,factories,setup,api,backend,seeding",knowledge/data-factories.md
|
||||
component-tdd,Component TDD Loop,"Red→green→refactor workflow, provider isolation, accessibility assertions","component-testing,tdd,ui",knowledge/component-tdd.md
|
||||
playwright-config,Playwright Config Guardrails,"Environment switching, timeout standards, artifact outputs","playwright,config,env",knowledge/playwright-config.md
|
||||
ci-burn-in,CI and Burn-In Strategy,"Staged jobs, shard orchestration, burn-in loops, artifact policy","ci,automation,flakiness",knowledge/ci-burn-in.md
|
||||
selective-testing,Selective Test Execution,"Tag/grep usage, spec filters, diff-based runs, promotion rules","risk-based,selection,strategy",knowledge/selective-testing.md
|
||||
feature-flags,Feature Flag Governance,"Enum management, targeting helpers, cleanup, release checklists","feature-flags,governance,launchdarkly",knowledge/feature-flags.md
|
||||
contract-testing,Contract Testing Essentials,"Pact publishing, provider verification, resilience coverage","contract-testing,pact,api",knowledge/contract-testing.md
|
||||
contract-testing,Contract Testing Essentials,"Pact publishing, provider verification, resilience coverage","contract-testing,pact,api,backend,microservices,service-contract",knowledge/contract-testing.md
|
||||
email-auth,Email Authentication Testing,"Magic link extraction, state preservation, caching, negative flows","email-authentication,security,workflow",knowledge/email-auth.md
|
||||
error-handling,Error Handling Checks,"Scoped exception handling, retry validation, telemetry logging","resilience,error-handling,stability",knowledge/error-handling.md
|
||||
visual-debugging,Visual Debugging Toolkit,"Trace viewer usage, artifact expectations, accessibility integration","debugging,dx,tooling",knowledge/visual-debugging.md
|
||||
error-handling,Error Handling Checks,"Scoped exception handling, retry validation, telemetry logging","resilience,error-handling,stability,api,backend",knowledge/error-handling.md
|
||||
visual-debugging,Visual Debugging Toolkit,"Trace viewer usage, artifact expectations, accessibility integration","debugging,dx,tooling,ui",knowledge/visual-debugging.md
|
||||
risk-governance,Risk Governance,"Scoring matrix, category ownership, gate decision rules","risk,governance,gates",knowledge/risk-governance.md
|
||||
probability-impact,Probability and Impact Scale,"Shared definitions for scoring matrix and gate thresholds","risk,scoring,scale",knowledge/probability-impact.md
|
||||
test-quality,Test Quality Definition of Done,"Execution limits, isolation rules, green criteria","quality,definition-of-done,tests",knowledge/test-quality.md
|
||||
nfr-criteria,NFR Review Criteria,"Security, performance, reliability, maintainability status definitions","nfr,assessment,quality",knowledge/nfr-criteria.md
|
||||
test-levels,Test Levels Framework,"Guidelines for choosing unit, integration, or end-to-end coverage","testing,levels,selection",knowledge/test-levels-framework.md
|
||||
test-levels,Test Levels Framework,"Guidelines for choosing unit, integration, or end-to-end coverage","testing,levels,selection,api,backend,ui",knowledge/test-levels-framework.md
|
||||
test-priorities,Test Priorities Matrix,"P0–P3 criteria, coverage targets, execution ordering","testing,prioritization,risk",knowledge/test-priorities-matrix.md
|
||||
test-healing-patterns,Test Healing Patterns,"Common failure patterns and automated fixes","healing,debugging,patterns",knowledge/test-healing-patterns.md
|
||||
selector-resilience,Selector Resilience,"Robust selector strategies and debugging techniques","selectors,locators,debugging",knowledge/selector-resilience.md
|
||||
selector-resilience,Selector Resilience,"Robust selector strategies and debugging techniques","selectors,locators,debugging,ui",knowledge/selector-resilience.md
|
||||
timing-debugging,Timing Debugging,"Race condition identification and deterministic wait fixes","timing,async,debugging",knowledge/timing-debugging.md
|
||||
overview,Playwright Utils Overview,"Installation, design principles, fixture patterns","playwright-utils,fixtures",knowledge/overview.md
|
||||
api-request,API Request,"Typed HTTP client, schema validation","api,playwright-utils",knowledge/api-request.md
|
||||
network-recorder,Network Recorder,"HAR record/playback, CRUD detection","network,playwright-utils",knowledge/network-recorder.md
|
||||
auth-session,Auth Session,"Token persistence, multi-user","auth,playwright-utils",knowledge/auth-session.md
|
||||
intercept-network-call,Intercept Network Call,"Network spy/stub, JSON parsing","network,playwright-utils",knowledge/intercept-network-call.md
|
||||
recurse,Recurse Polling,"Async polling, condition waiting","polling,playwright-utils",knowledge/recurse.md
|
||||
log,Log Utility,"Report logging, structured output","logging,playwright-utils",knowledge/log.md
|
||||
file-utils,File Utilities,"CSV/XLSX/PDF/ZIP validation","files,playwright-utils",knowledge/file-utils.md
|
||||
burn-in,Burn-in Runner,"Smart test selection, git diff","ci,playwright-utils",knowledge/burn-in.md
|
||||
network-error-monitor,Network Error Monitor,"HTTP 4xx/5xx detection","monitoring,playwright-utils",knowledge/network-error-monitor.md
|
||||
fixtures-composition,Fixtures Composition,"mergeTests composition patterns","fixtures,playwright-utils",knowledge/fixtures-composition.md
|
||||
overview,Playwright Utils Overview,"Installation, design principles, fixture patterns for API and UI testing","playwright-utils,fixtures,api,backend,ui",knowledge/overview.md
|
||||
api-request,API Request,"Typed HTTP client, schema validation, retry logic for API and service testing","api,backend,service-testing,api-testing,playwright-utils",knowledge/api-request.md
|
||||
network-recorder,Network Recorder,"HAR record/playback, CRUD detection for offline UI testing","network,playwright-utils,ui,har",knowledge/network-recorder.md
|
||||
auth-session,Auth Session,"Token persistence, multi-user, API and browser authentication","auth,playwright-utils,api,backend,jwt,token",knowledge/auth-session.md
|
||||
intercept-network-call,Intercept Network Call,"Network spy/stub, JSON parsing for UI tests","network,playwright-utils,ui",knowledge/intercept-network-call.md
|
||||
recurse,Recurse Polling,"Async polling for API responses, background jobs, eventual consistency","polling,playwright-utils,api,backend,async,eventual-consistency",knowledge/recurse.md
|
||||
log,Log Utility,"Report logging, structured output for API and UI tests","logging,playwright-utils,api,ui",knowledge/log.md
|
||||
file-utils,File Utilities,"CSV/XLSX/PDF/ZIP validation for API exports and UI downloads","files,playwright-utils,api,backend,ui",knowledge/file-utils.md
|
||||
burn-in,Burn-in Runner,"Smart test selection, git diff for CI optimization","ci,playwright-utils",knowledge/burn-in.md
|
||||
network-error-monitor,Network Error Monitor,"HTTP 4xx/5xx detection for UI tests","monitoring,playwright-utils,ui",knowledge/network-error-monitor.md
|
||||
fixtures-composition,Fixtures Composition,"mergeTests composition patterns for combining utilities","fixtures,playwright-utils",knowledge/fixtures-composition.md
|
||||
api-testing-patterns,API Testing Patterns,"Pure API test patterns without browser: service testing, microservices, GraphQL","api,backend,service-testing,api-testing,microservices,graphql,no-browser",knowledge/api-testing-patterns.md
|
||||
|
|
|
|||
|
|
|
@ -548,7 +548,7 @@ function checkDocLinks() {
|
|||
printHeader('Checking documentation links');
|
||||
|
||||
try {
|
||||
execSync('node tools/check-doc-links.js', {
|
||||
execSync('node tools/validate-doc-links.js', {
|
||||
cwd: PROJECT_ROOT,
|
||||
stdio: 'inherit',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,282 +0,0 @@
|
|||
/**
|
||||
* Internal documentation link checker
|
||||
* Scans markdown files in docs/ and verifies:
|
||||
* - All relative links point to existing files
|
||||
* - All anchor links (#section) point to valid headings
|
||||
* - No duplicate/conflicting paths
|
||||
*
|
||||
* Exits with code 1 if broken links are found (fails the build).
|
||||
*/
|
||||
|
||||
const { readFileSync, existsSync } = require('node:fs');
|
||||
const { resolve, dirname, join, normalize, relative } = require('node:path');
|
||||
const { glob } = require('glob');
|
||||
|
||||
const DOCS_DIR = resolve(process.cwd(), 'docs');
|
||||
|
||||
// Regex to match markdown links: [text](path) and reference-style [text]: path
|
||||
const LINK_PATTERNS = [
|
||||
/\[([^\]]*)\]\(([^)]+)\)/g, // [text](path)
|
||||
/\[([^\]]+)\]:\s*(\S+)/g, // [text]: path
|
||||
];
|
||||
|
||||
// Regex to extract headings for anchor validation
|
||||
const HEADING_PATTERN = /^#{1,6}\s+(.+)$/gm;
|
||||
|
||||
/**
|
||||
* Determines whether a link should be ignored during validation.
|
||||
* @param {string} link - The link URL or path to test.
|
||||
* @returns {boolean} `true` if the link is external, uses a special protocol (`http://`, `https://`, `mailto:`, `tel:`), or is an absolute path starting with `/`, `false` otherwise.
|
||||
*/
|
||||
function shouldIgnore(link) {
|
||||
return (
|
||||
link.startsWith('http://') ||
|
||||
link.startsWith('https://') ||
|
||||
link.startsWith('mailto:') ||
|
||||
link.startsWith('tel:') ||
|
||||
link.startsWith('/') // Absolute paths handled by Astro routing
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a markdown heading into the anchor slug used by common Markdown processors.
|
||||
*
|
||||
* Produces a lowercase slug with emojis and most punctuation removed, whitespace collapsed to single
|
||||
* hyphens, consecutive hyphens collapsed, and leading/trailing hyphens trimmed.
|
||||
* @param {string} heading - The heading text to convert.
|
||||
* @returns {string} The resulting anchor slug.
|
||||
*/
|
||||
function headingToAnchor(heading) {
|
||||
return heading
|
||||
.toLowerCase()
|
||||
.replaceAll(/[\u{1F300}-\u{1F9FF}]/gu, '') // Remove emojis
|
||||
.replaceAll(/[^\w\s-]/g, '') // Remove special chars except hyphens
|
||||
.replaceAll(/\s+/g, '-') // Spaces to hyphens
|
||||
.replaceAll(/-+/g, '-') // Collapse multiple hyphens
|
||||
.replaceAll(/^-+|-+$/g, ''); // Trim leading/trailing hyphens
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts anchor slugs from Markdown content by converting headings to their anchor form.
|
||||
*
|
||||
* Strips inline formatting (code spans, emphasis, bold, and inline links), processes
|
||||
* Markdown headings (levels 1–6), and returns the resulting anchor slugs.
|
||||
*
|
||||
* @param {string} content - The Markdown text to scan for headings.
|
||||
* @returns {Set<string>} A set of anchor slugs derived from the headings in `content`.
|
||||
*/
|
||||
function extractAnchors(content) {
|
||||
const anchors = new Set();
|
||||
let match;
|
||||
|
||||
HEADING_PATTERN.lastIndex = 0;
|
||||
while ((match = HEADING_PATTERN.exec(content)) !== null) {
|
||||
const headingText = match[1].trim();
|
||||
// Remove inline code, bold, italic, links from heading
|
||||
const cleanHeading = headingText
|
||||
.replaceAll(/`[^`]+`/g, '')
|
||||
.replaceAll(/\*\*([^*]+)\*\*/g, '$1')
|
||||
.replaceAll(/\*([^*]+)\*/g, '$1')
|
||||
.replaceAll(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||
.trim();
|
||||
anchors.add(headingToAnchor(cleanHeading));
|
||||
}
|
||||
|
||||
return anchors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove fenced and inline code segments from Markdown content.
|
||||
*
|
||||
* @param {string} content - Markdown text to sanitize.
|
||||
* @returns {string} The input content with fenced code blocks (```...``` and ~~~...~~~) and inline code (backtick-enclosed) removed.
|
||||
*/
|
||||
function stripCodeBlocks(content) {
|
||||
// Remove fenced code blocks (``` or ~~~)
|
||||
return content
|
||||
.replaceAll(/```[\s\S]*?```/g, '')
|
||||
.replaceAll(/~~~[\s\S]*?~~~/g, '')
|
||||
.replaceAll(/`[^`\n]+`/g, ''); // Also remove inline code
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts all non-external link targets from markdown content, ignoring links inside code blocks.
|
||||
* @param {string} content - Markdown source to scan for link targets.
|
||||
* @returns {string[]} Array of raw link strings (paths and optional anchors) found in the content; external or protocol-based links are excluded.
|
||||
*/
|
||||
function extractLinks(content) {
|
||||
const strippedContent = stripCodeBlocks(content);
|
||||
const links = [];
|
||||
for (const pattern of LINK_PATTERNS) {
|
||||
let match;
|
||||
pattern.lastIndex = 0;
|
||||
while ((match = pattern.exec(strippedContent)) !== null) {
|
||||
const rawLink = match[2];
|
||||
if (!shouldIgnore(rawLink)) {
|
||||
links.push(rawLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a link into its path and anchor components.
|
||||
* @param {string} link - The link string to parse; may include a `#` followed by an anchor.
|
||||
* @returns {{path: string|null, anchor: string|null}} An object where `path` is the portion before `#` (or `null` when empty, indicating a same-file anchor), and `anchor` is the portion after `#` (or `null` when no `#` is present). Note: `anchor` may be an empty string if the link ends with `#`.
|
||||
*/
|
||||
function parseLink(link) {
|
||||
const hashIndex = link.indexOf('#');
|
||||
if (hashIndex === -1) {
|
||||
return { path: link, anchor: null };
|
||||
}
|
||||
return {
|
||||
path: link.slice(0, hashIndex) || null, // Empty path means same file
|
||||
anchor: link.slice(hashIndex + 1),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a relative markdown link path from a source file to a concrete absolute file path.
|
||||
* @param {string} fromFile - Absolute path of the file containing the link.
|
||||
* @param {string|null} linkPath - Link target as written in markdown; may be `null` or empty for same-file anchors.
|
||||
* @returns {string} The resolved absolute path. If `linkPath` is null/empty returns `fromFile`. If the resolved path has no extension, an existing `.md` file or an `index.md` inside a matching directory is preferred; otherwise the normalized resolved path is returned.
|
||||
*/
|
||||
function resolveLink(fromFile, linkPath) {
|
||||
if (!linkPath) return fromFile; // Same file anchor
|
||||
|
||||
const fromDir = dirname(fromFile);
|
||||
let resolved = normalize(resolve(fromDir, linkPath));
|
||||
|
||||
// If link doesn't have extension, try .md
|
||||
if (!resolved.endsWith('.md') && !existsSync(resolved)) {
|
||||
const withMd = resolved + '.md';
|
||||
if (existsSync(withMd)) {
|
||||
return withMd;
|
||||
}
|
||||
// Try as directory with index.md
|
||||
const asIndex = join(resolved, 'index.md');
|
||||
if (existsSync(asIndex)) {
|
||||
return asIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// Cache for file anchors to avoid re-reading files
|
||||
const anchorCache = new Map();
|
||||
|
||||
/**
|
||||
* Retrieve and cache the set of markdown anchor slugs for a given file.
|
||||
*
|
||||
* Reads the file at the provided path, extracts heading-based anchor slugs, stores them in an internal cache, and returns them.
|
||||
* @param {string} filePath - Absolute or relative path to the markdown file.
|
||||
* @returns {Set<string>} The set of anchor slugs present in the file.
|
||||
*/
|
||||
function getAnchorsForFile(filePath) {
|
||||
if (anchorCache.has(filePath)) {
|
||||
return anchorCache.get(filePath);
|
||||
}
|
||||
|
||||
const content = readFileSync(filePath, 'utf-8');
|
||||
const anchors = extractAnchors(content);
|
||||
anchorCache.set(filePath, anchors);
|
||||
return anchors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Markdown files in docs/ for broken relative links and anchor targets.
|
||||
*
|
||||
* Scans all `.md` and `.mdx` files under DOCS_DIR, checks that relative links resolve to existing
|
||||
* files and that any `#anchor` references point to existing headings. Prints a grouped,
|
||||
* colored report of issues to stdout and terminates the process with exit code `0` if no issues
|
||||
* were found or `1` if any broken links or anchors are detected.
|
||||
*/
|
||||
async function main() {
|
||||
console.log(' → Scanning for broken links and anchors...');
|
||||
|
||||
const files = await glob('**/*.{md,mdx}', { cwd: DOCS_DIR, absolute: true });
|
||||
const errors = [];
|
||||
|
||||
// Track all resolved paths for duplicate detection
|
||||
const pathRegistry = new Map(); // normalized path -> [source files]
|
||||
|
||||
for (const file of files) {
|
||||
const content = readFileSync(file, 'utf-8');
|
||||
const links = extractLinks(content);
|
||||
const relativePath = relative(DOCS_DIR, file);
|
||||
|
||||
for (const rawLink of links) {
|
||||
const { path: linkPath, anchor } = parseLink(rawLink);
|
||||
|
||||
// Resolve target file
|
||||
const targetFile = resolveLink(file, linkPath);
|
||||
const normalizedTarget = normalize(targetFile);
|
||||
|
||||
// Check if file exists (skip for same-file anchors)
|
||||
if (linkPath && !existsSync(targetFile)) {
|
||||
errors.push({
|
||||
type: 'broken-link',
|
||||
file: relativePath,
|
||||
link: rawLink,
|
||||
message: `File not found: ${linkPath}`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check anchor if present
|
||||
if (anchor) {
|
||||
const anchors = getAnchorsForFile(targetFile);
|
||||
if (!anchors.has(anchor)) {
|
||||
errors.push({
|
||||
type: 'broken-anchor',
|
||||
file: relativePath,
|
||||
link: rawLink,
|
||||
message: `Anchor "#${anchor}" not found in ${linkPath || 'same file'}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Track paths for duplicate detection
|
||||
if (linkPath) {
|
||||
if (!pathRegistry.has(normalizedTarget)) {
|
||||
pathRegistry.set(normalizedTarget, []);
|
||||
}
|
||||
pathRegistry.get(normalizedTarget).push({ from: relativePath, link: rawLink });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Report results
|
||||
if (errors.length === 0) {
|
||||
console.log(` \u001B[32m✓\u001B[0m Checked ${files.length} files - no broken links found.`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log(`\n \u001B[31m✗\u001B[0m Found ${errors.length} issue(s):\n`);
|
||||
|
||||
// Group by file
|
||||
const byFile = {};
|
||||
for (const error of errors) {
|
||||
if (!byFile[error.file]) byFile[error.file] = [];
|
||||
byFile[error.file].push(error);
|
||||
}
|
||||
|
||||
for (const [file, fileErrors] of Object.entries(byFile)) {
|
||||
console.log(` \u001B[36m${file}\u001B[0m`);
|
||||
for (const error of fileErrors) {
|
||||
const icon = error.type === 'broken-link' ? '🔗' : '⚓';
|
||||
console.log(` ${icon} ${error.link}`);
|
||||
console.log(` └─ ${error.message}`);
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Error:', error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/**
|
||||
* Fix Documentation Links
|
||||
*
|
||||
* Converts relative markdown links to repo-relative paths with .md extension.
|
||||
* This ensures links work both in GitHub and on the Astro/Starlight site
|
||||
* (the rehype plugin transforms /docs/path/file.md → /path/file/ at build time).
|
||||
*
|
||||
* - ./file.md → /docs/current/path/file.md
|
||||
* - ../other/file.md → /docs/resolved/path/file.md
|
||||
* - /path/file/ → /docs/path/file.md (or /docs/path/file/index.md if it's a directory)
|
||||
*
|
||||
* Usage:
|
||||
* node tools/fix-doc-links.js # Dry run (shows what would change)
|
||||
* node tools/fix-doc-links.js --write # Actually write changes
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const DOCS_ROOT = path.resolve(__dirname, '../docs');
|
||||
const DRY_RUN = !process.argv.includes('--write');
|
||||
|
||||
// Regex to match markdown links:
|
||||
// - [text](path.md) or [text](path.md#anchor) - existing .md links
|
||||
// - [text](/path/to/page/) or [text](/path/to/page/#anchor) - site-relative links to convert
|
||||
const MARKDOWN_LINK_REGEX = /\[([^\]]*)\]\(([^)]+(?:\.md|\/))(?:#[^)]*)?(?:\?[^)]*)?\)/g;
|
||||
// Simpler approach: match all markdown links and filter in the handler
|
||||
const ALL_MARKDOWN_LINKS_REGEX = /\[([^\]]*)\]\(([^)]+)\)/g;
|
||||
|
||||
/**
|
||||
* Get all markdown files in docs directory, excluding _* directories/files
|
||||
*/
|
||||
function getMarkdownFiles(dir) {
|
||||
const files = [];
|
||||
|
||||
function walk(currentDir) {
|
||||
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(currentDir, entry.name);
|
||||
|
||||
// Skip underscore-prefixed entries
|
||||
if (entry.name.startsWith('_')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
walk(fullPath);
|
||||
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(dir);
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a markdown link href to repo-relative path with .md extension
|
||||
*
|
||||
* @param {string} href - The original href (e.g., "./file.md", "/path/to/page/", "/path/to/page/#anchor")
|
||||
* @param {string} currentFilePath - Absolute path to the file containing this link
|
||||
* @returns {string|null} - Repo-relative path (e.g., "/docs/path/to/file.md"), or null if shouldn't be converted
|
||||
*/
|
||||
function convertToRepoRelative(href, currentFilePath) {
|
||||
// Skip external links
|
||||
if (href.includes('://') || href.startsWith('mailto:') || href.startsWith('tel:')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip anchor-only links
|
||||
if (href.startsWith('#')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract anchor and query string if present
|
||||
let anchor = '';
|
||||
let query = '';
|
||||
let pathPortion = href;
|
||||
|
||||
const hashIndex = href.indexOf('#');
|
||||
const queryIndex = href.indexOf('?');
|
||||
|
||||
if (hashIndex !== -1 || queryIndex !== -1) {
|
||||
const firstDelimiter = Math.min(hashIndex === -1 ? Infinity : hashIndex, queryIndex === -1 ? Infinity : queryIndex);
|
||||
pathPortion = href.slice(0, Math.max(0, firstDelimiter));
|
||||
|
||||
const suffix = href.slice(Math.max(0, firstDelimiter));
|
||||
const anchorInSuffix = suffix.indexOf('#');
|
||||
|
||||
if (suffix.startsWith('?')) {
|
||||
if (anchorInSuffix === -1) {
|
||||
query = suffix;
|
||||
} else {
|
||||
query = suffix.slice(0, Math.max(0, anchorInSuffix));
|
||||
anchor = suffix.slice(Math.max(0, anchorInSuffix));
|
||||
}
|
||||
} else {
|
||||
anchor = suffix;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip non-documentation links (images, external assets, etc.)
|
||||
const ext = path.extname(pathPortion).toLowerCase();
|
||||
if (
|
||||
ext &&
|
||||
ext !== '.md' &&
|
||||
!['.md'].includes(ext) && // Has an extension that's not .md - skip unless it's a trailing slash path
|
||||
!pathPortion.endsWith('/')
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if original path ends with / (directory reference) BEFORE path.join normalizes it
|
||||
const isDirectoryPath = pathPortion.endsWith('/');
|
||||
|
||||
let absolutePath;
|
||||
|
||||
if (pathPortion.startsWith('/docs/')) {
|
||||
// Already repo-relative with /docs/ prefix
|
||||
absolutePath = path.join(path.dirname(DOCS_ROOT), pathPortion);
|
||||
} else if (pathPortion.startsWith('/')) {
|
||||
// Site-relative (e.g., /tutorials/getting-started/) - resolve from docs root
|
||||
absolutePath = path.join(DOCS_ROOT, pathPortion);
|
||||
} else {
|
||||
// Relative path (./, ../, or bare filename) - resolve from current file's directory
|
||||
const currentDir = path.dirname(currentFilePath);
|
||||
absolutePath = path.resolve(currentDir, pathPortion);
|
||||
}
|
||||
|
||||
// Convert to repo-relative path (with /docs/ prefix)
|
||||
let repoRelative = '/docs/' + path.relative(DOCS_ROOT, absolutePath);
|
||||
|
||||
// Normalize path separators for Windows
|
||||
repoRelative = repoRelative.split(path.sep).join('/');
|
||||
|
||||
// If original path was a directory reference (ended with /), check for index.md or file.md
|
||||
if (isDirectoryPath) {
|
||||
const relativeDir = repoRelative.slice(6); // Remove '/docs/'
|
||||
|
||||
// Handle root path case (relativeDir is empty or just '.')
|
||||
const normalizedDir = relativeDir === '' || relativeDir === '.' ? '' : relativeDir;
|
||||
const indexPath = path.join(DOCS_ROOT, normalizedDir, 'index.md');
|
||||
const filePath = normalizedDir ? path.join(DOCS_ROOT, normalizedDir + '.md') : null;
|
||||
|
||||
if (fs.existsSync(indexPath)) {
|
||||
// Avoid double slash when repoRelative is '/docs/' (root case)
|
||||
repoRelative = repoRelative.endsWith('/') ? repoRelative + 'index.md' : repoRelative + '/index.md';
|
||||
} else if (filePath && fs.existsSync(filePath)) {
|
||||
repoRelative = repoRelative + '.md';
|
||||
} else {
|
||||
// Neither exists - default to index.md and let validation catch it
|
||||
repoRelative = repoRelative.endsWith('/') ? repoRelative + 'index.md' : repoRelative + '/index.md';
|
||||
}
|
||||
} else if (!repoRelative.endsWith('.md')) {
|
||||
// Path doesn't end with .md - add .md
|
||||
repoRelative = repoRelative + '.md';
|
||||
}
|
||||
|
||||
return repoRelative + query + anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single markdown file, skipping links inside fenced code blocks
|
||||
*
|
||||
* @param {string} filePath - Absolute path to the file
|
||||
* @returns {Object} - { changed: boolean, original: string, updated: string, changes: Array }
|
||||
*/
|
||||
function processFile(filePath) {
|
||||
const original = fs.readFileSync(filePath, 'utf-8');
|
||||
const changes = [];
|
||||
|
||||
// Extract fenced code blocks and replace with placeholders
|
||||
const codeBlocks = [];
|
||||
const CODE_PLACEHOLDER = '\u0000CODE_BLOCK_';
|
||||
|
||||
let contentWithPlaceholders = original.replaceAll(/```[\s\S]*?```/g, (match) => {
|
||||
const index = codeBlocks.length;
|
||||
codeBlocks.push(match);
|
||||
return `${CODE_PLACEHOLDER}${index}\u0000`;
|
||||
});
|
||||
|
||||
// Process links only in non-code-block content
|
||||
contentWithPlaceholders = contentWithPlaceholders.replaceAll(ALL_MARKDOWN_LINKS_REGEX, (match, linkText, href) => {
|
||||
const newHref = convertToRepoRelative(href, filePath);
|
||||
|
||||
// Skip if conversion returned null (external link, anchor, etc.)
|
||||
if (newHref === null) {
|
||||
return match;
|
||||
}
|
||||
|
||||
// Only record as change if actually different
|
||||
if (newHref !== href) {
|
||||
changes.push({ from: href, to: newHref });
|
||||
return `[${linkText}](${newHref})`;
|
||||
}
|
||||
|
||||
return match;
|
||||
});
|
||||
|
||||
// Restore code blocks
|
||||
const updated = contentWithPlaceholders.replaceAll(
|
||||
new RegExp(`${CODE_PLACEHOLDER}(\\d+)\u0000`, 'g'),
|
||||
(match, index) => codeBlocks[parseInt(index, 10)],
|
||||
);
|
||||
|
||||
return {
|
||||
changed: changes.length > 0,
|
||||
original,
|
||||
updated,
|
||||
changes,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that a repo-relative link points to an existing file
|
||||
*/
|
||||
function validateLink(repoRelativePath) {
|
||||
// Strip anchor/query
|
||||
const checkPath = repoRelativePath.split('#')[0].split('?')[0];
|
||||
|
||||
// Remove /docs/ prefix to get path relative to DOCS_ROOT
|
||||
const relativePath = checkPath.startsWith('/docs/') ? checkPath.slice(6) : checkPath.slice(1);
|
||||
|
||||
return fs.existsSync(path.join(DOCS_ROOT, relativePath));
|
||||
}
|
||||
|
||||
// Main execution
|
||||
console.log(`\nScanning docs in: ${DOCS_ROOT}`);
|
||||
console.log(`Mode: ${DRY_RUN ? 'DRY RUN (use --write to apply changes)' : 'WRITE MODE'}\n`);
|
||||
|
||||
const files = getMarkdownFiles(DOCS_ROOT);
|
||||
console.log(`Found ${files.length} markdown files (excluding _* paths)\n`);
|
||||
|
||||
let totalChanges = 0;
|
||||
let filesChanged = 0;
|
||||
const brokenLinks = [];
|
||||
|
||||
for (const filePath of files) {
|
||||
const relativePath = path.relative(DOCS_ROOT, filePath);
|
||||
const result = processFile(filePath);
|
||||
|
||||
if (result.changed) {
|
||||
filesChanged++;
|
||||
totalChanges += result.changes.length;
|
||||
|
||||
console.log(`\n${relativePath}`);
|
||||
for (const change of result.changes) {
|
||||
const isValid = validateLink(change.to);
|
||||
const status = isValid ? ' ' : '! ';
|
||||
|
||||
console.log(`${status} ${change.from}`);
|
||||
console.log(` -> ${change.to}`);
|
||||
|
||||
if (!isValid) {
|
||||
brokenLinks.push({
|
||||
file: relativePath,
|
||||
link: change.to,
|
||||
original: change.from,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!DRY_RUN) {
|
||||
fs.writeFileSync(filePath, result.updated, 'utf-8');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n${'─'.repeat(60)}`);
|
||||
console.log(`\nSummary:`);
|
||||
console.log(` Files scanned: ${files.length}`);
|
||||
console.log(` Files with changes: ${filesChanged}`);
|
||||
console.log(` Total link updates: ${totalChanges}`);
|
||||
|
||||
if (brokenLinks.length > 0) {
|
||||
console.log(`\n! Potential broken links (${brokenLinks.length}):`);
|
||||
for (const bl of brokenLinks) {
|
||||
console.log(` ${bl.file}: ${bl.link}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (DRY_RUN && totalChanges > 0) {
|
||||
console.log(`\nRun with --write to apply these changes`);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue