demo skill: look up routing and demo users in the project
Steps 2 and 4 carried copy-paste from another project (lib/hub_web/router.ex, alias Hub.Accounts, /users/log-in with user[email]). A stale path there sends the agent to a router that does not exist, and a guessed module alias fails at run time. Both are now generic instructions to read the project: - route map: locate the router by searching for `use Phoenix.Router`, then read its scopes, pipelines and live_sessions to see what is public and what needs a session - authentication: only when the route actually needs it; take credentials from documented demo accounts or the project's seeds, create a demo user through the project's own path (seeds, registration route, or the accounts function found by grep - never a guessed alias), and read the login route and form selectors off the router and rendered form The port example keeps its concrete app/endpoint pair, now labelled as an example with the grep that finds the right names, plus a note to use the project's toolchain/build wrapper instead of bare `mix`. make check green.
This commit is contained in:
+45
-30
@@ -46,7 +46,7 @@ Build an understanding of what to demo from these sources (in priority order):
|
||||
Explicit scenario (--scenario): If provided, use as primary guide.
|
||||
Plan file: Read the plan's Goal, Acceptance Criteria, and completed Steps.
|
||||
Recent commits: Run git log --oneline -15 and git diff main...HEAD --stat to identify changed files and commit messages.
|
||||
Route map: Cross-reference changed files against known LiveView routes in the router (lib/hub_web/router.ex).
|
||||
Route map: Find the router yourself - do not assume a path. Search the project for its router (`grep -rn "use Phoenix.Router" lib/`; conventionally lib/<app>_web/router.ex), then read the scopes, pipelines and live_sessions to learn which routes the feature touches, which are public, and which require a logged-in user.
|
||||
|
||||
From these sources, produce a demo outline:
|
||||
|
||||
@@ -58,60 +58,75 @@ From these sources, produce a demo outline:
|
||||
If no plan exists and commits are ambiguous, ask the user for a brief description of what to demo.
|
||||
3. Resolve the dev port, then check the server
|
||||
|
||||
Never assume a port. The port lives in the project config: `app/config/dev.exs`
|
||||
sets `port: String.to_integer(System.get_env("PORT") || "8056")`, so `$PORT`
|
||||
wins and the config default is the fallback. Ask the app, from the repo root:
|
||||
Never assume a port. Read it from the project config, from the repo root:
|
||||
|
||||
DEMO_PORT=$(cd app && mise exec -- mix run --no-start -e \
|
||||
DEMO_PORT=$(cd app && mix run --no-start -e \
|
||||
'IO.puts(Application.get_env(:firehose, FirehoseWeb.Endpoint)[:http][:port])')
|
||||
DEMO_BASE_URL="http://localhost:${DEMO_PORT}"
|
||||
|
||||
curl -s -o /dev/null -w "%{http_code}" "$DEMO_BASE_URL/"
|
||||
|
||||
Use `Application.get_env/2`, not `FirehoseWeb.Endpoint.config(:http)`: with
|
||||
`--no-start` the endpoint's ETS table does not exist and `config/1` raises.
|
||||
Adapt that command to the project: find the app/endpoint pair in `config/*.exs`
|
||||
(`grep -rn "Endpoint," config/`) and use the same names. If the config reads the
|
||||
port from the environment, the value above already reflects it. Do not resolve
|
||||
the port with `<Endpoint>.config(:http)`: with `--no-start` the endpoint's ETS
|
||||
table does not exist and it raises.
|
||||
|
||||
If the project pins a toolchain or wraps builds, use its wrapper for every
|
||||
command below (`mise exec -- mix ...`, asdf shims, or its `make` targets - check
|
||||
AGENTS.md/README first). Bare `mix` is not a safe assumption.
|
||||
|
||||
If the server is not reachable:
|
||||
|
||||
The Phoenix dev server is not running. Start it now?
|
||||
|
||||
mkdir -p .tmp && (cd app && PORT=$DEMO_PORT mise exec -- mix phx.server \
|
||||
mkdir -p .tmp && (cd app && PORT=$DEMO_PORT mix phx.server \
|
||||
> ../.tmp/phx-demo.log 2>&1 &)
|
||||
|
||||
Then poll `$DEMO_BASE_URL` for up to 10 seconds. If it still fails, read
|
||||
`.tmp/phx-demo.log`: a bundle error about `highlight.js` (or any module) means
|
||||
`app/assets/node_modules` is missing - run `make -C app assets` (root
|
||||
`make deps` does it too). Only when the server really cannot come up, proceed
|
||||
with backend-only evidence (skip all browser screenshots) and note the
|
||||
limitation in the demo document.
|
||||
`.tmp/phx-demo.log`: an error about an unresolvable JS module means the
|
||||
project's JS packages are not installed - run its assets install step (in this
|
||||
repository `make -C app assets`, which root `make deps` also runs). Only when
|
||||
the server really cannot come up, proceed with backend-only evidence (skip all
|
||||
browser screenshots) and note the limitation in the demo document.
|
||||
|
||||
Use `$DEMO_BASE_URL` for every URL below - there is no default port to fall
|
||||
back on.
|
||||
4. Handle authentication
|
||||
4. Handle authentication (only if the route needs it)
|
||||
|
||||
The app requires authentication for LiveView routes. Before capturing UI screenshots:
|
||||
Decide this from the project, not from this file. If every page you need is
|
||||
public, skip this step. A route needs a session when the router found in step 2
|
||||
puts it inside a `pipe_through` that requires a logged-in user, or inside a
|
||||
`live_session` guarded that way.
|
||||
|
||||
Ensure a demo user exists:
|
||||
When you do need a session, read each part from the project instead of assuming
|
||||
it:
|
||||
|
||||
mix run -e "
|
||||
alias Hub.Accounts
|
||||
case Accounts.get_user_by_email(\"demo@example.com\") do
|
||||
nil -> Accounts.register_user(%{email: \"demo@example.com\", password: \"demodemo1234\"})
|
||||
user -> {:ok, user}
|
||||
end
|
||||
"
|
||||
- Credentials: check README, AGENTS.md, docs and the project's seeds
|
||||
(`priv/repo/seeds.exs`, a `mix demo`-style task). Use documented demo
|
||||
credentials if they exist - never invent them.
|
||||
- Demo user: if nothing is documented, create one through the project's own
|
||||
path, in this order: run its seeds; use its registration route; call the
|
||||
accounts/context function you find by searching for it (`grep -rn
|
||||
"get_user_by_email\|register_user\|create_user" lib/`). Copy the exact module,
|
||||
function and field names from the source; do not guess an alias.
|
||||
- Login route, form fields and submit button: read them off the router and out of
|
||||
the rendered form (`rodney html form` or `rodney ax-tree`) rather than
|
||||
assuming a path or an input name.
|
||||
|
||||
Log in via rodney:
|
||||
Then drive the form with the selectors you just read:
|
||||
|
||||
rodney start
|
||||
rodney open "$DEMO_BASE_URL/users/log-in"
|
||||
rodney wait "input[name='user[email]']"
|
||||
rodney input "input[name='user[email]']" "demo@example.com"
|
||||
rodney input "input[name='user[password]']" "demodemo1234"
|
||||
rodney click "button[type='submit']"
|
||||
rodney open "$DEMO_BASE_URL<login-route>"
|
||||
rodney wait "<email-input-selector>"
|
||||
rodney input "<email-input-selector>" "<email>"
|
||||
rodney input "<password-input-selector>" "<password>"
|
||||
rodney click "<submit-selector>"
|
||||
rodney waitidle
|
||||
|
||||
If login fails, warn and proceed with backend-only evidence.
|
||||
Confirm the session took - `rodney url` should have left the login route, and
|
||||
the page should show the user (name, avatar, menu). If login fails, warn, note it
|
||||
in the demo document, and proceed with backend-only evidence.
|
||||
5. Initialize the demo document
|
||||
|
||||
Slugify the feature name (lowercase, hyphens, no special chars). Then:
|
||||
|
||||
Reference in New Issue
Block a user