Last active
February 11, 2026 17:01
-
-
Save drhenner/13161c86fbedb9bd591485cfdb949305 to your computer and use it in GitHub Desktop.
Cursor rules for testing & security
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Manage CODEOWNERS when creating new files | |
| alwaysApply: true | |
| --- | |
| # CODEOWNERS Management | |
| When creating a new file, **always** add an entry to `.github/CODEOWNERS`. | |
| ## Workflow | |
| 1. **Ask about ownership**: "Should this file be owned by @zendesk/fang?" | |
| 2. **If not fang, suggest logical teams** based on the file path/type: | |
| - **Rules/automation**: @zendesk/fang, @zendesk/libretto | |
| - **Authentication/SSO**: @zendesk/authentication | |
| - **Users/roles**: @zendesk/users-platform | |
| - **Tickets**: @zendesk/ticket-platform, @zendesk/ticket-product | |
| - **Platform objects/custom fields**: @zendesk/vinyl, @zendesk/libretto | |
| - **Operations/infra**: @zendesk/classic-operations, @zendesk/squonk | |
| - **Search**: @zendesk/support-search | |
| - **Views**: @zendesk/support-views | |
| - **GraphQL**: @zendesk/skvader, @zendesk/one-graph | |
| - **Rails/Ruby core**: @zendesk/ruby-core | |
| - **Testing/CI**: @zendesk/classic-operations | |
| 3. **Add entry in alphabetical order**: The file must be sorted alphabetically | |
| 4. **Format**: `path/to/file @zendesk/team-name` | |
| ## Example | |
| ``` | |
| # User creates: app/jobs/ticket_automation_job.rb | |
| Ask: "Should this be owned by @zendesk/fang?" | |
| If yes: Add `app/jobs/ticket_automation_job.rb @zendesk/fang` | |
| If no: "This looks like it could be: @zendesk/fang (automation), @zendesk/ticket-platform (tickets), or @zendesk/classic-operations (general). Which team should own it?" | |
| ``` | |
| ## Important Notes | |
| - CODEOWNERS must be kept in **alphabetical order** (see file header comment) | |
| - Use full paths, not globs (unless following existing patterns in the file) | |
| - Multiple teams can own the same file (space-separated) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Guidelines for testing controller params and strong parameters | |
| globs: "{test/**/controllers/**/*_test.rb,components/**/test/**/controllers/**/*_test.rb}" | |
| alwaysApply: false | |
| --- | |
| # Controller Test Params Guidelines | |
| ## Don't Stub Params | |
| Never stub or mock `params` in controller tests. Pass real params through the request: | |
| ```ruby | |
| # ❌ BAD - stubbing params | |
| controller.stubs(:params).returns(ActionController::Parameters.new(name: "test")) | |
| # ✅ GOOD - pass params through the request | |
| post :create, params: { name: "test" } | |
| ``` | |
| ## Verify Strong Parameters Indirectly | |
| Don't write separate tests just to verify `allow_parameters`/`permit`. Instead, verify params are used correctly through integration: | |
| ```ruby | |
| # ❌ UNNECESSARY - testing permit directly | |
| test "permits name parameter" do | |
| params = ActionController::Parameters.new(name: "test") | |
| assert controller.send(:allowed_params).permitted? | |
| end | |
| # ✅ GOOD - verify indirectly through actual behavior | |
| test "creates resource with provided name" do | |
| post :create, params: { name: "test" } | |
| assert_equal "test", Resource.last.name | |
| end | |
| ``` | |
| ## Key Principles | |
| 1. **Test behavior, not implementation** - verify the endpoint does what it should | |
| 2. **Pass real params** - let Rails handle parameter filtering naturally | |
| 3. **Assert on outcomes** - check that permitted params affect the result | |
| 4. **Unpermitted params should be ignored** - test that extra params don't cause errors |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Do not push code to GitHub unless explicitly requested | |
| alwaysApply: true | |
| --- | |
| # Git Push Policy | |
| **Never push code to GitHub unless the user explicitly asks you to push.** | |
| ## Allowed Git Operations (without asking) | |
| - `git status` | |
| - `git diff` | |
| - `git log` | |
| - `git add` | |
| - `git commit` | |
| - `git branch` | |
| - `git checkout` | |
| - `git stash` | |
| ## Requires Explicit User Request | |
| - `git push` (any variant) | |
| - `git push origin` | |
| - `git push --force` | |
| - `git push -u origin` | |
| ## Example | |
| ``` | |
| ❌ BAD: Automatically pushing after a commit | |
| "Let me commit and push this change..." | |
| git commit -m "Fix bug" && git push | |
| ✅ GOOD: Commit only, inform user | |
| "I've committed the change. Let me know when you'd like me to push it." | |
| git commit -m "Fix bug" | |
| ``` | |
| When you've made commits that are ready to push, inform the user and wait for their explicit instruction to push. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Ask clarifying questions when starting work on a new Jira ticket | |
| alwaysApply: true | |
| --- | |
| # Jira Ticket Clarification Questions | |
| When the user mentions starting work on a new Jira ticket (e.g., "working on CW-1234", "starting ticket XYZ"), ask clarifying questions before diving into implementation. | |
| ## Acceptance Criteria Questions | |
| - What is the expected behavior when this is complete? | |
| - Are there specific edge cases to handle? | |
| - What should happen in error scenarios? | |
| - Are there any performance requirements? | |
| - What testing approach is expected (unit tests, integration tests, manual testing)? | |
| ## Context Gathering Questions | |
| - Are there related tickets or prior work I should reference? | |
| - Are there existing code patterns in this area I should follow? | |
| - Which components/files are likely affected? | |
| - Are there any dependencies on other teams or services? | |
| - Is this behind a feature flag (Arturo)? | |
| ## When to Ask | |
| Ask these questions when: | |
| - User explicitly mentions a Jira ticket number | |
| - User describes a new feature or bug fix without providing context | |
| - The scope seems ambiguous | |
| ## When to Skip | |
| Skip clarifying questions when: | |
| - User has already provided detailed context | |
| - User says "just do it" or indicates urgency | |
| - It's a follow-up to an existing conversation with established context |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Default formatting guidelines for writing to Logseq via MCP tools | |
| alwaysApply: true | |
| --- | |
| # Logseq MCP Default Formatting | |
| **Always follow these rules when using Logseq MCP tools.** | |
| ## Core Rules | |
| 1. **One item per block** - Each bullet point, sentence, or piece of content must be its own separate block | |
| 2. **Bold for section headers** - Use `**Section Title**` instead of markdown `##` or `###` | |
| 3. **Italics for sub-headers** - Use `*Sub-section*` for secondary headings | |
| 4. **Horizontal rules for separation** - Use `---` blocks between major sections | |
| 5. **No newlines in content** - Never include `\n` in block content strings | |
| ## Formatting Reference | |
| | Element | Use This | NOT This | | |
| |---------|----------|----------| | |
| | Section header | `**Summary**` | `## Summary` | | |
| | Sub-header | `*Details:*` | `### Details` | | |
| | Section separator | `---` | (nothing) | | |
| | Multiple items | Separate blocks | `item1\nitem2` | | |
| ## Standard Page Structure | |
| ``` | |
| Block 1: "**Summary**" | |
| Block 2: "Key point one" | |
| Block 3: "Key point two" | |
| Block 4: "---" | |
| Block 5: "**Next Section**" | |
| Block 6: "Content for this section" | |
| Block 7: "*Sub-header:*" | |
| Block 8: "Sub-content here" | |
| ``` | |
| ## Workflow | |
| 1. Create page with `logseq_create_page` including properties (tags, status, date, etc.) | |
| 2. Add section headers as bold text blocks | |
| 3. Add content items as separate blocks (one per block) | |
| 4. Use `---` blocks to visually separate major sections | |
| 5. Use `is_page_block: true` with page name as `parent_block` | |
| ## Why These Rules | |
| - Logseq shows "full content not displayed" warning for multi-line content | |
| - Markdown `##` headers don't render as headers in Logseq blocks | |
| - Bold text renders correctly and looks good as section headers | |
| - One item per block follows Logseq's outliner philosophy |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Append highlights to personal changelog on every commit | |
| alwaysApply: true | |
| --- | |
| # Personal Changelog | |
| Every time the user asks to commit code, append a summary to `.cursor/CHANGELOG.md` BEFORE creating the commit. | |
| ## Changelog Location | |
| `.cursor/CHANGELOG.md` in the current repo root (gitignored, personal only). | |
| ## Format | |
| Append a new entry at the end of the file (before any trailing whitespace), using this format: | |
| ```markdown | |
| ## YYYY-MM-DD | branch-name | |
| **Commit:** Short commit message here | |
| - Highlight of what changed and why | |
| - Another highlight if multiple things changed | |
| - Reference ticket numbers (e.g., CW-1234) when applicable | |
| --- | |
| ``` | |
| ## Rules | |
| 1. **Always append, never overwrite** existing entries | |
| 2. **Focus on the "why" and impact**, not just file names | |
| 3. **Keep it concise** - 2-5 bullet points per commit | |
| 4. **Include ticket/PR references** when available | |
| 5. **Group related changes** if committing multiple files | |
| 6. Do NOT include the changelog update in the git commit itself (it's gitignored anyway) | |
| 7. Write in first person ("Added...", "Fixed...", "Refactored...") | |
| ## Example | |
| ```markdown | |
| ## 2025-02-05 | drhenner/SLA_policy_confusion_CW-4129 | |
| **Commit:** Bump protobuf clients to 9.1583.0 | |
| - Updated zendesk_protobuf_clients and zendesk_grpc_clients for new SlaPolicyChanged schema | |
| - Required google-protobuf bump from 3.x to 4.x for compatibility | |
| - Supports CW-4129: SLA policy assignment tracking improvements | |
| --- | |
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Add accomplishments to quarterly notes with guided questions | |
| alwaysApply: true | |
| --- | |
| # Quarterly Accomplishments Notes | |
| When the user asks to "add to notes", "log this accomplishment", "record this for quarterly review", or similar: | |
| ## Notes File Location | |
| `/Users/dhenner/Code/drhenner/quarterly_accomplishments/config/notes.yml` | |
| ## Workflow | |
| 1. **Determine category** by asking: | |
| ``` | |
| Which category best fits this accomplishment? | |
| 1. Slack/helping others | |
| 2. Mentoring | |
| 3. Presentation/knowledge sharing | |
| 4. Process improvement | |
| 5. Other (cross-team, incident, hiring, etc.) | |
| ``` | |
| 2. **Ask category-specific follow-ups:** | |
| ### For Slack/Helping Others: | |
| - What channel or context? (e.g., #classic-dev, DM, meeting) | |
| - Who did you help? (person, team, or "multiple engineers") | |
| - What was the impact? (time saved, unblocked work, etc.) | |
| ### For Mentoring: | |
| - Who did you mentor? (new hire, intern, team member) | |
| - What did you help with? (onboarding, code review, architecture) | |
| ### For Presentations: | |
| - What was the title/topic? | |
| - Who was the audience? (team, org, external) | |
| - When was it? (approximate date) | |
| ### For Process Improvements: | |
| - What did you improve? (runbook, tooling, documentation) | |
| - What was the impact? (time saved, errors prevented) | |
| ### For Other: | |
| - What category? (cross-team, incident response, hiring, etc.) | |
| - Brief description of contribution | |
| 3. **Format and add** to the appropriate section in notes.yml | |
| ## Notes Format | |
| ```yaml | |
| slack_highlights: | |
| - channel: "#channel-name" | |
| description: "What you helped with" | |
| impact: "Result/outcome" | |
| mentoring: | |
| - who: "Person or group" | |
| description: "What you did" | |
| presentations: | |
| - title: "Title" | |
| audience: "Who attended" | |
| date: "YYYY-MM-DD" | |
| process_improvements: | |
| - description: "What you improved" | |
| impact: "How it helped" | |
| other: | |
| - category: "Category name" | |
| description: "What you did" | |
| impact: "Optional impact" | |
| ``` | |
| ## Example Interaction | |
| User: "Add to notes - just helped Sarah debug the SLA calculation issue" | |
| Assistant response: | |
| 1. Ask: "Which channel/context was this in?" | |
| 2. Ask: "What was the impact - did it unblock her work?" | |
| 3. Add entry to slack_highlights section |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Security considerations when reviewing code changes and PRs | |
| globs: ["**/*.rb", "**/*.erb", "**/*.js", "**/*.ts"] | |
| --- | |
| # Security Review Checklist | |
| When reviewing code changes or PRs, **always consider these security concerns**: | |
| ## 🔐 Authorization & Access Control | |
| ### Account Scoping (CRITICAL for Multi-tenancy) | |
| Every database query must be scoped to the current account to prevent data leakage between tenants: | |
| ```ruby | |
| # ✅ Good - scoped to account | |
| account.tickets.find(params[:id]) | |
| Ticket.where(account_id: current_account.id).find(params[:id]) | |
| # ❌ Bad - unscoped query can access other accounts' data | |
| Ticket.find(params[:id]) | |
| Ticket.where(id: params[:id]).first | |
| ``` | |
| ### Permission Checks | |
| Verify the user has permission to perform the action: | |
| ```ruby | |
| # ✅ Good - explicit authorization check | |
| def update | |
| @ticket = current_account.tickets.find(params[:id]) | |
| authorize! :update, @ticket # or use access policies | |
| # ... | |
| end | |
| # ❌ Bad - no authorization check | |
| def update | |
| @ticket = Ticket.find(params[:id]) | |
| @ticket.update(ticket_params) | |
| end | |
| ``` | |
| ## 💉 Injection Vulnerabilities | |
| ### SQL Injection | |
| Never interpolate user input directly into SQL: | |
| ```ruby | |
| # ✅ Good - parameterized query | |
| User.where("email = ?", params[:email]) | |
| User.where(email: params[:email]) | |
| # ❌ Bad - SQL injection vulnerability | |
| User.where("email = '#{params[:email]}'") | |
| User.where("email = " + params[:email]) | |
| ``` | |
| ### Command Injection | |
| Never pass user input to shell commands: | |
| ```ruby | |
| # ✅ Good - use arrays to avoid shell interpretation | |
| system("convert", input_file, output_file) | |
| # ❌ Bad - command injection vulnerability | |
| system("convert #{params[:filename]}") | |
| `convert #{params[:filename]}` | |
| ``` | |
| ## 🌐 Cross-Site Scripting (XSS) | |
| ### Output Encoding | |
| All user-controlled data must be escaped in views: | |
| ```erb | |
| <%# ✅ Good - auto-escaped %> | |
| <%= user.name %> | |
| <%# ❌ Bad - raw output, XSS vulnerability %> | |
| <%= raw user.bio %> | |
| <%= user.bio.html_safe %> | |
| <%== user.comment %> | |
| ``` | |
| ### Be Careful With: | |
| - `raw()`, `html_safe`, `<%==` in ERB | |
| - `dangerouslySetInnerHTML` in React | |
| - Rendering user content in JavaScript contexts | |
| ## 🔑 Sensitive Data Handling | |
| ### Don't Log Sensitive Data | |
| ```ruby | |
| # ❌ Bad - logging sensitive information | |
| Rails.logger.info("User login: #{user.email}, password: #{password}") | |
| Rails.logger.info("API key: #{api_key}") | |
| # ✅ Good - filter sensitive params | |
| # Ensure config/initializers/filter_parameter_logging.rb includes sensitive fields | |
| ``` | |
| ### Don't Expose Internal IDs/Data in Errors | |
| ```ruby | |
| # ❌ Bad - exposes internal details | |
| render json: { error: e.message, backtrace: e.backtrace } | |
| # ✅ Good - generic error message | |
| render json: { error: "An error occurred" }, status: :internal_server_error | |
| # Log details internally via Sentry/zendesk_exceptions | |
| ``` | |
| ## 🛡️ Mass Assignment | |
| ### Strong Parameters | |
| Always whitelist permitted attributes: | |
| ```ruby | |
| # ✅ Good - explicit permit | |
| def ticket_params | |
| params.require(:ticket).permit(:subject, :description, :priority) | |
| end | |
| # ❌ Bad - permits everything | |
| params.require(:ticket).permit! | |
| params[:ticket].to_unsafe_h | |
| ``` | |
| ### Watch for Privilege Escalation | |
| ```ruby | |
| # ❌ Dangerous - user could set admin: true | |
| params.require(:user).permit(:name, :email, :admin, :role) | |
| # ✅ Good - sensitive fields handled separately | |
| params.require(:user).permit(:name, :email) | |
| # Admin/role changes require separate authorization | |
| ``` | |
| ## 🔄 CSRF & Request Forgery | |
| ### State-Changing Actions | |
| All state-changing actions should: | |
| - Use POST/PUT/PATCH/DELETE (not GET) | |
| - Verify CSRF tokens (Rails does this by default) | |
| ```ruby | |
| # ❌ Bad - GET request changes state | |
| get '/users/:id/delete' | |
| # ✅ Good - proper HTTP verb | |
| delete '/users/:id' | |
| ``` | |
| ## 🔗 Insecure Direct Object References (IDOR) | |
| ### Always Verify Ownership | |
| ```ruby | |
| # ❌ Bad - IDOR vulnerability | |
| @attachment = Attachment.find(params[:attachment_id]) | |
| # ✅ Good - scoped through association | |
| @attachment = @ticket.attachments.find(params[:attachment_id]) | |
| ``` | |
| ## 📦 Dependency Security | |
| ### When Adding/Updating Gems | |
| - Check for known vulnerabilities: `bundle audit` | |
| - Review gem's security history | |
| - Prefer well-maintained, widely-used gems | |
| ## 🚨 Red Flags to Watch For | |
| | Pattern | Risk | | |
| |---------|------| | |
| | `Ticket.find(params[:id])` | Missing account scope | | |
| | `raw()`, `html_safe` | Potential XSS | | |
| | String interpolation in SQL | SQL injection | | |
| | `permit!` or `to_unsafe_h` | Mass assignment | | |
| | `system()` with string arg | Command injection | | |
| | Logging request params | Sensitive data exposure | | |
| | `skip_before_action :verify_authenticity_token` | CSRF bypass | | |
| | Hardcoded secrets/API keys | Credential exposure | | |
| ## 📋 PR Security Checklist | |
| Before approving any PR, verify: | |
| - [ ] All queries are scoped to account | |
| - [ ] Authorization checks are in place | |
| - [ ] User input is validated and sanitized | |
| - [ ] No raw SQL with string interpolation | |
| - [ ] No `html_safe`/`raw` on user content | |
| - [ ] Strong parameters properly configured | |
| - [ ] Sensitive data not logged or exposed | |
| - [ ] New gems have been security-reviewed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| description: Testing conventions for Zendesk Classic - prefer real objects, use Arturo test helpers | |
| globs: ["test/**/*.rb", "components/**/test/**/*.rb"] | |
| --- | |
| # Testing Conventions | |
| ## Prefer Real Objects Over Stubs/Mocks | |
| When writing tests, **prefer using real objects and fixtures over stubs and mocks**: | |
| ### ✅ Do: Use Real Objects | |
| ```ruby | |
| # Good - use fixtures and real objects | |
| test "user can update ticket" do | |
| account = accounts(:acme) | |
| user = users(:admin) | |
| ticket = tickets(:problem_ticket) | |
| ticket.update!(subject: "New subject") | |
| assert_equal "New subject", ticket.reload.subject | |
| end | |
| # Good - create objects with FactoryBot when needed | |
| test "creates a new ticket" do | |
| account = accounts(:acme) | |
| ticket = create(:ticket, account: account, subject: "Test") | |
| assert ticket.persisted? | |
| end | |
| ``` | |
| ### ❌ Avoid: Excessive Stubbing | |
| ```ruby | |
| # Avoid - stubbing everything makes tests brittle and hides real behavior | |
| test "user can update ticket" do | |
| ticket = stub(id: 1, subject: "Old") | |
| ticket.stubs(:update!).returns(true) | |
| ticket.stubs(:reload).returns(ticket) | |
| ticket.stubs(:subject).returns("New subject") | |
| # This test doesn't actually verify anything real | |
| end | |
| ``` | |
| ### When Stubs ARE Appropriate | |
| - External API calls (use WebMock for HTTP) | |
| - Time-sensitive operations (`travel_to`) | |
| - Expensive operations that are not the focus of the test | |
| - Third-party services | |
| ## Testing Arturo Feature Flags | |
| When testing code behind an Arturo feature flag, **always test both enabled and disabled states** using the helpers from `ArturoTestHelper`. | |
| ### Required Pattern: Test Both States | |
| ```ruby | |
| class MyFeatureTest < ActiveSupport::TestCase | |
| # Test with Arturo DISABLED (old behavior) | |
| describe_with_arturo_disabled :my_feature_flag do | |
| test "behaves the old way when feature is off" do | |
| # Assert old behavior | |
| end | |
| end | |
| # Test with Arturo ENABLED (new behavior) | |
| describe_with_arturo_enabled :my_feature_flag do | |
| test "behaves the new way when feature is on" do | |
| # Assert new behavior | |
| end | |
| end | |
| end | |
| ``` | |
| ### Or Use the Combined Helper | |
| ```ruby | |
| class MyFeatureTest < ActiveSupport::TestCase | |
| # Tests both states automatically | |
| describe_with_and_without_arturo_enabled :my_feature_flag do | |
| test "works correctly" do | |
| if @arturo_enabled | |
| # Assert new behavior | |
| else | |
| # Assert old behavior | |
| end | |
| end | |
| end | |
| end | |
| ``` | |
| ### Available Arturo Test Helpers | |
| #### Option 1: Describe Blocks (Preferred for grouping tests) | |
| | Helper | Use Case | | |
| |--------|----------| | |
| | `describe_with_arturo_enabled :flag` | Test with feature ON | | |
| | `describe_with_arturo_disabled :flag` | Test with feature OFF | | |
| | `describe_with_and_without_arturo_enabled :flag` | Test both states | | |
| | `describe_with_arturo_enabled_for_pod :flag` | Test pod-specific rollout | | |
| | `describe_with_arturos [{arturo: :a, enabled: true}, ...]` | Multiple flags | | |
| #### Option 2: Enable/Disable Within Tests | |
| For more granular control within individual tests, use `Arturo.enable_feature!` and `Arturo.disable_feature!`: | |
| ```ruby | |
| test "behaves differently based on feature flag" do | |
| # Test with feature disabled | |
| Arturo.disable_feature!(:my_feature_flag) | |
| assert_equal "old behavior", subject.do_something | |
| # Test with feature enabled | |
| Arturo.enable_feature!(:my_feature_flag) | |
| assert_equal "new behavior", subject.do_something | |
| end | |
| ``` | |
| You can also scope to specific subdomains or pods: | |
| ```ruby | |
| test "feature enabled for specific subdomain" do | |
| Arturo.enable_feature_for!(:my_feature_flag, subdomains: ['acme'], pods: [1]) | |
| # ... | |
| end | |
| ``` | |
| **Pros of enable/disable approach:** | |
| - More accurate tests, less error prone | |
| - Can be nested | |
| - State automatically resets after test completes | |
| - Works well for testing transitions within a single test | |
| **Con:** Requires database writes | |
| ### ⚠️ Important Warning | |
| The Arturo **must be registered in `app/models/account/capabilities.rb`** before using these test helpers. Failing to do so causes false positives, incidents, and failed deploys. | |
| ```ruby | |
| # In app/models/account/capabilities.rb | |
| feature :my_feature_flag, arturo: !Rails.env.test? # enabled by default in tests | |
| ``` | |
| ### Accessing Arturo State in Tests | |
| Inside `describe_with_arturo_*` blocks, you can check the current state: | |
| ```ruby | |
| describe_with_and_without_arturo_enabled :my_feature do | |
| test "conditional behavior" do | |
| result = some_method_that_checks_arturo | |
| if @arturo_enabled | |
| assert_equal "new result", result | |
| else | |
| assert_equal "old result", result | |
| end | |
| end | |
| end | |
| ``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment