| name | frontend-test |
| description | Run frontend tests for Graft via Chrome browser automation. Broken into sections — pick any combination, create a todo list, and execute. Invoke with /frontend-test and optionally specify which sections (e.g. "/frontend-test setup rename-validation rename-nested-to-flat"). If no sections specified, run all. |
| allowed-tools | Read, Bash, mcp__claude-in-chrome__tabs_context_mcp, mcp__claude-in-chrome__tabs_create_mcp, mcp__claude-in-chrome__navigate, mcp__claude-in-chrome__computer, mcp__claude-in-chrome__javascript_tool, mcp__claude-in-chrome__find, mcp__claude-in-chrome__form_input, mcp__claude-in-chrome__zoom, mcp__claude-in-chrome__get_page_text, TaskCreate, TaskUpdate, TaskList |
Graft Frontend Test Skill
How to Use
When invoked, determine which sections to run based on args (or all if none). Create a TaskCreate entry per section, then execute each using Chrome automation, marking done/fail as you go.
Available sections:
setup — connect API, enable tags + labels
tag-graph — verify green tag nodes, hierarchy edges
node-preview-doc — document node preview correctness
node-preview-tag-leaf — leaf tag node preview
node-preview-tag-parent — parent tag preview (children section)
rename-validation — dialog input validation (special chars, trailing slash, nested)
rename-flat-to-flat — rename non-nested → non-nested
rename-nested-to-flat — rename nested → non-nested (child loses parent)
rename-flat-to-nested — rename non-nested → nested (gains parent)
rename-parent — rename parent tag (all children renamed too)
refresh-incremental — edit tag in Craft, refresh, verify update
refresh-progress — verify "Refreshing graph" title + progress bar in Connect panel
Setup Notes
Dev server: ensure bun run dev is running on :3000 before starting.
Credentials: read from .env — API_URL and API_KEY.
Connecting via JS (form_input doesn't always persist through React state):
const nativeSet = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
const urlInput = document.querySelector('input[type="url"]');
const keyInput = document.querySelector('input[type="password"]');
nativeSet.call(urlInput, 'API_URL_VALUE');
urlInput.dispatchEvent(new Event('input', { bubbles: true }));
nativeSet.call(keyInput, 'API_KEY_VALUE');
keyInput.dispatchEvent(new Event('input', { bubbles: true }));
Then click Save connection by coordinate (not ref — avoids chrome-extension URL redirect bug).
Graph loads in ~2 min on first load. Check for absence of "Loading graph" panel before proceeding.
Section Definitions
setup
Goal: App connected, tags visible, labels visible.
Steps:
- Get tab context, navigate to http://localhost:3000
- Read credentials from
.env
- Fill form via JS nativeSet pattern, click Save connection (~176, 381)
- Wait 30s, screenshot — check "Loading graph" message visible
- Wait 30s more, screenshot — check loading panel gone, nodes present
- Click Customize icon (4th icon in toolbar, ~163, 75)
- Click "Show" labels button
- Click "Tags" toggle to enable
- Close Customize panel
- Screenshot — verify green tag nodes visible with labels
Pass: green nodes visible, labels showing on graph.
tag-graph
Goal: Tag nodes are green, hierarchy edges connect parent→child.
Steps:
- Zoom into tag cluster (scroll up on tag area)
- Screenshot
- Verify: tag nodes are green (#34d399 color), NOT grey
- Verify: hierarchy edge visible between a parent tag (e.g.
#corp) and its child (e.g. #corp/sub)
- Zoom in closer if needed
Pass: green color confirmed, at least one parent→child edge visible.
node-preview-doc
Goal: Document node preview shows tags section, collapsible links, no Document ID for tags.
Steps:
- Click any document node (grey node)
- Screenshot right panel
- Verify: panel shows title, "document" badge, connection count
- Verify: "Document ID" field present with UUID
- If doc has tags: "Tags (N)" section appears above Links to/from with green chip buttons
- Click "Links to (N)" header — list collapses
- Click again — list expands
- Same for "Linked from (N)"
Pass: doc ID shown, tags as chips if any, links collapsible.
node-preview-tag-leaf
Goal: Leaf tag node preview is correct.
Steps:
- Click a leaf tag node (green, no children)
- Screenshot right panel
- Verify: title starts with
#, badge shows "tag"
- Verify: NO "Document ID" section
- Verify: "Rename Tag" button present
- If nested: "Tags (parent)" section shows parent chip
- If not nested: no "Tags (parent)" section
- Verify: NO "Tags (children)" section
- Verify: "Links to (N)" shows documents
Pass: all above hold.
node-preview-tag-parent
Goal: Parent tag node shows correct children.
Steps:
- Click a parent tag node (green, larger — hub of nested tags)
- Screenshot right panel
- Verify: "Tags (children)" section present with child tag chips
- Verify: child tags match what's visible as hierarchy children in the graph
- Click a child chip — panel updates to that child tag
Pass: children listed correctly, navigation works.
rename-validation
Goal: Input validation works correctly in rename dialog.
Steps:
- Click any tag node → click "Rename Tag"
- Screenshot (initial state: old tag name pre-filled, caption shows old tag static)
- Clear input, type
corp @invalid
- Verify: red error "Tag names can only contain letters, numbers, underscores, and slashes"
- Verify: Preview Changes disabled
- Clear, type
newname/
- Verify: grey advisory "Continue typing to complete the nested tag name." (NOT red)
- Verify: Preview Changes disabled
- Continue typing
sub (input now newname/sub)
- Verify: advisory disappears, no error
- Verify: Preview Changes enabled
- Clear, type same name as current tag
- Verify: Preview Changes disabled (unchanged)
- Press Escape or Cancel
Pass: all validation states correct.
rename-flat-to-flat
Goal: Rename a non-nested tag to another non-nested name. Graph updates.
Pick a leaf non-nested tag (e.g. #internal).
Steps:
- Click tag → Rename Tag
- Clear input, type new non-nested name (e.g.
internalv2)
- Click Preview Changes
- Verify confirm screen: correct doc count, correct mapping shown (
#internal → #internalv2)
- Click Rename
- Screenshot during execution — verify progress message "Loading block content for document X of N…"
- Wait for completion
- Verify done screen: X documents updated, X blocks modified
- Click Done, wait ~15s for graph reload
- Verify:
#internalv2 green node present in graph, #internal gone
- Click
#internalv2 node — verify title, no parent section (leaf), correct doc count
Pass: rename executed, graph updated, node preview correct.
rename-nested-to-flat
Goal: Rename a nested tag (e.g. #corp/sub) to a flat name. Parent's children section updates.
Steps:
- Identify a nested tag (has
/ in name)
- Note its parent tag name
- Click nested tag → Rename Tag
- Type flat name (no
/), Preview Changes, Rename
- Wait for graph reload
- Click parent tag — verify "Tags (children)" no longer includes the renamed tag
- Click new flat tag — verify no "Tags (parent)" section
- Verify old nested tag node gone from graph
Pass: hierarchy correctly removed after rename.
rename-flat-to-nested
Goal: Rename a flat tag to a nested name under an existing parent. Hierarchy created.
Steps:
- Identify a flat (non-nested) tag
- Note the name of an existing parent tag to nest under (e.g.
#corp)
- Click flat tag → Rename Tag
- Type
existingparent/newchild, Preview Changes, Rename
- Wait for graph reload
- Click parent tag — verify "Tags (children)" now includes the new child
- Click new child tag — verify "Tags (parent)" shows the parent
- Verify hierarchy edge visible in graph
Pass: hierarchy created correctly after rename.
rename-parent
Goal: Renaming a parent tag renames all children too.
Steps:
- Identify a parent tag with at least one child (e.g.
#corp with #corp/sub)
- Note all child tag names
- Click parent tag → Rename Tag
- Type new name (e.g.
newcorp), Preview Changes
- Verify confirm screen shows ALL affected tags:
#corp → #newcorp, #corp/sub → #newcorp/sub
- Click Rename, wait for completion
- Verify done screen: correct counts
- Wait for graph reload
- Verify:
#newcorp present, #newcorp/sub present, old names gone
- Click
#newcorp — verify Tags (children) shows #newcorp/sub
- Click
#newcorp/sub — verify Tags (parent) shows #newcorp
Pass: parent + all children renamed, hierarchy preserved.
refresh-incremental
Goal: Editing a tag in Craft and refreshing Graft reflects the change without full reload.
Pre-condition: manually edit a document in Craft to change a tag (e.g. #corp/orrr → #corp/op).
Steps:
- Note the current tag name in Graft graph
- (User edits tag in Craft app — cannot be automated)
- Click Refresh button (last icon in toolbar)
- Wait ~30s
- Verify: old tag node gone, new tag node present
- Click parent tag — verify Tags (children) updated (old child gone, new child present)
- Click new tag node — verify Tags (parent) correct
Pass: incremental refresh reflects Craft changes correctly.
refresh-progress
Goal: Refresh button shows "Refreshing graph" title + progress in Connect panel.
Pre-condition: there must be actual changes (incremental refresh with no changes shows nothing).
Steps:
- Open Connect panel (plug icon, 1st icon)
- Click Refresh button immediately
- Screenshot quickly — verify Connect panel shows:
- Title: "Refreshing graph" (NOT "Loading graph")
- Progress message visible
- Progress bar advancing
- Wait for completion
- Verify panel returns to normal state (no progress bar)
Pass: "Refreshing graph" title shown, progress visible during refresh.
Reporting
After all sections complete, output a table:
| Section | Result | Notes |
|---|
| setup | ✓ Pass / ✗ Fail | ... |
| ... | ... | ... |
Flag any failures with screenshots and specific observations.