diff --git a/alchemy-solidus.gemspec b/alchemy-solidus.gemspec index fd16b74..8c16fa2 100644 --- a/alchemy-solidus.gemspec +++ b/alchemy-solidus.gemspec @@ -20,6 +20,7 @@ Gem::Specification.new do |gem| gem.add_dependency('deface', ['~> 1.0']) gem.add_development_dependency('rspec-rails', ['~> 3.7']) + gem.add_development_dependency('shoulda-matchers', ['~> 4.0']) gem.add_development_dependency('capybara', ['~> 2.15']) gem.add_development_dependency('capybara-screenshot', ['~> 1.0']) gem.add_development_dependency('factory_bot', ['~> 4.8']) diff --git a/app/models/alchemy/essence_spree_variant.rb b/app/models/alchemy/essence_spree_variant.rb new file mode 100644 index 0000000..44c3d6f --- /dev/null +++ b/app/models/alchemy/essence_spree_variant.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Alchemy + class EssenceSpreeVariant < ActiveRecord::Base + VARIANT_ID = /\A\d+\z/ + + belongs_to :variant, class_name: 'Spree::Variant', optional: true + + acts_as_essence( + ingredient_column: :variant, + preview_text_method: :name + ) + + def ingredient=(variant) + case variant + when VARIANT_ID + self.variant = Spree::Variant.new(id: variant) + when Spree::Variant + self.variant = variant + else + super + end + end + end +end diff --git a/app/views/alchemy/essences/_essence_spree_variant_editor.html.erb b/app/views/alchemy/essences/_essence_spree_variant_editor.html.erb new file mode 100644 index 0000000..cda6dc0 --- /dev/null +++ b/app/views/alchemy/essences/_essence_spree_variant_editor.html.erb @@ -0,0 +1,9 @@ +
+ <%= content_label(content) %> + <%= select_tag( + content.form_field_name, + options_from_collection_for_select(Spree::Variant.all, :id, :name, content.essence.variant_id), + id: content.form_field_id, + class: 'alchemy_selectbox full_width' + ) %> +
diff --git a/app/views/alchemy/essences/_essence_spree_variant_view.html.erb b/app/views/alchemy/essences/_essence_spree_variant_view.html.erb new file mode 100644 index 0000000..e69de29 diff --git a/bin/rails b/bin/rails index 1981c1d..9050151 100755 --- a/bin/rails +++ b/bin/rails @@ -9,6 +9,6 @@ APP_PATH = File.expand_path('../../spec/dummy/config/application', __FILE__) # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) - require 'rails/all' +require 'rspec-rails' require 'rails/engine/commands' diff --git a/db/migrate/20191107135822_create_alchemy_essence_spree_variants.rb b/db/migrate/20191107135822_create_alchemy_essence_spree_variants.rb new file mode 100644 index 0000000..afab341 --- /dev/null +++ b/db/migrate/20191107135822_create_alchemy_essence_spree_variants.rb @@ -0,0 +1,9 @@ +class CreateAlchemyEssenceSpreeVariants < ActiveRecord::Migration[5.2] + def change + create_table :alchemy_essence_spree_variants do |t| + t.references :variant, null: true, foreign_key: { to_table: Spree::Variant.table_name } + + t.timestamps + end + end +end diff --git a/spec/models/alchemy/essence_spree_variant_spec.rb b/spec/models/alchemy/essence_spree_variant_spec.rb new file mode 100644 index 0000000..6fc05d7 --- /dev/null +++ b/spec/models/alchemy/essence_spree_variant_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'rails_helper' +require 'alchemy/test_support/essence_shared_examples' +require 'alchemy/test_support/factories/page_factory' +require 'alchemy/test_support/factories/element_factory' +require 'alchemy/test_support/factories/content_factory' +require 'spree/testing_support/factories/variant_factory' + +require_dependency 'alchemy/site' + +RSpec.describe Alchemy::EssenceSpreeVariant, type: :model do + let(:variant) { build(:variant) } + let(:essence) { described_class.new(variant: variant) } + + it_behaves_like 'an essence' do + let(:ingredient_value) { variant } + end + + describe 'ingredient=' do + subject(:ingredient) { essence.variant } + + context 'when String value is only a number' do + let(:value) { '101' } + + before do + essence.ingredient = value + end + + it 'sets variant to an variant instance with that id' do + is_expected.to be_a(Spree::Variant) + expect(ingredient.id).to eq(101) + end + end + + context 'when value is an Spree Variant' do + let(:value) { variant } + + before do + essence.ingredient = value + end + + it 'sets variant to an variant instance with that id' do + is_expected.to be_a(Spree::Variant) + expect(ingredient).to eq(variant) + end + end + + context 'when value is not only a number' do + let(:value) { 'variant1' } + + it do + expect { + essence.ingredient = value + }.to raise_error(ActiveRecord::AssociationTypeMismatch) + end + end + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 45342f9..c6125e0 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -31,6 +31,14 @@ # If you are not using ActiveRecord, you can remove this line. # ActiveRecord::Migration.maintain_test_schema! +require 'shoulda-matchers' +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :active_record + end +end + RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures" @@ -59,4 +67,6 @@ config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") + + config.include FactoryBot::Syntax::Methods end diff --git a/spec/views/alchemy/essences/essence_spree_variant_editor_spec.rb b/spec/views/alchemy/essences/essence_spree_variant_editor_spec.rb new file mode 100644 index 0000000..976ab1f --- /dev/null +++ b/spec/views/alchemy/essences/essence_spree_variant_editor_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'alchemy/essences/_essence_spree_variant_editor' do + let(:content) { Alchemy::Content.new(essence: essence) } + let(:essence) { Alchemy::EssenceSpreeVariant.new } + + before do + view.class.send(:include, Alchemy::Admin::EssencesHelper) + allow(view).to receive(:content_label).and_return(content.name) + end + + it "renders a variant select box" do + render 'alchemy/essences/essence_spree_variant_editor', content: content + expect(rendered).to have_css('select.alchemy_selectbox.full_width') + end + + context 'with a variant related to essence' do + let(:product) { Spree::Product.new(name: 'Chocolate') } + let(:variant) { Spree::Variant.new(id: 1, product: product) } + let(:essence) { Alchemy::EssenceSpreeVariant.new(variant_id: variant.id) } + + before do + expect(Spree::Variant).to receive(:all) { [variant] } + end + + it "selects variant in select box" do + render 'alchemy/essences/essence_spree_variant_editor', content: content + expect(rendered).to have_css('option[value="1"][selected]') + end + end +end