Testing Patterns
dilolabs/nosia
Writes Minitest tests with fixtures following 37signals conventions.
Create a controller with commands, read model queries, routes, and integration tests
$ npx skills add RailsEventStore/ecommerce --skill controller -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install RailsEventStore/ecommerce controller --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/controller .claude/skills/controller && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "controller" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/controller into .claude/skills/controller/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "controller", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/controllerType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add RailsEventStore/ecommerce --skill controller -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install RailsEventStore/ecommerce controller --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/controller .agents/skills/controller && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "controller" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/controller into .agents/skills/controller/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "controller", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add RailsEventStore/ecommerce --skill controller -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install RailsEventStore/ecommerce controller --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/controller .cursor/skills/controller && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "controller" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/controller into .cursor/skills/controller/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "controller", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/RailsEventStore/ecommerce.git --path .claude/skills/controller--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add RailsEventStore/ecommerce --skill controller -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install RailsEventStore/ecommerce controller --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/controller .gemini/skills/controller && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "controller" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/controller into .gemini/skills/controller/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "controller", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install RailsEventStore/ecommerce controllerInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add RailsEventStore/ecommerce --skill controller -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/controller .github/skills/controller && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "controller" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/controller into .github/skills/controller/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "controller", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add RailsEventStore/ecommerce --skill controller -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install RailsEventStore/ecommerce controller --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/RailsEventStore/ecommerce.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/controller .opencode/skills/controller && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "controller" agent skill from https://github.com/RailsEventStore/ecommerce/tree/master/.claude/skills/controller into .opencode/skills/controller/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "controller", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
controllerCreate a controller with commands, read model queries, routes, and integration tests
Controller is an agent skill from RailsEventStore/ecommerce. Create a controller with commands, read model queries, routes, and integration tests
Its SKILL.md is about 1.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering Integration testing. It works with Ruby on Rails. The repository describes itself as: Application with CQRS and Event Sourcing built on Rails and Rails Event Store. The licence is MIT.
10 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 42c6c23. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
railsmakeFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Controller loads about 1.9k tokens when it runs. Until then it costs about 24 tokens; SKILL.md has 419 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from RailsEventStore/ecommerce at commit 42c6c23, republished under its MIT licence (© RailsEventStore). 419 words, ~1,905 tokens.
.claude/skills/controller/SKILL.md (or your agent's skills folder).Use this skill when asked to create a new controller or add actions to an existing controller in any Rails app under apps/.
Determine which app the controller belongs to. Default is apps/rails_application/ unless specified.
Before writing any code, clarify:
admin/, client/)Create a test file at test/integration/{controller_name}_test.rb.
require "test_helper"
class ResourceNameTest < InMemoryRESIntegrationTestCase
def test_list_resources
get "/resources"
assert_response :success
end
def test_create_resource
post "/resources", params: { name: "Test" }
follow_redirect!
assert_select("td", "Test")
end
def test_update_resource
resource_id = create_resource("Original")
patch "/resources/#{resource_id}", params: { name: "Updated" }
follow_redirect!
assert_select("td", "Updated")
end
private
def create_resource(name)
post "/resources", params: { name: name }
follow_redirect!
# extract ID from page or use read model facade
ReadModel.all.last.uid
end
endIntegration test conventions:
InMemoryRESIntegrationTestCaseget, post, patch, deletefollow_redirect! after redirecting actionsassert_response, assert_selectAdd to config/routes.rb:
resources :resources, only: [:index, :show, :new, :create, :edit, :update, :destroy] do
member do
post :custom_action
end
collection do
delete :clear_all
end
endRoute conventions:
resources with only: to limit actionsmember do (operates on one record) or collection do (operates on many)namespace :admin do
resources :stores, only: [:index, :new, :create]
endclass ResourcesController < ApplicationController
def index
@resources = ReadModel.all
end
def show
@resource = ReadModel.find_by_uid(params[:id])
end
def new
@resource_id = SecureRandom.uuid
end
def create
ActiveRecord::Base.transaction do
command_bus.call(Domain::CreateResource.new(
resource_id: params[:resource_id],
name: params[:name]
))
end
redirect_to resources_path, notice: "Resource was successfully created"
end
def edit
@resource = ReadModel.find_by_uid(params[:id])
end
def update
command_bus.call(Domain::UpdateResource.new(
resource_id: params[:id],
name: params[:name]
))
redirect_to resource_path(params[:id]), notice: "Resource was successfully updated"
end
def destroy
command_bus.call(Domain::RemoveResource.new(resource_id: params[:id]))
redirect_to resources_path, notice: "Resource was successfully removed"
end
endCommand dispatch:
command_bus.call(Command.new(...)) to dispatch commandsActiveRecord::Base.transaction do ... endid = SecureRandom.uuidRead model queries:
ReadModel.all, ReadModel.find_by_uid(id)Redirects:
redirect_to path, notice: "..."redirect_to path, alert: "..."Error handling:
rescue/else for domain exceptions:def submit
SomeService.new(params[:id]).call
rescue Domain::SomeError => e
redirect_to edit_path(params[:id]), alert: e.message
else
redirect_to show_path(params[:id]), notice: "Success"
endBefore actions:
before_action :load_resource, only: [:show, :edit, :update]
private
def load_resource
@resource = ReadModel.find_by_uid(params[:id])
endFor non-trivial forms, create a form object in the controller file or a separate file:
class ResourceForm
include ActiveModel::Model
include ActiveModel::Attributes
include ActiveModel::Validations
attribute :name, :string
attribute :price, :decimal
attribute :resource_id, :string
validates :name, presence: true
validates :price, presence: true, numericality: { greater_than: 0 }
endUse in the controller:
def create
form = ResourceForm.new(**resource_params)
unless form.valid?
return render "new", locals: { errors: form.errors }, status: :unprocessable_entity
end
ActiveRecord::Base.transaction do
command_bus.call(Domain::CreateResource.new(resource_id: form.resource_id, name: form.name))
end
redirect_to resources_path, notice: "Created"
endWhen a controller action involves complex coordination (multiple commands, event subscriptions, error handling), extract to a service:
# app/services/{namespace}/submit_service.rb
module Namespace
class SubmitService
def initialize(id)
@id = id
end
def call
ActiveRecord::Base.transaction do
command_bus.call(Domain::Submit.new(id: @id))
end
end
private
def command_bus
Rails.configuration.command_bus
end
end
endFor controllers under a namespace (e.g. admin/, client/):
# app/controllers/admin/resources_controller.rb
module Admin
class ResourcesController < ApplicationController
def index
@resources = ReadModel.all
end
end
endWith a base controller for shared behavior:
# app/controllers/client/base_controller.rb
module Client
class BaseController < ApplicationController
layout "client_panel"
before_action :ensure_logged_in
private
def ensure_logged_in
# auth check
end
end
end
# app/controllers/client/orders_controller.rb
module Client
class OrdersController < BaseController
def index
@orders = ClientOrders.orders_for_client(current_client_id)
end
end
endCreate ERB views in app/views/{controller_name}/:
index.html.erb — list viewshow.html.erb — detail viewnew.html.erb — form for creatingedit.html.erb — form for editingViews query data via instance variables set in controller (@resources, @resource).
rails test test/integration/{test_file}.rb — integration tests passmake test — all tests green© RailsEventStore, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/controller of RailsEventStore/ecommerce.
Open the folder on GitHubat commit 42c6c23
Controller next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Controller this skillRailsEventStore/ecommerce | 507 | — | ~1.9k | Automated safety check: Pass | MIT | |
| Testing Patternsdilolabs/nosia | 213 | 1 repos | ~1.4k | Automated safety check: Pass | MIT | |
| OpenHarness End-to-End EvalsHKUDS/OpenHarness | 16k | 1 repos | ~2.1k | Automated safety check: Notes | MIT | |
| E2E Testinglangflow-ai/langflow | 156k | — | ~3.3k | Automated safety check: Pass | MIT | |
| Test Writing WorkflowiOfficeAI/AionUi | 33k | 1 repos | ~1.2k | Automated safety check: Pass | Apache-2.0 | |
| Remote Executor Integration Testsopeninterpreter/openinterpreter | 69k | 2 repos | ~842 | Automated safety check: Pass | Apache-2.0 |
dilolabs/nosia
Writes Minitest tests with fixtures following 37signals conventions.
HKUDS/OpenHarness
Validates OpenHarness features by running real multi-turn agent loops with live LLM calls against an unfamiliar codebase, checking actual tool execution.
langflow-ai/langflow
Write and review Playwright E2E tests for Langflow. An agent skill from langflow-ai/langflow.
iOfficeAI/AionUi
Sets the test-writing workflow for the repository: risk-first scenario lists, behavior-focused Vitest tests, a full run before each commit and a coverage target.
openinterpreter/openinterpreter
Explains how to run agent integration tests against remote executors, using Docker for Linux or Wine for Windows, and how to opt tests in or skip them.
airbytehq/airbyte
Starts a throwaway MongoDB 7.0 replica set and runs the Airbyte spec, check, discover and read commands against source-mongodb-v2 images for local end-to-end testing.
RailsEventStore/ecommerce
Create atomic git commits following project conventions. An agent skill from RailsEventStore/ecommerce.
RailsEventStore/ecommerce
Create a new domain bounded context with aggregates, commands, events, and handlers
RailsEventStore/ecommerce
Scaffold a new Rails app with event sourcing, following project conventions (todomvc as reference)
RailsEventStore/ecommerce
Plan a new feature end-to-end — impact analysis across all layers, start-from-the-middle slicing into deployable steps, then delegating to /domain, /read-model, /controller skills
RailsEventStore/ecommerce
Build a new read model following project conventions (event handlers, tests, migration, configuration)
RailsEventStore/ecommerce
Upgrade Rails framework to a newer version following the smooth upgrade methodology
Works with
Categories
Create a controller with commands, read model queries, routes, and integration tests. Controller is an agent skill from RailsEventStore/ecommerce.
Controller fits situations like: tasks that involve Integration testing.
Run `npx skills add RailsEventStore/ecommerce --skill controller -a claude-code`. Or copy the skill folder (.claude/skills/controller in RailsEventStore/ecommerce) into .claude/skills/controller in your project. Claude Code loads it when a task matches its description.
Run `npx skills add RailsEventStore/ecommerce --skill controller -a codex`. Or copy the skill folder (.claude/skills/controller in RailsEventStore/ecommerce) into .agents/skills/controller in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add RailsEventStore/ecommerce --skill controller -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/controller, .gemini/skills/controller, .github/skills/controller and .opencode/skills/controller in your project.
Going by SKILL.md and its folder, Controller needs the command-line tools its instructions call (rails and make).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Controller is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 1.9k tokens (SKILL.md is roughly 7.6k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Controller: Testing Patterns (dilolabs/nosia, 213 stars), OpenHarness End-to-End Evals (HKUDS/OpenHarness, 16k stars), E2E Testing (langflow-ai/langflow, 156k stars) and Test Writing Workflow (iOfficeAI/AionUi, 33k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
RailsEventStore (a GitHub organization) maintains it in RailsEventStore/ecommerce, which has 507 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on September 21, 2026.
Source: RailsEventStore/ecommerce on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.