# How to Map Any Workflow: Actions & Test Cases

**Audience:** Someone with zero prior context on the specific application
being mapped — a new QA hire, a different agent, anyone picking this up
cold, on any product. This guide teaches the *method*. It contains no
knowledge specific to any one application — that kind of knowledge (what
the screens actually look like, what bugs have been found, what the known
edge cases are) belongs in a separate, product-specific companion notes
file that sits alongside this one.

This guide was written after several review cycles that caught real gaps
in an earlier mapping effort — the mistakes are described here on purpose,
so you don't repeat them, regardless of which application you're mapping.

---

## 1. Briefing an agent to start a mapping session

A guide sitting in a folder doesn't enforce itself. Whoever kicks off a
mapping session needs to actively point the agent at it and set a few
ground rules — otherwise the same mistakes this guide exists to prevent
just happen again.

### The minimal effective prompt

> Read `QA-Workflow-Mapping-Guide.md` in full before doing anything else,
> then read the product-specific notes file for this workflow (if one
> exists) for context. If a coverage map already exists for this workflow
> (an Actions CSV / Flows CSV), read those too before making changes —
> don't restart from the blank templates.
>
> Map the **[workflow name]** workflow at **[URL]**. Login: [credentials].
>
> Follow the guide exactly — in particular: chrome pass every screen,
> branch-spike every multi-state control in both directions, every Flow
> runs to a verifiable end state (never a fragment), and Flows are only
> ever `Observed-Live` or blank `NOT TESTED` — never inferred.
>
> Before producing a full set of rows, show me 3–5 as a sample so I can
> confirm the format and depth are right, then continue.

The two things doing the real work: **pointing at every relevant file**
(the guide, the product notes, and any existing CSVs), and **asking for
a sample before a full run** — a full rebuild after the fact costs far
more than a quick format check up front.

### What to prepare before starting

- **URL(s)** — the entry point to the workflow itself, and any
  admin/config surface needed to set up test scenarios (seed data,
  toggle settings, create test records).
- **Login credentials for each role in scope** — at minimum one account
  per distinct role that needs testing. Note anything that needs to be
  pre-seeded (e.g. a role's account must already be registered/linked to
  a specific test record before the workflow will even let it through).
- **Test data** — a known-state test record already seeded, or explicit
  permission for the agent to create one, plus any config-driven
  settings (a specific toggle, a specific pricing rule) that need to
  exist for the flows you actually want covered.
- **If payment or other financial actions are in scope** — explicit
  confirmation that charges may be made, which test card/gateway to use
  (sandbox/test-mode only), and confirmation the environment is
  non-production. Don't assume a green light from earlier in the
  conversation carries forward indefinitely — re-confirm before further
  real charges, especially in a new session.
- **Any existing coverage map or product notes file** — point the agent
  at these explicitly so it extends prior work instead of starting over
  and losing everything already verified.

### Practices to insist on during the session

- **Sample before scale.** Ask for 3–5 rows before a full set is
  generated, every time the format or depth of what's being produced is
  new or has changed.
- **Confirm before real financial or destructive actions**, even in a
  test environment, even if something similar was approved earlier in
  the same conversation. Prior approval is not a standing authorization.
- **Restore any config changed to unblock testing** before the session
  ends — a setting changed to get past a blocker (a minimum, a toggle, a
  date) needs to be set back, and that restoration is easy to forget
  once the actual testing goal is reached.
- **Self-check completeness before declaring done.** A coverage map that
  looks thin relative to the number of settings and branches actually
  discovered during exploration is a sign of under-scoping, not
  efficiency — ask "does this look complete against everything found?"
  before wrapping up, not just "did I write some rows?"

---

## 2. What this guide produces

Two artifacts, together forming a coverage map for a workflow:

1. **An Actions sheet** — every discrete, user-triggered interaction that
   exists in the workflow (a click, a select, a toggle, a form submit).
2. **A Flows sheet** (test cases) — scenarios built out of those actions,
   each running from a defined starting state to a verifiable outcome.

Before opening any application, understand the three concepts below. Most
of the damage in a bad coverage map comes from confusing them.

---

## 3. The three things people confuse: Action, Flow, Test Case

### Action
A **discrete, user-triggered interaction that fires something in the
system** — a click, a select, a toggle, a form submit. That's it.

- ✅ "Click the Add Item button" — fires a workflow (opens a modal, adds a
  row, starts a process)
- ✅ "Fill out and submit the contact-info form" — one action, even though
  it has 5 fields, because it's one submit
- ❌ "A confirmation modal appears" — this is an **outcome**, not an
  action. Nobody clicked "make modal appear."
- ❌ "Typing a non-matching value returns no results" — this is a **test
  case** (an assertion about behavior), not an action. The action is
  "type into the search field"; what happens when you type something
  specific is a Flow.
- ❌ "The summary screen shows contact info, charges, and totals" — this
  is a **display**, not an action. Nothing was triggered.

**Rule of thumb:** if you can't answer "what did the user click, select,
or submit to cause this?", it's not an action — it's an outcome, and
outcomes belong in a Flow's Assert column, or folded into the description
of the action that caused them.

**Multi-field forms are ONE action.** Don't create a separate Action ID
per input field. List every field in the Description instead:
> "Editable fields, submitted together via Next: Name, Email, Address,
> Phone, plus the Terms checkbox."

### Flow (Test Case)
A **complete journey**: given a defined starting state (Arrange), a
sequence of actions (Act), you reach one specific, verifiable outcome
(Assert). See §8 below — this is the part that's easiest to get wrong.

### Test Case ≠ Action
If you find yourself naming an Action row after a *result* ("no results
found", "purchase blocked", "payment successful"), stop — that's a Flow's
Assert, not an Action.

---

## 4. The two artifacts and their columns

Two blank starting-point files accompany this guide:
`QA-Actions-Template.csv` and `QA-Flows-Template.csv`. Copy them for any
new workflow/product you map — they contain only headers, no data. The
Flows template's role columns are named generically (`Role 1`, `Role 2`,
...) plus `Logged Out User`; rename those to the actual roles that exist
in whatever product you're mapping before you start filling in rows.

### Actions sheet
| Column | What goes here |
|---|---|
| Platform | Which product/platform this action belongs to (e.g. a short code). Useful once you're mapping more than one product's workflows in the same overall effort. |
| Action ID | Stable, descriptive ID, e.g. `PLATFORM-CATEGORY-ADD-CARD-BTN` |
| Surface | Free-text notes / reviewer comments |
| Category | Which area or step of the workflow this belongs to |
| Description | What it does, including every field if it's a form |
| Dependencies | See below — non-obvious, high-level dependencies only |
| Verification | See §6 below — how confident are we this is real? |

**Dependencies is the column people get wrong most often.** It is not a
place to restate the obvious: "modal must be open," "the previous step
must be completed," "a room must exist before you can edit it" — these
are already implied by the workflow's own sequence and add nothing.
Leave the column blank rather than fill it with sequencing trivia.

What belongs there instead: **cross-cutting dependencies that aren't
visible from the action itself** — especially ones driven by an admin/config
setting elsewhere in the system that silently changes what a user sees or
must do. For example: an admin enables a tax setting, and as a result a
field the user used to have to fill in disappears; a discount code is
only accepted for certain order types because of how it was configured;
a control that's freely editable in isolation becomes locked once some
other piece of data exists. These are the dependencies worth writing
down, because nobody exploring the screen in isolation would guess them —
they only show up by testing across screens or against admin-side config.
If an action's behavior only ever depends on itself and the immediately
preceding step, its Dependencies field should be empty.

### Flows (Test Cases) sheet
Status (Pass/Fail/Not Tested), Platform, Category/Sub-Category, Flow name,
Preconditions (Arrange), Description, Action Sequence (ordered Action
IDs), Expected Outcome (Assert), Priority, Automation recommendation,
applicable roles, Verification.

Don't repeat the platform inside the Flow name itself (e.g. don't name a
flow `PLATFORM-CHECKOUT-...` when there's already a Platform column
holding that value) — say it once, in its own column. Action IDs may
still use the platform as a namespacing prefix if that's useful for
uniqueness across a larger ID list; that's a different concern from
naming a Flow row.

A `FAIL` means a real bug was found — say exactly what's wrong and what
you'd expect instead.

**Every Flow's Expected Outcome/Assert should end with a standing data
validation prompt.** Whatever you can verify by driving the UI (a
confirmation screen, a displayed total) goes in the main Assert as usual.
But UI-level verification can't confirm what actually landed in the
backend — the right database row was created, the right field holds the
right value, nothing else was silently affected. Since this typically
requires access and schema knowledge the exploring agent doesn't have,
close every Assert with an explicit, consistent prompt for a human (or a
later pass with DB access) to fill in, e.g.:

> DATA VALIDATION (manual, to be filled in by tester): list the specific
> backend tables/fields that must be checked to confirm this outcome.

Leaving this prompt in place — rather than skipping it because you can't
answer it yet — keeps the gap visible instead of silently assuming
UI-level confirmation was enough.

---

## 5. The exploration process (do this, in this order, per screen)

Apply all four steps to **every screen**, not just the ones that look
interesting. Skipping this is the single biggest source of missed
coverage.

### Step 1 — Chrome pass, before anything else
Screenshot the whole page. List every clickable element in the header,
footer, and nav — **before** touching the main content. This is how
global elements (log out, a "back" link, a "forgot password" link, help
links) get missed: they're not in the center of the screen, so people
skip straight to the form.

### Step 2 — Branch spike on every multi-state control
Any radio, toggle, checkbox, or dropdown that changes what happens next
needs this full sequence — not just "click it once and move on":

1. Test it in its **default** state, proceed forward.
2. Come back, switch it to the **alternate** state, proceed forward. Does
   the flow skip a step? Show or hide something?
3. From the step ahead, navigate **backward**. Does it skip the same step
   in reverse, symmetrically? (Forward-only testing is a common gap —
   the reverse direction is often silently different.)
4. Add some downstream data (e.g. complete a sub-step that depends on
   this control), then **come back and re-test the control**. Does it
   now lock, disable, or change behavior because dependent data exists?
   (Settings that look freely editable in isolation often become locked
   once something downstream depends on them — this only shows up if you
   deliberately re-test after creating that dependency.)

### Step 3 — Decompose sub-flows to their actual end
If a button opens a modal, or starts a mini-wizard-within-the-workflow,
don't stop at the first screen of that modal. Walk it all the way
through: what happens after you save? Is there a follow-up prompt? Can
you edit or delete what you just created from the parent list? Each of
those is its own Action.

### Step 4 — Tag verification honestly
Mark each Action row `Observed-Live` only if you actually clicked it this
session. For Flows, only tag `Observed-Live` if you ran the entire
journey to its actual end state — never mark a Flow as inferred. See §6.

### Step 5 — Review loop (expect this, don't skip it)
After a first pass, hand the draft to someone with product knowledge (or
re-check it against source material like walkthroughs/PRDs) and expect
corrections. This is a standard part of the process, not a sign the first
pass failed. Fold every correction back into the sheets **and** into this
guide if it reveals a new category of thing that gets missed generally.

---

## 6. The Verification column (why it exists)

**This works differently for Actions than for Flows — don't apply one
rule to both.**

### For Actions
Tag each row with how sure you are it's real:

| Tag | Meaning |
|---|---|
| `Observed-Live` | You personally clicked through this and saw it happen |
| `Confirmed-by-User` | A human with product knowledge told you this is how it works, but you haven't clicked it yourself |
| `Inferred-Needs-Verification` | You reasoned this must be true (e.g. from an admin-side config, or by analogy to a similar screen) but haven't verified it either way |

This three-tier system is acceptable for Actions because an Action is a
single, atomic fact about one element ("this icon exists," "this field
appears") — a reasonable inference about it is a small, contained claim.

### For Flows — never `Inferred`
**A Flow makes a much bigger claim: that a whole sequence of steps
produces a specific, exact outcome.** Reasoning your way to "this should
work" and recording it with a verification tag makes an untested,
multi-step behavioral claim look as solid as a tested one — which is far
more misleading than an inferred Action.

So for Flows, there are only two states:
- **`Observed-Live`** — you actually ran the whole journey and confirmed
  the exact outcome.
- **Not yet run** — Status is `NOT TESTED`, and the Verification column
  is left **blank**. Do not fill it with `Inferred-Needs-Verification` or
  anything else that implies a belief about the outcome. A flow that
  hasn't been executed has an unknown outcome, not an inferred one.

If you're tempted to write a confident-sounding Assert for a flow you
haven't run, that's a sign to mark it `NOT TESTED` with an empty
Verification cell, not to dress it up with a verification tag.

---

## 7. Reusable setup presets

To avoid re-describing the same starting state in every Flow row, define
short named presets and reference them consistently in the
Preconditions/Arrange column, e.g.:

| Preset | Meaning |
|---|---|
| `SETUP-FRESH` | Logged-in user, no prior in-progress work, no saved payment method |
| `SETUP-<CONFIG-A>` | A specific admin-side configuration relevant to this workflow (name it for what it configures) |

When a flow's setup diverges enough that it doesn't fit an existing
preset, either extend the preset's definition (if the divergence is small
and widely reusable) or spell out the one-off precondition directly in
that row rather than forcing a mismatched preset onto it.

---

## 8. Full workflow journeys, not fragments

**The most important rule in this guide: a Flow row must be a complete
journey with a verifiable end state — not a check on one setting in
isolation.**

Consider a workflow with a setting that changes how a cost is calculated
(e.g., a shipping-fee toggle between "per item" and "flat rate"). It's
tempting to write a Flow like:

> ❌ "Per-item shipping mode: total scales with item count."

This is a true fact, but it is **not a Flow** on its own — it never
confirms that fact survives all the way to a completed order at the
correct final charge. Compare it to:

> ✅ **F-CHECKOUT-SHIPPING-PERITEM** — Start: `SETUP-FRESH`, shipping
> configured per-item. Act: add 3 items to cart, proceed through
> checkout, pay. Assert: order confirmation shown; total charged =
> (per-item shipping rate × 3) + item costs, exactly matching the receipt.

The setting under test is now embedded *inside* a full start-to-finish
journey, and the Assert states the exact final outcome, not just an
intermediate calculation.

### The pattern to follow for every new Flow

1. **Start state** — named account/session state, ideally a reusable
   preset (§7).
2. **One goal** — what is this specific journey testing (a setting, a
   branch, a bug), embedded inside a real end-to-end use of the
   workflow, not a fragment of it.
3. **End state** — a specific, checkable outcome: a confirmation screen
   plus an exact total/value, or a specific block point with a reason
   nothing further can happen. Never end a Flow's Assert on a mid-flow
   observation alone.

A request to test "what happens if X setting is different" should almost
always be answered with a full journey that happens to have X configured
differently — not a standalone check of X.

---

## 9. Worked example: turning a screen into rows

Say you land on a step with: a Yes/No toggle controlling whether an
optional sub-step appears, plus a dropdown that's only relevant when the
toggle is Yes, plus global nav chrome (a "back" link, a "log out" link).

**Actions produced:**
```
ACT-NAV-BACK           (chrome pass - global, log once)
ACT-NAV-LOGOUT         (chrome pass - global, log once)
ACT-STEP-TOGGLE        (the Yes/No control)
ACT-STEP-SELECT-OPTION (the dropdown, only relevant when toggle=Yes)
```

**Flows produced (from the branch spike on the toggle, per §5 Step 2):**
```
F-OPTION-SELECTED-FULL-JOURNEY     (Yes -> pick an option -> complete
                                     the rest of the workflow -> verify
                                     the final outcome reflects that choice)
F-OPTION-SKIPPED-FULL-JOURNEY      (No -> confirm the optional sub-step
                                     is skipped BOTH going forward and
                                     going backward -> complete the rest
                                     of the workflow -> verify the final
                                     outcome has no trace of the skipped step)
F-OPTION-LOCKED-AFTER-DOWNSTREAM   (after completing the optional
                                     sub-step, try changing the toggle -
                                     does it now block, given data
                                     depends on it?)
```

Notice: one screen, one toggle, produced 2 actions and 3 full-journey
flows — because the branch spike was applied, and each flow still runs to
a real, verifiable end state rather than stopping at the toggle itself.

---

## 10. Pre-"done" checklist for any screen

Before marking a screen fully mapped, confirm:

- [ ] Chrome (header/footer/nav) elements logged as Actions
- [ ] Every visible control has an Action row, named after what it does
      (not its result)
- [ ] Every multi-state control has been branch-spiked (default,
      alternate, forward, backward, re-tested after downstream data)
- [ ] Dependencies column only has entries for non-obvious, cross-cutting
      cases (especially admin/config-driven ones) — not sequencing
      trivia restating what the workflow already implies
- [ ] Any modal/sub-wizard opened from this screen has been walked to its
      actual end state
- [ ] Every Flow row runs from a named start state to a verifiable end
      state (a completed workflow with a specific outcome/value, or a
      confirmed block point) — not a mid-flow observation on its own
- [ ] Every Flow's Assert ends with the standing data validation prompt
      for backend tables/fields, even if left for the tester to fill in
- [ ] Platform is recorded once, in its own column, on both sheets — not
      repeated inside Flow names or Action descriptions
- [ ] Verification column filled in honestly for every new Action row
      (`Observed-Live` / `Confirmed-by-User` / `Inferred-Needs-Verification`
      as appropriate)
- [ ] Every Flow is either `Observed-Live` (actually run end to end) or
      `NOT TESTED` with Verification left blank — never `Inferred`
- [ ] Nothing named after its outcome is sitting in the Actions sheet

---

## 11. Where product-specific knowledge goes

This guide intentionally contains no facts about any particular
application. When you map a real workflow, keep a **separate,
product-specific companion notes file** alongside this one, containing:

- A short description of that workflow's actual steps/screens
- The reusable setup presets defined for it (§7), spelled out concretely
- A living list of known gotchas/bugs found in it
- Anything else a newcomer to *that specific product* would need, that
  isn't part of the general method

That separation is what lets this guide be reused as-is for a completely
different workflow, or a completely different product, by anyone who
picks it up next.

