Skip to content

Commit edc74c3

Browse files
authored
Merge branch 'main' into dependabot/bundler/aws-sdk-s3-1.198.0
2 parents 03170ca + bb048f9 commit edc74c3

File tree

224 files changed

+7345
-1719
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

224 files changed

+7345
-1719
lines changed

.github/copilot-instructions.md

Lines changed: 59 additions & 178 deletions
Large diffs are not rendered by default.

.rubocop.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ AllCops:
33
- 'bin/*'
44
- 'node_modules/**/*'
55
- 'spec/dummy/db/schema.rb'
6+
- 'db/schema.rb'
67
- 'vendor/**/*'
78
NewCops: enable
89
TargetRubyVersion: 3.4

AGENTS.md

Lines changed: 108 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,37 @@ Instructions for GitHub Copilot and other automated contributors working in this
1212

1313
## Setup
1414
- Environment runs a setup script that installs Ruby 3.4.4, Node 20, Postgres + PostGIS, and ES7, then prepares databases.
15+
- **Docker Environment**: All commands requiring database access must use `bin/dc-run` to execute within the containerized environment.
16+
- **Dummy App Commands**: Use `bin/dc-run-dummy` for Rails commands that need the dummy app context (e.g., `bin/dc-run-dummy rails console`, `bin/dc-run-dummy rails db:migrate`).
1517
- Databases:
1618
- development: `community_engine_development`
1719
- test: `community_engine_test`
1820
- Use `DATABASE_URL` to connect (overrides fallback host in `config/database.yml`).
1921

2022
## Commands
21-
- **Tests:** `bin/ci`
22-
(Equivalent: `cd spec/dummy && bundle exec rspec`)
23-
- **Lint:** `bundle exec rubocop`
24-
- **Security:** `bundle exec brakeman --quiet --no-pager` and `bundle exec bundler-audit --update`
25-
- **Style:** `bin/codex_style_guard`
26-
- **I18n:** `bin/i18n [normalize|check|health|all]` (runs normalize + missing + interpolation checks by default)
23+
- **Tests:** `bin/dc-run bin/ci`
24+
(Equivalent: `bin/dc-run bash -c "cd spec/dummy && bundle exec rspec"`)
25+
- **Running specific tests:**
26+
- Single spec file: `bin/dc-run bundle exec rspec spec/path/to/file_spec.rb`
27+
- Specific line: `bin/dc-run bundle exec rspec spec/path/to/file_spec.rb:123`
28+
- Multiple files: `bin/dc-run bundle exec rspec spec/file1_spec.rb spec/file2_spec.rb`
29+
- Multiple specific lines: `bin/dc-run bundle exec rspec spec/file1_spec.rb:123 spec/file2_spec.rb:456`
30+
- **Important**: RSpec does NOT support hyphenated line numbers (e.g., `spec/file_spec.rb:123-456` is INVALID)
31+
- **Do NOT use `-v` flag**: The `-v` flag displays RSpec version information, NOT verbose output. Use `--format documentation` for detailed test descriptions.
32+
- **Rails Console:** `bin/dc-run-dummy rails console` (runs console in the dummy app context)
33+
- **Rails Commands in Dummy App:** `bin/dc-run-dummy rails [command]` for any Rails commands that need the dummy app environment
34+
- **Lint:** `bin/dc-run bundle exec rubocop`
35+
- **Security:** `bin/dc-run bundle exec brakeman --quiet --no-pager` and `bin/dc-run bundle exec bundler-audit --update`
36+
- **Style:** `bin/dc-run bin/codex_style_guard`
37+
- **I18n:** `bin/dc-run bin/i18n [normalize|check|health|all]` (runs normalize + missing + interpolation checks by default)
2738
- **Documentation:**
2839
- **Table of Contents**: [`docs/table_of_contents.md`](docs/table_of_contents.md) - Main documentation index
2940
- **Progress tracking**: `docs/scripts/update_progress.sh` - Update system completion status
3041
- **Diagram rendering**: `bin/render_diagrams` - Generate PNG/SVG from Mermaid sources
3142
- **Validation**: `docs/scripts/validate_documentation_tooling.sh` - Validate doc system integrity
3243

3344
## Security Requirements
34-
- **Run Brakeman before generating code**: `bundle exec brakeman --quiet --no-pager`
45+
- **Run Brakeman before generating code**: `bin/dc-run bundle exec brakeman --quiet --no-pager`
3546
- **Fix high-confidence vulnerabilities immediately** - never ignore security warnings with "High" confidence
3647
- **Review and address medium-confidence warnings** that are security-relevant
3748
- **Safe coding practices when generating code:**
@@ -41,11 +52,11 @@ Instructions for GitHub Copilot and other automated contributors working in this
4152
- Use strong parameters in controllers
4253
- Implement proper authorization checks (Pundit policies)
4354
- **For reflection-based features**: Create concerns with `included_in_models` class methods for safe dynamic class resolution
44-
- **Post-generation security check**: Run `bundle exec brakeman --quiet --no-pager -c UnsafeReflection,SQL,CrossSiteScripting` after major code changes
55+
- **Post-generation security check**: Run `bin/dc-run bundle exec brakeman --quiet --no-pager -c UnsafeReflection,SQL,CrossSiteScripting` after major code changes
4556

4657
## Conventions
4758
- Make incremental changes with passing tests.
48-
- **Security first**: Run `bundle exec brakeman --quiet --no-pager` before committing code changes.
59+
- **Security first**: Run `bin/dc-run bundle exec brakeman --quiet --no-pager` before committing code changes.
4960
- **Test every change**: Generate RSpec tests for all code modifications, including models, controllers, mailers, jobs, and JavaScript.
5061
- **Test coverage requirements**: All new features, bug fixes, and refactors must include comprehensive test coverage.
5162
- Avoid introducing new external services in tests; stub where possible.
@@ -150,14 +161,14 @@ We use the `i18n-tasks` gem to ensure all translation keys are present, normaliz
150161

151162
## Example Commands
152163
```bash
153-
i18n-tasks normalize
154-
i18n-tasks missing
155-
i18n-tasks add-missing
156-
i18n-tasks health
164+
bin/dc-run i18n-tasks normalize
165+
bin/dc-run i18n-tasks missing
166+
bin/dc-run i18n-tasks add-missing
167+
bin/dc-run i18n-tasks health
157168
```
158169

159170
## CI Note
160-
- The i18n GitHub Action installs dev/test gem groups to make `i18n-tasks` available. Locally, you can mirror CI with `bin/i18n`, which sets `BUNDLE_WITH=development:test` automatically.
171+
- The i18n GitHub Action installs dev/test gem groups to make `i18n-tasks` available. Locally, you can mirror CI with `bin/dc-run bin/i18n`, which sets `BUNDLE_WITH=development:test` automatically.
161172

162173
See `.github/instructions/i18n-mobility.instructions.md` for additional translation rules.
163174

@@ -199,6 +210,22 @@ For every implementation plan, create acceptance criteria covering relevant stak
199210
- **Test all layers**: models (validations, associations, methods), controllers (actions, authorization), services, mailers, jobs, and view components.
200211
- **JavaScript/Stimulus testing**: Include feature specs that exercise dynamic behaviors like form interactions and AJAX updates.
201212

213+
## Test Environment Requirements
214+
- **Host Platform Configuration**: All controller, request, and feature tests MUST configure the host platform/community before testing.
215+
- **Use `configure_host_platform`**: Call this helper method in a `before` block for any test that makes HTTP requests or tests authentication/authorization.
216+
- **DeviseSessionHelpers**: Include this module and use authentication helpers like `login('[email protected]', 'password')` for authenticated tests.
217+
- **Platform Setup Pattern**:
218+
```ruby
219+
RSpec.describe BetterTogether::SomeController do
220+
before do
221+
configure_host_platform # Creates host platform with community
222+
login('[email protected]', 'password') # For authenticated tests
223+
end
224+
end
225+
```
226+
- **Required for**: Controller specs, request specs, feature specs, and any integration tests that involve routing or authentication.
227+
- **Locale Parameters**: Engine controller tests require locale parameters (e.g., `params: { locale: I18n.default_locale }`) due to routing constraints.
228+
202229
## Test Coverage Standards
203230
- **Models**: Test validations, associations, scopes, instance methods, class methods, and callbacks.
204231
- **Controllers**: Test all actions, authorization policies, parameter handling, and response formats.
@@ -309,3 +336,70 @@ Each major system must include:
309336
- Security implications and access controls
310337
- API endpoints with request/response examples
311338
- Monitoring tools and troubleshooting procedures
339+
340+
## Testing Architecture Consistency Lessons Learned
341+
342+
### Critical Testing Pattern: Request Specs vs Controller Specs
343+
- **Project Standard**: All tests use request specs (`type: :request`) for consistency with Rails engine routing
344+
- **Exception Handling**: Controller specs (`type: :controller`) require special URL helper configuration in Rails engines
345+
- **Why This Matters**: Request specs handle Rails engine routing automatically through the full HTTP stack, while controller specs test in isolation and need explicit configuration
346+
- **Debugging Indicator**: If you see `default_url_options` errors only in one spec while others pass, check if it's a controller spec in a request spec codebase
347+
348+
### Rails Engine URL Helper Configuration
349+
- **Problem**: Controller specs in Rails engines throw `default_url_options` errors that request specs don't encounter
350+
- **Root Cause**: Engines need special URL helper setup for controller specs but not request specs
351+
- **Solution Patterns**:
352+
```ruby
353+
# For controller spec assertions, use pattern matching instead of path helpers:
354+
expect(response.location).to include('/person_blocks') # Good
355+
expect(response).to redirect_to(person_blocks_path) # Problematic in controller specs
356+
357+
# Ensure consistent route naming throughout:
358+
# Controller: person_blocks_path (not blocks_path)
359+
# Views: <%= link_to "Block", better_together.person_blocks_path %>
360+
# Tests: params path should match controller actions
361+
```
362+
363+
### Route Naming Convention Enforcement
364+
- **Pattern**: Engine routes follow full resource naming: `better_together.resource_name_path`
365+
- **Common Error**: Using shortened path names (`blocks_path`) instead of full names (`person_blocks_path`)
366+
- **Consistency Check**: Views, controllers, and tests must all use the same complete path helper names
367+
- **Verification**: Check all three layers when debugging routing issues
368+
369+
### Factory and Association Dependencies
370+
- **Requirement**: Every Better Together model needs a corresponding FactoryBot factory
371+
- **Naming Convention**: Factory names follow `better_together_model_name` pattern with aliases
372+
- **Association Setup**: Factories must properly handle engine namespace associations
373+
- **Missing Factory Indicator**: Tests failing on association creation often indicate missing factories
374+
375+
### Test Environment Configuration Enforcement
376+
- **Critical Setup**: `configure_host_platform` must be called before any controller/request/feature tests
377+
- **Why Required**: Better Together engine needs host platform setup for authentication and authorization
378+
- **Pattern Recognition**: Tests failing with authentication/authorization errors often need this setup
379+
- **Documentation Reference**: This pattern is well-documented but bears reinforcement
380+
381+
### Architecture Consistency Principles
382+
- **Consistency Is Key**: When one component (PersonBlocksController) differs from project patterns, it requires special handling
383+
- **Pattern Detection**: Single anomalies (one controller spec among many request specs) signal architectural inconsistencies
384+
- **Prevention**: New tests should follow the established pattern (request specs) unless there's a compelling reason for exceptions
385+
- **Documentation**: When exceptions are necessary, document why they exist and how to handle their special requirements
386+
387+
### Testing Strategy Recommendations
388+
- **Default Choice**: Use request specs for new controller tests to maintain consistency
389+
- **Engine Compatibility**: Request specs handle Rails engine complexity automatically
390+
- **Special Cases**: If controller specs are needed, prepare for URL helper configuration complexity
391+
- **Debugging Approach**: When testing errors occur in only one spec, compare its type and setup to working specs
392+
393+
## Docker Environment Usage
394+
- **All database-dependent commands must use `bin/dc-run`**: This includes tests, generators, and any command that connects to PostgreSQL, Redis, or Elasticsearch
395+
- **Dummy app commands use `bin/dc-run-dummy`**: For Rails commands that need the dummy app context (console, migrations specific to dummy app)
396+
- **Examples of commands requiring `bin/dc-run`**:
397+
- Tests: `bin/dc-run bundle exec rspec`
398+
- Generators: `bin/dc-run rails generate model User`
399+
- Brakeman: `bin/dc-run bundle exec brakeman`
400+
- RuboCop: `bin/dc-run bundle exec rubocop`
401+
- **Examples of commands requiring `bin/dc-run-dummy`**:
402+
- Rails console: `bin/dc-run-dummy rails console`
403+
- Dummy app migrations: `bin/dc-run-dummy rails db:migrate`
404+
- Dummy app database operations: `bin/dc-run-dummy rails db:seed`
405+
- **Commands that don't require bin/dc-run**: File operations, documentation generation (unless database access needed), static analysis tools that don't connect to services

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ group :test do
105105
gem 'database_cleaner-active_record'
106106
# # Easy installation and use of chromedriver to run system tests with Chrome
107107
# gem 'webdrivers'
108+
# Rails controller testing for assigns method
109+
gem 'rails-controller-testing'
108110
# RuboCop RSpec for RSpec-specific code analysis
109111
gem 'rubocop-capybara'
110112
gem 'rubocop-factory_bot'

Gemfile.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,10 @@ GEM
562562
activesupport (= 7.1.5.2)
563563
bundler (>= 1.15.0)
564564
railties (= 7.1.5.2)
565+
rails-controller-testing (1.0.5)
566+
actionpack (>= 5.0.1.rc1)
567+
actionview (>= 5.0.1.rc1)
568+
activesupport (>= 5.0.1.rc1)
565569
rails-dom-testing (2.3.0)
566570
activesupport (>= 5.0.0)
567571
minitest
@@ -848,6 +852,7 @@ DEPENDENCIES
848852
rack-mini-profiler
849853
rack-protection
850854
rails (= 7.1.5.2)
855+
rails-controller-testing
851856
rb-readline
852857
rbtrace
853858
redis (~> 5.4)

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,12 @@ Run the RSpec tests:
117117
```bash
118118
bin/dc-run app rspec
119119
```
120+
121+
## Contributing
122+
123+
We welcome contributions from the community.
124+
125+
- Guidelines: See [CONTRIBUTING.md](CONTRIBUTING.md) for how to report issues, propose changes, and submit pull requests.
126+
- Code of Conduct: See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for expectations of behavior in our community.
127+
128+
Thank you for helping make Better Together better for everyone.

app/assets/stylesheets/better_together/forms.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
font-weight: bold;
66
}
77

8+
.ss-content .ss-search input {
9+
color: $light-background-text-color;
10+
}
11+
812
.form-label {
913
font-weight: 500;
1014
}

app/builders/better_together/access_control_builder.rb

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,44 @@ def seed_data
1616
end
1717

1818
def build_community_roles
19-
::BetterTogether::Role.create!(community_role_attrs)
19+
community_role_attrs.each do |attrs|
20+
# Idempotent: find by unique identifier and update attributes if needed
21+
role = ::BetterTogether::Role.find_or_initialize_by(identifier: attrs[:identifier])
22+
role.assign_attributes(attrs)
23+
role.save! if role.changed?
24+
end
2025
end
2126

2227
def build_community_resource_permissions
23-
::BetterTogether::ResourcePermission.create!(community_resource_permission_attrs)
28+
community_resource_permission_attrs.each do |attrs|
29+
perm = ::BetterTogether::ResourcePermission.find_or_initialize_by(identifier: attrs[:identifier])
30+
perm.assign_attributes(attrs)
31+
perm.save! if perm.changed?
32+
end
2433
end
2534

2635
def build_platform_resource_permissions
27-
::BetterTogether::ResourcePermission.create!(platform_resource_permission_attrs)
36+
platform_resource_permission_attrs.each do |attrs|
37+
perm = ::BetterTogether::ResourcePermission.find_or_initialize_by(identifier: attrs[:identifier])
38+
perm.assign_attributes(attrs)
39+
perm.save! if perm.changed?
40+
end
2841
end
2942

3043
def build_platform_roles
31-
::BetterTogether::Role.create!(platform_role_attrs)
44+
platform_role_attrs.each do |attrs|
45+
role = ::BetterTogether::Role.find_or_initialize_by(identifier: attrs[:identifier])
46+
role.assign_attributes(attrs)
47+
role.save! if role.changed?
48+
end
3249
end
3350

3451
def build_person_resource_permissions
35-
::BetterTogether::ResourcePermission.create!(person_resource_permission_attrs)
52+
person_resource_permission_attrs.each do |attrs|
53+
perm = ::BetterTogether::ResourcePermission.find_or_initialize_by(identifier: attrs[:identifier])
54+
perm.assign_attributes(attrs)
55+
perm.save! if perm.changed?
56+
end
3657
end
3758

3859
# Clear existing data - Use with caution!

app/builders/better_together/agreement_builder.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ def build_privacy_policy # rubocop:todo Metrics/MethodLength, Metrics/AbcSize
3535

3636
# If a Page exists for the privacy policy, link it so the page content
3737
# is shown to users instead of the agreement terms.
38-
page = BetterTogether::Page.find_by(identifier: 'privacy_policy') ||
39-
BetterTogether::Page.friendly.find('privacy-policy')
38+
page = BetterTogether::Page.find_by(identifier: 'privacy_policy')
4039
agreement.update!(page: page) if page.present?
4140
end
4241
# rubocop:enable Metrics/AbcSize
@@ -57,8 +56,7 @@ def build_terms_of_service # rubocop:todo Metrics/MethodLength, Metrics/AbcSize
5756
end
5857

5958
# Link a Terms of Service Page if one exists
60-
page = BetterTogether::Page.find_by(identifier: 'terms_of_service') ||
61-
BetterTogether::Page.friendly.find('terms-of-service')
59+
page = BetterTogether::Page.find_by(identifier: 'terms_of_service')
6260
agreement.update!(page: page) if page.present?
6361
end
6462
# rubocop:enable Metrics/AbcSize
@@ -79,8 +77,7 @@ def build_code_of_conduct # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
7977
end
8078

8179
# Link a Code of Conduct Page if one exists
82-
page = BetterTogether::Page.find_by(identifier: 'code_of_conduct') ||
83-
BetterTogether::Page.friendly.find('code-of-conduct')
80+
page = BetterTogether::Page.find_by(identifier: 'code_of_conduct')
8481
agreement.update!(page: page) if page.present?
8582
end
8683
# rubocop:enable Metrics/MethodLength

app/builders/better_together/navigation_builder.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,9 @@ def delete_navigation_areas
352352
end
353353

354354
def delete_navigation_items
355-
::BetterTogether::NavigationItem.delete_all
355+
# Delete children first to satisfy FK constraints, then parents
356+
::BetterTogether::NavigationItem.where.not(parent_id: nil).delete_all
357+
::BetterTogether::NavigationItem.where(parent_id: nil).delete_all
356358
end
357359
end
358360
end

0 commit comments

Comments
 (0)