From 032b71d3b6662e9b026e425c77def311425b7112 Mon Sep 17 00:00:00 2001
From: Jerome Dalbert <jerome.dalbert@gmail.com>
Date: Sun, 10 Nov 2024 16:08:59 -0800
Subject: [PATCH] Add Rails 8 authentication generator

---
 .../authentication_generator.rb               | 25 ++++++++++++++
 .../authentication/templates/user_spec.rb     |  5 +++
 .../rspec/authentication/templates/users.yml  | 11 ++++++
 .../authentication_generator_spec.rb          | 34 +++++++++++++++++++
 4 files changed, 75 insertions(+)
 create mode 100644 lib/generators/rspec/authentication/authentication_generator.rb
 create mode 100644 lib/generators/rspec/authentication/templates/user_spec.rb
 create mode 100644 lib/generators/rspec/authentication/templates/users.yml
 create mode 100644 spec/generators/rspec/authentication/authentication_generator_spec.rb

diff --git a/lib/generators/rspec/authentication/authentication_generator.rb b/lib/generators/rspec/authentication/authentication_generator.rb
new file mode 100644
index 000000000..f653c5c4e
--- /dev/null
+++ b/lib/generators/rspec/authentication/authentication_generator.rb
@@ -0,0 +1,25 @@
+require 'generators/rspec'
+
+module Rspec
+  module Generators
+    # @private
+    class AuthenticationGenerator < Base
+      def initialize(args, *options)
+        args.replace(['User'])
+        super
+      end
+
+      def create_user_spec
+        template 'user_spec.rb', target_path('models', 'user_spec.rb')
+      end
+
+      hook_for :fixture_replacement
+
+      def create_fixture_file
+        return if options[:fixture_replacement]
+
+        template 'users.yml', target_path('fixtures', 'users.yml')
+      end
+    end
+  end
+end
diff --git a/lib/generators/rspec/authentication/templates/user_spec.rb b/lib/generators/rspec/authentication/templates/user_spec.rb
new file mode 100644
index 000000000..4dfb2b069
--- /dev/null
+++ b/lib/generators/rspec/authentication/templates/user_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe User, <%= type_metatag(:model) %> do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/lib/generators/rspec/authentication/templates/users.yml b/lib/generators/rspec/authentication/templates/users.yml
new file mode 100644
index 000000000..d2eae44a2
--- /dev/null
+++ b/lib/generators/rspec/authentication/templates/users.yml
@@ -0,0 +1,11 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+<%% password_digest = BCrypt::Password.create("password") %>
+
+one:
+  email_address: one@example.com
+  password_digest: <%%= password_digest %>
+
+two:
+  email_address: two@example.com
+  password_digest: <%%= password_digest %>
diff --git a/spec/generators/rspec/authentication/authentication_generator_spec.rb b/spec/generators/rspec/authentication/authentication_generator_spec.rb
new file mode 100644
index 000000000..e5590aedd
--- /dev/null
+++ b/spec/generators/rspec/authentication/authentication_generator_spec.rb
@@ -0,0 +1,34 @@
+# Generators are not automatically loaded by Rails
+require 'generators/rspec/authentication/authentication_generator'
+require 'support/generators'
+
+RSpec.describe Rspec::Generators::AuthenticationGenerator, type: :generator do
+  setup_default_destination
+
+  it 'runs both the model and fixture tasks' do
+    gen = generator
+    expect(gen).to receive :create_user_spec
+    expect(gen).to receive :create_fixture_file
+    gen.invoke_all
+  end
+
+  describe 'the generated files' do
+    it 'creates the user spec' do
+      run_generator
+
+      expect(File.exist?(file('spec/models/user_spec.rb'))).to be true
+    end
+
+    describe 'with fixture replacement' do
+      before do
+        run_generator ['--fixture-replacement=factory_bot']
+      end
+
+      describe 'the fixtures' do
+        it "will skip the file" do
+          expect(File.exist?(file('spec/fixtures/users.yml'))).to be false
+        end
+      end
+    end
+  end
+end