From 4e7217b88186ca5550d7e89557027f854912034d Mon Sep 17 00:00:00 2001 From: Federico Date: Tue, 1 Oct 2024 18:03:10 -0300 Subject: [PATCH] Add CI and rspec matrix --- .github/workflows/ci.yml | 52 ++++++ lib/sea_food/service.rb | 3 +- spec/gemfiles/6_1.gemfile | 3 + spec/gemfiles/7_0.gemfile | 4 + spec/gemfiles/7_1.gemfile | 4 + spec/gemfiles/7_2.gemfile | 4 + spec/sea_food/service/service_spec.rb | 231 ++++++++++++++------------ 7 files changed, 195 insertions(+), 106 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 spec/gemfiles/6_1.gemfile create mode 100644 spec/gemfiles/7_0.gemfile create mode 100644 spec/gemfiles/7_1.gemfile create mode 100644 spec/gemfiles/7_2.gemfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..afb4530 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,52 @@ +name: Test Matrix + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + matrix: + gemfile: [5_2.gemfile, 6_1.gemfile, 7_0.gemfile, 7_1.gemfile, 7_2.gemfile] + ruby-version: [ '2.7', '3.0', '3.1', '3.3'] + exclude: + - ruby-version: '2.7' + gemfile: '7_0.gemfile' + - ruby-version: '2.7' + gemfile: '7_1.gemfile' + - ruby-version: '2.7' + gemfile: '7_2.gemfile' + - ruby-version: '3.0' + gemfile: '5_2.gemfile' + - ruby-version: '3.1' + gemfile: '5_2.gemfile' + - ruby-version: '3.3' + gemfile: '5_2.gemfile' + + env: + BUNDLE_GEMFILE: spec/gemfiles/${{ matrix.gemfile }} + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Ruby ${{ matrix.ruby-version }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true + + - name: Install dependencies + run: | + gem install bundler + bundle install + + - name: Run tests + run: | + bundle exec rspec \ No newline at end of file diff --git a/lib/sea_food/service.rb b/lib/sea_food/service.rb index 8b2033e..d2b22c5 100644 --- a/lib/sea_food/service.rb +++ b/lib/sea_food/service.rb @@ -21,7 +21,8 @@ class << self # @param args [Hash] Arguments to pass to the service. # @return [ServiceResult] The result of the service call. def call(params = {}) - service = new(params) + # debugger + service = new(**params) service.call service.result || ServiceResult.new rescue ServiceError => e diff --git a/spec/gemfiles/6_1.gemfile b/spec/gemfiles/6_1.gemfile new file mode 100644 index 0000000..10e091f --- /dev/null +++ b/spec/gemfiles/6_1.gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' +gemspec path: '../..' +gem 'rails', '~> 6.1' diff --git a/spec/gemfiles/7_0.gemfile b/spec/gemfiles/7_0.gemfile new file mode 100644 index 0000000..50ec11d --- /dev/null +++ b/spec/gemfiles/7_0.gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' +gemspec path: '../..' +gem 'rails', '~> 7.0' +gem 'sqlite3', '~> 1.5.0' diff --git a/spec/gemfiles/7_1.gemfile b/spec/gemfiles/7_1.gemfile new file mode 100644 index 0000000..50734a7 --- /dev/null +++ b/spec/gemfiles/7_1.gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' +gemspec path: '../..' +gem 'rails', '~> 7.1' +gem 'sqlite3', '~> 1.5.0' diff --git a/spec/gemfiles/7_2.gemfile b/spec/gemfiles/7_2.gemfile new file mode 100644 index 0000000..7693975 --- /dev/null +++ b/spec/gemfiles/7_2.gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' +gemspec path: '../..' +gem 'rails', '~> 7.2' +gem 'sqlite3', '~> 1.5.0' diff --git a/spec/sea_food/service/service_spec.rb b/spec/sea_food/service/service_spec.rb index dd8fb4f..44b881c 100644 --- a/spec/sea_food/service/service_spec.rb +++ b/spec/sea_food/service/service_spec.rb @@ -70,156 +70,177 @@ def call # Test enforcing the interface of the service ###### - it '.call - fails on missing arguments' do - TestFailOnMissingArgsService = Class.new(SeaFood::Service) do - def initialize(email:) - @email = email + context "when the configuration is set to enforce the interface" do + before do + SeaFood.configure do |config| + config.enforce_interface = true end + end - def call - success(email: email) + it 'rasies an error when the #initialize method is not implemented' do + TestService = Class.new(SeaFood::Service) do + def call + end end - end - expect { TestFailOnMissingArgsService.call }.to raise_error( - ArgumentError - ).with_message('missing keyword: :email') - end + expect { TestService.call }.to raise_error( + NotImplementedError + ).with_message( + 'Subclasses must implement the initialize '\ + 'method because `enforce_interface` is set to true' + ) + end - it '.call - success with arguments' do - TestSuccessWithArgsService = Class.new(SeaFood::Service) do - def initialize(email:) - @email = email + it 'does not rasies an error when the #initialize method is implemented' do + TestService = Class.new(SeaFood::Service) do + def initialize; end + def call; end end - def call - success(email: @email) - end + expect { TestService.call }.not_to raise_error( + NotImplementedError + ) end - result = TestSuccessWithArgsService.call(email: 'fede@example.com') - expect(result).to be_success - expect(result.email).to eq('fede@example.com') - end + it '.call - fails on missing arguments' do + TestFailOnMissingArgsService = Class.new(SeaFood::Service) do + def initialize(email:) + @email = email + end - it '.call - success default with arguments ' do - TestSuccessWithArgsService = Class.new(SeaFood::Service) do - def initialize(email:) - @email = email + def call + success(email: email) + end end - def call; end + expect { TestFailOnMissingArgsService.call }.to raise_error( + ArgumentError + ).with_message('missing keyword: :email') end - result = TestSuccessWithArgsService.call(email: 'fede@example.com') - expect(result).to be_success - expect(result.email).to be_nil - end - - ###### - # Test the difference behavior of #success #fail #fail! - ###### + it '.call - success with arguments' do + TestSuccessWithArgsService = Class.new(SeaFood::Service) do + def initialize(email:) + @email = email + end - it 'call #success twice' do - TestSuccessService = Class.new(SeaFood::Service) do - def call - success(email: 'hi@example.com') - success(email: params[:email]) + def call + success(email: @email) + end end - end - result = TestSuccessService.call(email: 'service@example.com') + result = TestSuccessWithArgsService.call(email: 'fede@example.com') + expect(result).to be_success + expect(result.email).to eq('fede@example.com') + end - expect(result).to be_success - expect(result.email).to eq('service@example.com') - end + it '.call - success default with arguments ' do + TestSuccessWithArgsService = Class.new(SeaFood::Service) do + def initialize(email:) + @email = email + end - it 'call #fail twice' do - TestFailService = Class.new(SeaFood::Service) do - def call - fail(email: 'hi@example.com') - fail(email: params[:email]) + def call; end end + + result = TestSuccessWithArgsService.call(email: 'fede@example.com') + expect(result).to be_success + expect(result.email).to be_nil end - result = TestFailService.call(email: 'service@example.com') + ###### + # Test the difference behavior of #success #fail #fail! + ###### - expect(result).to be_fail - expect(result.email).to eq('service@example.com') - end + it 'call #success twice' do + TestSuccessService = Class.new(SeaFood::Service) do + def initialize(email:) + @email = email + end - it 'call #fail! twice' do - TestFailService = Class.new(SeaFood::Service) do - def call - fail!(email: 'hi@example.com') - fail!(email: params[:email]) + def call + success(email: 'hi@example.com') + success(email: @email) + end end - end - result = TestFailService.call(email: 'service@example.com') - - expect(result).to be_fail - expect(result.email).to eq('hi@example.com') - end + result = TestSuccessService.call(email: 'service@example.com') - it '#fail then #success' do - TestFailService = Class.new(SeaFood::Service) do - def call - fail(email: 'hi@example.com') - success(email: params[:email]) - end + expect(result).to be_success + expect(result.email).to eq('service@example.com') end - result = TestFailService.call(email: 'service@example.com') - - expect(result).to be_success - expect(result.email).to eq('service@example.com') - end + it 'call #fail twice' do + TestFailService = Class.new(SeaFood::Service) do + def initialize(email:) + @email = email + end - it '#fail! then #success!' do - TestFailService = Class.new(SeaFood::Service) do - def call - fail!(email: 'hi@example.com') - success!(email: params[:email]) + def call + fail(email: 'hi@example.com') + fail(email: @email) + end end - end - result = TestFailService.call(email: 'service@example.com') + result = TestFailService.call(email: 'service@example.com') - expect(result).to be_fail - expect(result.email).to eq('hi@example.com') - end + expect(result).to be_fail + expect(result.email).to eq('service@example.com') + end - context "when the configuration is set to enforce the interface" do - before do - SeaFood.configure do |config| - config.enforce_interface = true + it 'call #fail! twice' do + TestFailService = Class.new(SeaFood::Service) do + def initialize(email:) + @email = email + end + + def call + fail!(email: 'hi@example.com') + fail!(email: @email) + end end + + result = TestFailService.call(email: 'service@example.com') + + expect(result).to be_fail + expect(result.email).to eq('hi@example.com') end - it 'rasies an error when the #initialize method is not implemented' do - TestService = Class.new(SeaFood::Service) do + it '#fail then #success' do + TestFailService = Class.new(SeaFood::Service) do + + def initialize(email:) + @email = email + end + def call + fail(email: 'hi@example.com') + success(email: @email) end end - expect { TestService.call }.to raise_error( - NotImplementedError - ).with_message( - 'Subclasses must implement the initialize '\ - 'method because `enforce_interface` is set to true' - ) + result = TestFailService.call(email: 'service@example.com') + + expect(result).to be_success + expect(result.email).to eq('service@example.com') end - it ' does not rasies an error when the #initialize method is implemented' do - TestService = Class.new(SeaFood::Service) do - def initialize; end - def call; end + it '#fail! then #success!' do + TestFailService = Class.new(SeaFood::Service) do + def initialize(email:) + @email = email + end + + def call + fail!(email: 'hi@example.com') + success!(email: @email) + end end - expect { TestService.call }.not_to raise_error( - NotImplementedError - ) + result = TestFailService.call(email: 'service@example.com') + + expect(result).to be_fail + expect(result.email).to eq('hi@example.com') end end end