agentleFS
WikiEducationFoundationWikiEducationFoundation/WikiEduDashboard/.claude/skills/feature-spec/SKILL.md

feature-spec

Skill431 starsChanged 8 months agoMITView on GitHub

Write browser-based Capybara feature specs for WikiEduDashboard controllers and views. Use this skill when asked to improve test coverage, write feature specs, add browser tests, or cover a controller with specs.

21 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use changelog.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • HashiCorpSkill

    changelog

    Add a `.changelog/<PR_NUMBER>.txt` entry for a GitHub Pull Request, commit, and push.

    Also in 4 projects that use this

The file

We split this skill into the rules it gives an agent

8 rules. 0 are common, 3 are distinctive, and 5 are very specific to this project.

  • 0

    Common

    Most of the 19 edited versions we read keep these.

  • 3

    Distinctive

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Write concise, high-level Capybara feature specs that exercise controller code the way a real user would — visiting pages, filling forms, …

    line 8
  2. Distinctive:

    Before writing anything, read:

    line 16
  3. Very specific:

    No constants at top level of describe block — use let

    line 67
  4. Very specific:

    Always use bin/feature-spec to run specs — it prints rspec's normal colored output, then appends a colored coverage summary for the target …

    line 90
  5. Very specific:

    If the user says "show me", prefix with HEADED=1 so Chrome opens visibly:

    line 108
  6. Very specific:

    If the user says "show me slowly", add SLOW=0.3 to pause after each click, fill, check, and select:

    line 114
  7. Very specific:

    If the user says "show me very slowly", use SLOW=10:

    line 120
  8. Distinctive:

    Add a new scenario (or extend an existing one) that exercises it

    line 132

“Common” is measured: kept by at least 6 in 10 of the 19 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Feature Spec Writer

Write concise, high-level Capybara feature specs that exercise controller code the way a real user would — visiting pages, filling forms, clicking buttons — rather than testing implementation details.

Goal

Cover every executable line in the target file, using the fewest, most readable specs possible. Start by exploring, write the spec, run it, check coverage, and iterate until coverage is complete.

Phase 1: Explore

Before writing anything, read:

  1. The target file — understand every action, before_action, private method, and branch
  2. The routes (config/routes.rb) — find the URL paths
  3. The views — know what content will be on the page (text to assert, form fields to fill)
  4. Error handling — check lib/errors/rescue_errors.rb for how exceptions render (what text appears for unauthorized, not-signed-in, etc.)
  5. Relevant factories — spec/factories/ to know what's available and what associations are required
  6. A few existing feature specs in spec/features/ for patterns

Note every branch in check_permission or similar guards — each branch needs its own scenario.

Phase 2: Write the spec

File location: spec/features/<controller_name_snake>_spec.rb

Template

# frozen_string_literal: true

require 'rails_helper'

describe 'Brief description of feature', type: :feature, js: true do
  let(:course) { create(:course) }
  let(:user)   { create(:user) }
  # ... other shared setup

  describe 'as [role/scenario]' do
    before { login_as(user) }

    it 'does the main thing' do
      visit '/path/to/page'
      expect(page).to have_content 'Expected text'
      # interact with the page...
      click_button 'Submit'
      expect(page).to have_content 'Success message'
    end
  end

  # one describe block per distinct permission/scenario
end

Key conventions

  • require 'rails_helper' — always
  • type: :feature, js: true — always put both on the top-level describe. Every feature spec runs through Selenium so "show me" works on any spec.
  • Auth: login_as(user) in a before block (Warden test helpers, already configured)
  • Factories: create(:factory_name, association: other_record, field: value)
  • Instructors: create(:courses_user, user: instructor, course: course, role: CoursesUsers::Roles::INSTRUCTOR_ROLE)
  • Admins: create(:admin)
  • No constants at top level of describe block — use let

What to cover

For a typical permission-gated controller, you need one scenario per permission branch:

ScenarioWhat to check
Owner/authorized user — happy pathForm renders AND form submits successfully
AdminPage renders
InstructorPage renders
Unauthorized (signed in, wrong user)Error text visible (e.g., "not authorized")
UnauthenticatedSign-in prompt visible (e.g., "Please sign in.")

Collapse the "can view" cases for admin and instructor into minimal single it blocks — just visit the page and assert one piece of content. Save the fuller interaction test for the main authorized-user scenario.

Error page text

  • NotSignedInError → renders errors/unauthorized → shows "Please sign in." in flash
  • ActionController::InvalidAuthenticityToken → rescue_invalid_token → renders plain text "not authorized" (check lib/errors/rescue_errors.rb and config/locales/en.yml for the exact phrase)

Phase 3: Run and iterate

Always use bin/feature-spec to run specs — it prints rspec's normal colored output, then appends a colored coverage summary for the target file:

bin/feature-spec spec/features/<spec_file>_spec.rb [app/controllers/<target>_controller.rb]

The target file argument is optional; if omitted it's guessed from the spec name. After every run, always report the key results as a text message (outside the collapsed tool output):

  • Pass/fail count and time (from the rspec summary line)
  • Coverage percentage and covered/total lines
  • Uncovered line numbers if any

Example: 5 examples, 0 failures (3.4s) — 100% coverage (22/22 lines)

The coverage summary colors in the script output:

  • Green — 100% covered
  • Yellow — ≥80% covered
  • Red — below 80%, with a list of uncovered line numbers

If the user says "show me", prefix with HEADED=1 so Chrome opens visibly:

HEADED=1 bin/feature-spec spec/features/<spec_file>_spec.rb

If the user says "show me slowly", add SLOW=0.3 to pause after each click, fill, check, and select:

HEADED=1 SLOW=0.3 bin/feature-spec spec/features/<spec_file>_spec.rb

If the user says "show me very slowly", use SLOW=10:

HEADED=1 SLOW=10 bin/feature-spec spec/features/<spec_file>_spec.rb

The SLOW value is the pause in seconds — SLOW=0.1 for a quick flash, SLOW=1 for a full second, SLOW=10 for a very long pause, etc.

A line count of None in the raw resultset means non-executable (comments, blank lines, end). Only 0 means missed — those are what appear in the "Uncovered lines" list.

Iterate — for each uncovered line:

  • Identify which branch or condition it's in
  • Add a new scenario (or extend an existing one) that exercises it
  • Re-run and re-check

Phase 4: Rubocop

bundle exec rubocop spec/features/<spec_file>_spec.rb

Fix any offenses before finishing.

Tips

  • Minimal factory setup — only set associations that are actually used by the controller or view. Don't add article: if the code handles nil articles gracefully.
  • Assert content, not implementation — check for flash messages, page text, and form fields, not internal state (except when verifying a save, like checking record.reload.attribute).
  • One submit test is enough — if the form submit path is covered once, don't repeat it for admin/instructor scenarios.
  • Check the view for assert text — the exact strings on the page come from the view template or i18n keys.
  • details: hashes — when a model uses serialize :details, type: Hash, pass the hash directly in the factory: create(:alert, details: { key: 'value' }).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.