Skip to content

Add request specs generation to authentication generator #2863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

DiegoPisa2003
Copy link

Rails' built-in authentication generator (TestUnit) generates four test files when creating authentication scaffolding. However, the RSpec equivalent was only generating two of these tests - the model spec and fixtures. This PR adds the missing request specs for sessions and passwords functionality, bringing feature parity between TestUnit and RSpec authentication generators.

What's Changed

  • Generator Enhancements:

    • Added --request-specs option (defaults to true) to control request spec generation
    • Added create_session_request_spec method to generate session authentication tests
    • Added create_password_request_spec method to generate password reset tests
  • New Test Templates:

    • session_spec.rb - Tests for user login, logout, and session management
    • password_spec.rb - Tests for password reset flow including email sending and token validation
  • Test Coverage:

    • Added comprehensive test coverage for the new functionality
    • Tests verify files are created by default
    • Tests verify --request-specs=false option works correctly
    • Tests ensure compatibility with fixture replacement options

References

Based on Rails' TestUnit authentication generator

method

- Add create_session_request_spec method to generate
sessions_spec.rb
- Include basic test structure for login/logout endpoints
- Respects request_specs option for conditional generation"
method

- Add create_password_request_spec method to generate
passwords_spec.rb
- Include basic test structure for password reset endpoints
- Respects request_specs option for conditional generation"
After creating a dummy app with only rspec and authentication, I added both test, and they pass without any additional configuration
Copy link
Member

@JonRowe JonRowe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great start, I'd love to see this land, just a couple of points to address


private

def sign_in_as(user)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given Rails's own preference for helpers, I feel this should be generated in a module thats included or configured for automatic inclusion.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right, it is cleaner and it is closer to the Rails way. What do you think about adding this two methods to the authentication_generator:

create_authentication_support:
Creates the spec/support/authentication_support.rb file with the sign_in_as(user) helper

configure_authentication_support:
Automatically modifies spec/rails_helper.rb to include the helper in all request specs

Comment on lines 50 to 55
Current.session = user.sessions.create!

ActionDispatch::TestRequest.create.cookie_jar.tap do |cookie_jar|
cookie_jar.signed[:session_id] = Current.session.id
cookies[:session_id] = cookie_jar[:session_id]
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also prefer if this did a simple post rather than reaching into internals, seems like it could be brittle?

Comment on lines 4 to 6
fixtures :users

let(:user) { users(:one) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See below

Comment on lines 4 to 6
fixtures :users

let(:user) { users(:one) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although we do generate fixtures when thats enabled, we don't use them anywhere else, I feel like this should be gated on fixtures being turned on but I'm not sure what the alternative should be?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could remove fixture usage and use direct model creation like the scaffold generator lib/generators/rspec/scaffold/templates/request_spec.rb:

# TODO: Replace with your factory or model creation method
# For example, with FactoryBot: let(:user) { create(:user) }
# or with fixtures: let(:user) { users(:one) }
let(:user) { User.create!(email_address: "test@example.com", password: "password") }

This option is completely agnostic to fixtures vs factory replacements

- Create AuthenticationSupport module with sign_in_as helper method
- Extract sign_in_as from session_spec to shared support module
- Auto-configure rails_helper to include AuthenticationSupport for request specs
- Add generator methods to create and configure authentication support
- Update generator specs to test new authentication support functionality
Replace fixture usage with direct model creation to ensure compatibility
with both fixtures and fixture replacements
@DiegoPisa2003 DiegoPisa2003 requested a review from JonRowe August 20, 2025 12:33
Comment on lines 48 to 50
expect(file('spec/rails_helper.rb')).not_to contain(
" # Rails.root.glob('spec/support/**/*.rb').sort_by(&:to_s).each { |f| require f }\n"
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being pedantic, this only asserts the line was removed, I think prehaps match on the line without the #

Suggested change
expect(file('spec/rails_helper.rb')).not_to contain(
" # Rails.root.glob('spec/support/**/*.rb').sort_by(&:to_s).each { |f| require f }\n"
)
expect(file('spec/rails_helper.rb')).to contain(
/^#{Regexp.escape("Rails.root.glob('spec/support/**/*.rb').sort_by(&:to_s).each { |f| require f }"}$/
)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah you are right, thanks. I will apply your suggestion

Change test from checking commented line removal to verifying
uncommented support glob line is present in rails_helper.rb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants